首先看一个例子:
const obj = {
aaa() {
setTimeout(function () {
console.log(this);
}, 0);
setTimeout(() => {
console.log(this);
}, 0);
},
};
obj.aaa();
结果:
第一个setTimeout函数里面写的普通函数打印的this指向的是window,第二个setTimeout里面写的箭头函数指向的是obj,这是为什么呢?
原因:setTimeout中的普通函数的this指向的是window
setTimeout中的function你可以理解为callback,
function callback(){}
setTimeout(callback,2000);
setTimout中的执行伪代码可以理解为:
function setTimeout(fn,delay);
可以看到,他是直接调用fn(),前面没有给任何对象绑定在一起,所以根据JavaScript的规则,它属于默认绑定,自然就是window了。
上例中第一个setTimeout写法相当于:
function fn() {
console.log(this);
}
const obj = {
aaa() {
setTimeout(fn, 0);
},
};
obj.aaa();
箭头函数的中this:是最近作用域中的this。也就是说往外层作用域中,一层一层往外找,直到有this的定义出现。
上例中箭头函数中的this往外找,发现了函数aaa,aaa中的this指向的是obj,所以第二个setTimeout中箭头函数中指向的this是obj
再看一个复杂的例子:
const obj = {
aaa() {
setTimeout(function () { // 起名为 1
setTimeout(function () { // 起名为 1.1
console.log(this); // window
}, 0);
setTimeout(() => { // 起名为 1.2
console.log(this); // window
}, 0);
}, 0);
setTimeout(() => { // 起名为 2
setTimeout(function () { // 起名为 2.1
console.log(this); // window
}, 0);
setTimeout(() => { // 起名为 2.2
console.log(this); // obj
}, 0);
}, 0);
},
};
obj.aaa();
为了方便,上面的settimeout函数我起了名字
解释:settimeout中的普通函数的this指向的都是window,所以 1.1 和 2.1 中的this指向window是毫无疑问的。然后通过最开始的例子我们知道 1 的this指向的是window,所以1.2 中的this往上找,找到了 1 中的this,指向的window,所以 1.2 中的this指向的是window。通过最开始的例子我们也知道, 2 中的this指向的是obj,那么 2.2 中的this往上找,找到了 2 中的this,指向的obj,所以 2.2 中的this指向的是obj。