JS中this的指向以及call、apply的作用
在具体的实际应用中,this的指向无法在函数定义时确定,而是在函数执行的时候才确定的,根据执行时的环境大致可以分为以下3种:
1、当函数作为普通函数调用时,this指向全局对象
2、当函数作为对象的方法调用时,this指向该对象
3、当函数作为构造器调用时,this指向新创建的对象
示例一:
window.name='myname';
functiongetName(){
console.log(this.name);
}
getName();//输出myname
示例二:
varboy={
name:'Bob',
getName:function(){
console.log(this.name);
}
}
boy.getName();//输出Bob
示例三:
functionBoy(name){
this.name=name;
}
varboy1=newBoy('Bob');
console.log(boy1.name);//输出Bob
对于示例三,还有一种特殊情况,就是当构造函数通过"return"返回的是一个对象的时候,此次运算的最终结果返回的就是这个对象,而不是新创建的对象,因此this在这种情况下并没有什么用。
示例四:
functionBoy(name){
this.name=name;
return{//返回一个对象
name:'Jack'
}
}
varboy1=newBoy('Bob');
console.log(boy1.name);//输出Jack
示例五:
functionBoy(name){
this.name=name;
return1;//返回非对象
}
varboy1=newBoy('Bob');
console.log(boy1.name);//输出Bob
call和apply的作用
apply接受两个参数,第一个参数指定了函数体内this的指向,第二个参数是一个数组或类数组,用于传递被调用函数的参数列表。
示例一:
functiongetInfo(){
console.log(this.name+'like'+arguments[0]+'and'+arguments[1]);
}
varboy1={
name:'Bob',
age:12
}
getInfo.apply(boy1,['sing','swimming']);//输出Boblikesingandswimming
call传入参数的数量是不固定的,跟apply相同的是,第一个参数也是用于指定函数体内this的指向,从第二个参数开始往后,每个参数被依次传入被调用函数。
示例二:
functiongetInfo(){
console.log(this.name+'like'+arguments[0]+'and'+arguments[1]);
}
varboy1={
name:'Bob',
age:12
}
getInfo.call(boy1,'sing','shopping');//输出Boblikesingandshopping
此外,大部分高级浏览器还实现了bind方法,它与call和apply的区别在于bind只是改变函数内部this的指向,但不会立即执行,你需要显示调用它。
示例三:模拟浏览器的bind方法
Function.prototype.bind=function(obj){
varself=this;
returnfunction(){
returnself.apply(obj,arguments);
}
};
varobj={
name:'Bob',
age:12
};
varfunc=function(){
console.log(this.name+'like'+arguments[0]+'and'+arguments[1]);
}.bind(obj);
func('sing','shopping');
丢失的this
在某些情况下会丢失this的指向,此时,我们就需要借助call、apply和bind来改变this的指向问题。
示例一:当"getName"方法作为"boy"对象的属性调用时,this指向"boy"对象,当另外一个变量引用"getName"方法时,因为它是作为普通函数调用,所以this指向全局对象window
varboy={
name:'Bob',
getName:function(){
console.log(this.name);
}
}
boy.getName();//输出Bob
vargetBoyName=boy.getName;
getBoyName();//输出undefined
示例二:即使在函数内部定义的函数,如果它作为普通对象调用,this同样指向window对象
varboy1={
name:'Bob',
age:12,
getInfo:function(){
console.log(this.name);
functiongetAge(){
console.log(this.age);
}
getAge();
}
}
boy1.getInfo();//Bob
//undefined