JavaScript 中 this 是如何工作的?
废话
经历了一个非常紧急的迭代,加班加到怀疑人生,收拾心情,重新捡起 blog,争取做一个更博小能手。
之前印象
JS 中 this 的工作原理,是自古以来的必考点。有一句经典的话,谁最终调用函数,this 指向谁。这句话听起来好像很简单,但是结合各种场景,this 分别是如何指向的呢? ##具体场景
全局作用域
// global scope
foo = 'abc';
alert(foo); // abc
this.foo = 'def';
alert(foo); // def
在全局作用域/全局环境(global scope/global context)中,this 指向的就是全局变量 在浏览器中指的就是 window,在 node.js 中就是 global。
函数中
var boat = {
size: 'normal',
boatInfo: function() {
alert(this === boat);
alert(this.size);
}
};
boat.boatInfo(); // true, 'normal'
var bigBoat = {
size: 'big'
};
bigBoat.boatInfo = boat.boatInfo;
bigBoat.boatInfo(); // false, 'big'
从上述代码中可以看,同样是 boatInfo()打印出来确实不同的值,这是因为在任何函数中,this 的指向都不是静态的(static),它总是在你调用一个函数,但尚未执行函数内部代码前被指定,是由调用函数的父作用域提供的,这就是那句经典的话的来源。 接着上面在深一级
var boatInfo = bigBoat.boatInfo;
boatInfo();//false,undefined
这就是因为执行 boatInfo 函数的父作用域是全局,所以 this 指向了全局。
构造函数中
当使用 new 关键字去执行构造函数时,构造函数中的 this 指向的的就是新建的那个对象实例。
var thisArg;
function Ctor(){
thisArg = this
}
var instance = new Ctor()
console.log(thisArg === instance) //true
箭头函数
当使用 es6 箭头函数时,默认绑定外层第一个不是箭头函数的 this,并且 this 一旦绑定,就不会被 call,apply,bind 改变。
var obj = {
foo:()=>{
console.log(this)
}
}
obj.foo()//window|global
总结
this 的指向判断可以遵循一个方法,在非箭头函数下,通过()左边的对象,如果是一个引用,那么 this 就指向该对象,如果没有,就指向全局,如果有箭头函数存在,就绑定了外层第一个不是箭头函数的 this。