回调函数的this问题

299 阅读2分钟

之前一直对回调函数的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变为可控的呢。答案是使用箭头函数。下面是个人看过的某大佬写的比较好理解的文章。

zhuanlan.zhihu.com/p/38997000

箭头函数的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。