为什么箭头函数的'this'不会在嵌套对象文字内部发生变化?

jt-*_*ang 7 javascript this object-literal ecmascript-6 arrow-functions

我发现'this'关键字似乎始终指向global在嵌套对象文字中使用箭头函数.

根据其他问题,下面的代码片段可以解释为箭头函数的'this'在词汇上下文中定义.

var c = 100;
var a = {c:5 , fn: () => {return this.c;} };
console.log(a.c); //100
Run Code Online (Sandbox Code Playgroud)

但是,我无法理解以下代码(嵌套对象文字):

var c = 100;

var a = {
    c: 5,
    b: {
        c: 10,
        fn: ()=> {return this.c;}
    }
}

console.log(a.b.fn());// still 100, why not 5?
Run Code Online (Sandbox Code Playgroud)

我的意思是,如果从词汇语境方面考虑,不应该在abfn中的'this'指向一个?

为什么,无论对象嵌套多少级别,所有'this'实例都指向窗口还是全局?

Joh*_* H. 6

JavaScript 中唯一改变作用域的表达式是函数,并且在 ES6 中是块(请注意,对象字面量不是块,尽管它周围有花括号)。这意味着:不在函数内的所有内容都在全局范围内。

在全局范围内,this指的是全局对象(window在浏览器的情况下)。唯一改变作用域的是箭头函数(是的,它们确实改变了作用域!) - 但它在词法上绑定了 this (这意味着,它使用this来自外部作用域的 ),所以它仍然是全局对象。

如果要this引用a对象,请使用 IIFE 而不是对象文字:

var c = 100;

var a = new function () {
    this.c = 5;
    this.b = {
        c: 10,
        fn: ()=> {return this.c;}
    }
}()

alert(a.b.fn()) // 5;
Run Code Online (Sandbox Code Playgroud)

或者,绑定bthis

var c = 100;

var a = {
    c : 5,
    b : new function () {
        this.c = 10;
        this.fn = ()=> {return this.c;}
    }()
}

alert(a.b.fn()) // 10;
Run Code Online (Sandbox Code Playgroud)

或者,要绑定thisb,您还可以使用常规函数而不是箭头函数:

var c = 100;

var a = {
    c: 5,
    b: {
        c: 10,
        fn: function () {return this.c;}
    }
}

alert(a.b.fn()) // 10;
Run Code Online (Sandbox Code Playgroud)

  • 当心将 *scope* 和 *execution context* 混为一谈。它们是相关的,但非常不同。`this` 与执行上下文有关,而不是范围。 (4认同)

T.J*_*der 5

this与对象初始化程序所在的位置相同。因此,在您的两个示例中,它都与行this所在位置相同var a = ...this从不在给定的执行上下文中更改,并且对象初始化程序不会创建新的执行上下文;只有功能并eval做到这一点。在您的示例中,只有在调用时才创建新的执行上下文fn,并且由于它fn是一个箭头函数,因此this它将在创建它的执行上下文中关闭(在您的示例中恰好是全局执行上下文) 。

你看到的原因100this.c在您的示例代码是this在全局范围内(以松散模式)指的是全局对象,并var在全局范围内变量成为全局对象的属性,因此this.cc全局变量。

如果将所有这些代码都放在作用域函数中,如下所示:

(function() { // Or `(() => {`, doesn't matter in this case
    var c = 100;

    var a = {
        c: 5,
        b: {
            c: 10,
            fn: ()=> {return this.c;}
        }
    }
    console.log(a.b.fn());// still 100, why not 5?
})();    
Run Code Online (Sandbox Code Playgroud)

... this.c将是undefined,因为尽管this仍将引用全局对象,但c它将不再是全局变量(因此也不是全局对象的属性)。

如果要this在表达式中fn引用内部,那么您不希望在其中使用箭头功能,而需要普通功能;您会得到的值,而不是的值。ba.b.fn()10a.b.c5a.c

当然,由于这是一个一次性对象并fn关闭a,因此您也可以只制作fn主体return a.c;return a.b.c;根据c您的需要。