之前一直对回调函数的this指向,今天在实现Promise时,被各种回调函数和this给搞麻了。在这里写下之前忽略的问题,以警示自己,后续会陆续补充。
基本函数的this指向
this永远指向他的调用者(动态)
这句话算是老生常谈了,这里只举例最容易被忽略的情况——当函数直接被调用时,无论在哪,均指向window对象。这里说的函数直接调用,是指函数前面不带有[ . ]号的调用。
console.log('************************* 函数直接调用的this指向 ************************* ');
function a() {
console.log(this);
};
const b = {
b: function () {
a();
}
}
b.b()
function B() {
a();
}
// result:
// Window { window: Window, self: Window, document: document, name: '', location: Location, … }
new B();
// result:
// Window { window: Window, self: Window, document: document, name: '', location: Location, … }
之前看的资料里面,总是举函数在全局作用域中直接调用的例子,结果让我误以为函数直接调用需要看被调用时所在作用域的this。于是举了在别的函数中调用的例子。得出真实情况是,无论在哪直接调用函数,其实都是被window对象隐式调用。
回调函数的this指向
回调函数的理解
回调函数本质是在将函数作为参数传入函数内,然后在函数体的恰当时机调用。其实这一过程和普通函数的定义和调用类似。
function A(exe){
// this.exe = exe;
// this.exe();
exe();
}
new A(function(){
console.log(this);
})
// 类似于
const exe = function(){console.log(this)};
function A(){
exe();
}
new A();
回调函数的this指向
和基本函数的this指向一样,回调函数的this指向取决被谁调用。
function A(exe) {
this.exe = exe;
this.exe();
exe();
}
new A(function () { console.log(this); })
// result:
// A {exe: ƒ}
// Window { window: Window, self: Window, document: document, name: '', location: Location, … }
如何改变回调函数的this指向
在setTimeout(f)中的回调函数f的this指向为window,原因就在于f函数在函数体调用时是直接调用,前面没有带[ . ]号。那么如何将回调函数的this变为可控的呢。答案是使用箭头函数。下面是个人看过的某大佬写的比较好理解的文章。
箭头函数的this和我们定义函数的地方有关,而和使用函数的地方无关,利用这一点,我们可以决定回调函数的this指向。 将上面的代码改写
function A(exe) {
this.exe = exe;
this.exe();
exe();
}
new A(() => { console.log(this); })
// result:
// Window { window: Window, self: Window, document: document, name: '', location: Location, … }
// Window { window: Window, self: Window, document: document, name: '', location: Location, … }
传入的箭头函数的this指向window,因此无论在哪使用this都指向的是window。