我发现在嵌套对象文字中使用箭头函数时,'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'实例都指向窗口还是全局?
答案 0 :(得分:4)
与对象初始化程序所在的this
相同。因此,在您的两个示例中,它与this
行所在的var a = ...
相同。 this
永远不会在给定的执行上下文中发生变化,并且对象初始值设定者不会创建新的执行上下文;只有函数和eval
这样做。在您的示例中,创建新执行上下文的唯一时间是您调用fn
,并且因为fn
是箭头函数,它会在执行上下文中关闭this
已创建(恰好是示例中的全局执行上下文)。
您在示例代码中看到100
this.c
的原因是全局范围内的this
(在松散模式下)是指全局对象,var
个变量在全局范围内成为全局对象的属性,因此this.c
是c
全局变量。
如果您将所有代码放在作用域函数中,如下所示:
(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
内的fn
在b
表达式中引用a.b.fn()
,那么您不希望在那里使用箭头功能,您需要正常功能;您获得10
(a.b.c
的值),而不是5
(a.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)
另一种思考方式是,没有新的概念,这个"文字内的范围。
另一方面,一个函数会引入一个新的范围。