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

时间:2016-06-05 14:44:51

标签: javascript ecmascript-6 this object-literal arrow-functions

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

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

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

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

var c = 100;

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

console.log(a.b.fn());// still 100, why not 5?

我的意思是,如果从词汇语境方面考虑,a.b.fn中的'this'是否应该指向?

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

3 个答案:

答案 0 :(得分:4)

与对象初始化程序所在的this相同。因此,在您的两个示例中,它与this行所在的var a = ...相同。 this永远不会在给定的执行上下文中发生变化,并且对象初始值设定者不会创建新的执行上下文;只有函数和eval这样做。在您的示例中,创建新执行上下文的唯一时间是您调用fn,并且因为fn是箭头函数,它会在执行上下文中关闭this已创建(恰好是示例中的全局执行上下文)。

您在示例代码中看到100 this.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?
})();    

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

如果您希望this内的fnb表达式中引用a.b.fn(),那么您不希望在那里使用箭头功能,您需要正常功能;您获得10a.b.c的值),而不是5a.c的值)。

当然,由于这是一次性对象且fn关闭a,您也可以fn return a.c;return a.b.c; c取决于您想要的System.out.print(ans); System.out.print(" with score: " + smallestAccept[i].getScore() + "\n");

答案 1 :(得分:4)

JavaScript中唯一一个更改范围的表达式是一个函数,从ES6开始,阻塞(请注意,对象文字一个块,尽管它周围有花括号)。这意味着:函数内部的所有内容都在全局范围内。

在全局范围内,this引用全局对象(如果是浏览器,则为window)。唯一改变范围的是箭头函数(是的,它们会改变范围!) - 但它会在词汇上绑定它(这意味着它使用来自外部范围的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;

或者,将b绑定到this

var c = 100;

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

alert(a.b.fn()) // 10;

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

var c = 100;

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

alert(a.b.fn()) // 10;

答案 2 :(得分:1)

另一种思考方式是,没有新的概念,这个"文字内的范围。

另一方面,一个函数会引入一个新的范围。