为什么箭头函数的 'this' 在嵌套对象字面量中没有变化?
why doesn't 'this' of an arrow function change inside an nested object literal?
我发现在嵌套对象文字中使用箭头函数时,'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'不应该指向a吗?
为什么,无论对象嵌套了多少层,所有 'this' 个实例都指向 window 还是全局?
它与this
对象初始化器所在的位置相同。因此,在您的两个示例中,它与您的 var a = ...
行所在的 this
相同。 this
在给定的执行上下文中永远不会改变,并且对象初始化器不会创建新的执行上下文;只有函数和 eval
可以做到这一点。在您的示例中,唯一一次创建新的执行上下文是在您调用 fn
时,并且由于 fn
是一个箭头函数,它会关闭执行上下文中的 this
已创建(恰好是您示例中的全局执行上下文)。
您在示例代码中看到 this.c
的 100
的原因是 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
将不再是全局变量(并且因此 属性 的全局对象)。
如果你想让 fn
中的 this
引用表达式 a.b.fn()
中的 b
,那么你不需要箭头函数,你需要一个正常功能;你会得到 10
(a.b.c
的值),而不是 5
(a.c
的值)。
当然,由于这是一次性对象,fn
比 a
关闭,您也可以将 fn
的主体设为 return a.c;
或 return a.b.c;
取决于你想要哪个 c
。
另一种思考方式是,文字中没有新的 "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;
或者,将 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;
我发现在嵌套对象文字中使用箭头函数时,'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'不应该指向a吗?
为什么,无论对象嵌套了多少层,所有 'this' 个实例都指向 window 还是全局?
它与this
对象初始化器所在的位置相同。因此,在您的两个示例中,它与您的 var a = ...
行所在的 this
相同。 this
在给定的执行上下文中永远不会改变,并且对象初始化器不会创建新的执行上下文;只有函数和 eval
可以做到这一点。在您的示例中,唯一一次创建新的执行上下文是在您调用 fn
时,并且由于 fn
是一个箭头函数,它会关闭执行上下文中的 this
已创建(恰好是您示例中的全局执行上下文)。
您在示例代码中看到 this.c
的 100
的原因是 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
将不再是全局变量(并且因此 属性 的全局对象)。
如果你想让 fn
中的 this
引用表达式 a.b.fn()
中的 b
,那么你不需要箭头函数,你需要一个正常功能;你会得到 10
(a.b.c
的值),而不是 5
(a.c
的值)。
当然,由于这是一次性对象,fn
比 a
关闭,您也可以将 fn
的主体设为 return a.c;
或 return a.b.c;
取决于你想要哪个 c
。
另一种思考方式是,文字中没有新的 "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;
或者,将 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;