JavaScript中如何确定「this」的值
JavaScript中的this指函数上下文(function context),在函数被调用时自动创建,由函数的调用方式决定。也就是说函数的调用方式决定了该函数中this的值,this叫函数调用上下文似乎更准确一些。
「this」的值由函数的调用方式决定
在JavaScript中,函数有4种调用方式,this值也就对应了4种值:
- 直接以函数形式调用,
this的值为undefined(严格模式)或者global/workerGlobal(非严格模式) - 作为对象方法调用,
this的值为该对象 - 使用new操作符调用,
this的值为新创建的对象 - call()和apply()显式指定
this的值,this的值为指定的值
两个特例
this值的确定除了由函数调用方式决定的通用法则外,还有两个特例:事件处理程序和定时器回调中的this值。
事件处理程序
事件处理程序中,this值为注册事件处理程序的元素对象,通过查看调用栈,事件处理程序是以函数的形式调用的,如下图所示。

从调用方式来看,this值应该是undefined,但是这在事件处理程序中没有意义,而this值是注册事件程序所在的元素对象才有实际意义,也是在实际编程中通常期望的值。
定时器中的「this」
在定时器(setTimeout和setInterval)和requestAnimationFrame的回调中,无论是否使用严格模式,this值一律是global或者workerGlobal。
这是不合理的,这个问题也引起了激烈的讨论。
ES6中的「词法this」
ES6引入了箭头函数,它的一个重要特征是该函数没有this对象,而是通过词法作用域链获取this。
「this」与作用域
对于普通函数而言,函数被调用时,在该函数的作用域中就会自动创建this对象,每个函数中都会有一个局部变量this,所以无法直接通过this标识符获取到外层函数的this值。
要获取外层函数中的this通常通过设置一个临时变量保存外层函数的this然后通过词法作用域获取,或者使用bind方法绑定外层函数的this。
1
2
3
4
5
6
7
8
9
10
11
function outer() {
const context = this;
function inner() {
// 可以使用context访问到outer中的this
}
innerBindThis = function() {
// this为函数outer中的this
}.bind(this);
}
但是this和所有其他标识符一样,遵循词法作用域规则。这也是ES6中的箭头函数没有创建this对象时访问到外层函数的this的原因。
绑定「this」
在实际编程中会遇到需要某个函数以特定的上下文运行的情景,这时可以使用函数的bind方法创建一个绑定了this对象的函数。
绑定this常在事件处理程序中使用。
1
2
3
4
5
6
7
8
9
10
const obj = {
count: 0,
increment() {
this.count++;
}
};
const btn = document.querySelector('.btn');
btn.addEventListener('click', obj.increment); // => this为btn对象,出错
btn.addEventListener('click', obj.increment.bind(obj)); // => 绑定this为obj
小结
JavaScript中,this对象在函数被调用时自动创建,由函数的调用方式决定。但是有两个特例:事件处理程序中,this的值是注册事件程序的元素对象;定时器和requestAnimationFrame的回调中,this的值是global或workerGlobal,无论是否使用严格模式。
this和任何标识符一样,遵循词法作用域规则,因为普通函数在被调用时会自动创建this对象,每个函数中都有一个局部变量this,所以无法直接通过外层函数中的this值。而ES6中的箭头函数不会创建this局部变量,可以直接获取到外层函数中的this。
当需要访问外层函数中的this时,可以使用箭头函数、使用临时变量保存外层函数的this然后通过该临时变量访问或者使用bind方法绑定外层函数的this。绑定this还通常用于某个函数需要使用某个特定对象作为上下文的情况。