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