this 原型链 继承
this 相关问题
1.apply、call 、bind有什么作用,什么区别
apply、call 、bind这三个方法都可以用来改变函数this的指向。
bind
返回一个新函数,并且使函数内部的this为传入的第一个参数
示例:
this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 返回 81
var retrieveX = module.getX;
retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域
// 创建一个新函数,将"this"绑定到module对象
// 新手可能会被全局的x变量和module里的属性x所迷惑
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81
call
和apply
比较相似,在指定this的同时,可以传递参数。唯一区别在于call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组。
示例:
function greet() {
var reply = [this.person, 'Is An Awesome', this.role].join(' ');
console.log(reply);
}
var i = {
person: 'Douglas Crockford', role: 'Javascript Developer'
};
greet.call(i); // Douglas Crockford Is An Awesome Javascript Developer
var numbers = [5, 6, 2, 3, 7];
var max = Math.max.apply(null, numbers);
//max=7
2.以下代码输出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
输出结果:弹窗 John:hi!
3. 下面代码输出什么,为什么
func()
function func() {
alert(this)
}
[Object window],因为直接调用函数func(),this将会被指向window
4.下面代码输出什么
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
点击之后先输出:#document
延时200ms后再输出window
5.下面代码输出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
输出 John,因为call 的第一个参数为指定this的指向,传入john相当于讲func中的this直线了john
6.以下代码有什么问题,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
当bind被调用,$btn被点击的时候,会报错showMsg() undefined。
主要原因是on的回调函数里的this被指向了被点击的元素本身,想要正常执行需要修改成
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
}.bind(this))
},
showMsg: function(){
console.log('饥人谷');
}
}
原型链相关问题
7.有如下代码,解释Person、 prototype、proto、p、constructor之间的关联。
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
console.log('My name is :' + this.name);
}
var p = new Person("若愚")
p.sayName();
构造函数Person,他的prototype里有一个sayName方法。实例化一个Person 赋值给p,p的proto包含了Person.prototype里的方法和属性,以及constructor,constructor被指向Person,因为p是由Person这个构造函数创建的,相当于Person是p的模板。
8.上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
image.png9.对String做扩展,实现如下方式获取字符串中频率最高的字符
String.prototype.getMostOften=function(){
var string = this,
info={},
get_obj,
get_max;
get_obj=(function(){
var obj={};
for(var i = 0;i<string.length;i++){
if (obj[string[i]]) {
obj[string[i]] = obj[string[i]] + 1;
}else{
obj[string[i]] =1;
}
}
return obj;
})(string);
// console.log(obj);
get_max=(function(){
var max = 0;
for(var i in get_obj){
if(get_obj[i]>max){
max = get_obj[i];
}
}
return max;
})();
for(var i in get_obj){
if (get_obj[i]===get_max) {
info[i] = get_obj[i]
}
}
// console.log(max);
return info;
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
10. instanceOf有什么作用?内部逻辑是如何实现的?
instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
示例:
instanceof的内部就是实现了如下内容:
s instanceof Person
//首先
s.__proto__ === Person.prototype //false
//得到结果是false,接下去再比较
s.__proto__.__proto__ ===Person.prototype //true
继承相关问题
11.继承有什么作用?
子类可以不重写父类的属性和方法,直接调用父类的属性和方法。同时可以拓展出自己的方法和属性。
举个例子:
上图中的 s既可以调用自己prototype中的方法,也可以调用父类中prototype中的方法。
12.下面两种写法有什么区别?
//方法1
function People(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){
console.log(this.name);
}
}
var p1 = new People('饥人谷', 2)
//方法2
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){
console.log(this.name);
}
var p1 = new Person('若愚', 27);
通过方法一创建的p1单独拥有一个printnName方法,而通过方法二创建的p1也可以调用printName方法 但是自己不拥有该方法,而是存在与原型链里由Person创建出来的实例公有的方法。
13. Object.create 有什么作用?兼容性如何?
Object.create()
方法使用指定的原型对象和其属性创建了一个新的对象。它接受两个参数,如果当参数只有一个的时候,它的作用和object()方法的行为是相同的。第二个参数的用法
目前支持该方法的浏览器有IE9+,Firefox4+, Safari5+,Opera12+ 和Chrome。也就是说IE 6 7 8 不支持。不过可以使用下面这个方法来hack 实现:
借用new来实现继承
14. hasOwnProperty有什么作用? 如何使用?
使用hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。
示例:
function Person(){
}
Person.prototype={
name:'Jack',
age:22,
sex:'male',
sayName:function(){
console.log(this.name)
}
}
var p1 = new Person();
var p2 = new Person();
p1.name = 'Greg';
console.log(p1.name); //Greg ---来自实例
console.log(p1.hasOwnProperty('name')); //true
console.log(p2.name); //Jack ---来自原型
console.log(p2.hasOwnProperty('name'));//false
delete p1.name;
console.log(p1.name); //Jack ---来自原型
console.log(p1.hasOwnProperty('name'));//false
15.如下代码中call的作用是什么?
function Person(name, sex){
this.name = name;
this.sex = sex;
}
function Male(name, sex, age){
Person.call(this, name, sex); //这里的 call 有什么作用
this.age = age;
}
继承Person 的属性
16.补全代码,实现继承
function Person(name, sex){
// todo ...
}
Person.prototype.getName = function(){
// todo ...
};
function Male(name, sex, age){
//todo ...
}
//todo ...
Male.prototype.getAge = function(){
//todo ...
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
实现继承:
function Person(name, sex) {
this.name= name;
this.sex = sex;
}
Person.prototype.printName = function() {
console.log(this.name);
};
function Male(name, sex, age) {
Person.call(this,name,sex);
this.age= age;
}
Male.prototype =Object.create(Person.prototype);
Male.prototype.constructor = Male;
Male.prototype.getAge = function() {
console.log(this.age);
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();