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'实例都指向窗口还是全局?
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)
或者,绑定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;
Run Code Online (Sandbox Code Playgroud)
或者,要绑定this到b,您还可以使用常规函数而不是箭头函数:
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)
它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?
})();
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您的需要。