本文详解JavaScript中this关键字的四种常见指向场景:全局函数调用指向全局对象,构造函数中指向新实例,通过call或apply改变指向,以及作为对象方法调用时指向该对象。结合代码示例分析易错点,帮助理解this的动态绑定机制。
JavaScript this指向详解
此前在面试中涉及this相关话题时,面试官指出我的理解存在偏差。回顾相关书籍与博客并经过实际测试后,我确认之前的认知确实有误。
全局环境中的this
1. 全局变量环境下的this
这是最常见的情况。当在普通函数中直接调用this时,在非严格模式下,this通常指向全局对象(在浏览器中为window)。
var value="0"; function mei(){
var value="1";
console.log(this.value); //0 console.log(value); //1 }
mei();
代码输出0,正是因为此时this指向全局对象,访问的是全局变量value。
构造函数中的this
2. 构造函数中的this
这是较为熟悉的用法。在构造函数内部使用this时,当通过new关键字创建新对象后,this便指向这个新创建的实例对象。
var value="window"; function mei(){
this.value=1;
this.show=function(){
console.log(this.value)
}
} var m=new mei();
console.log(m.value); //1 m.show(); //1
输出结果为1而非window,这表明在构造函数语境下,this已正确指向新对象,而非全局变量。
call与apply改变this指向
3. 使用call和apply改变this指向
此处引用之前关于call和apply博客中的示例代码进行说明。
var p="456";
function f1(){
this.p="123";
}
function f2() {
console.log(this.p);
}
f2(); //456 f2.call(f1()); //123 f2.apply(f1()); //123
第一行输出456,此时this指向全局对象;后续输出123,是因为使用call或apply后,f2中的this被显式绑定到了f1实例上,而f1实例的p属性值为123。具体机制可参考相关博文详解。
对象方法调用中的this
4. 函数作为对象方法调用(此处曾出错)
面试时要求编写包含多个方法的对象,我错误地定义了一个全局变量,并在对象方法中尝试用this调用该变量。面试官质疑此时this的值,我起初误以为只有new或call/apply才会改变this指向,因此回答可能是window。面试官指出错误后,我通过测试验证了自己的误解。
var value="father"; function mei(){}
mei.value="child";
mei.get=function(){console.log(this.value)};
mei.show=function(){console.log(value)};
mei.get(); //child mei.show(); //father
由于get方法是作为mei对象的方法被调用的,因此该处的this指向mei对象,故输出child。
对于show方法的输出father,我的理解是:show指向的函数定义在全局环境中。由于作用域链查找机制,在show函数内部未找到value属性时,会向上层作用域(即全局环境)查找,从而找到全局变量value。若此理解有误,欢迎指正。