逗号运算符是否影响 Javascript 中的执行上下文?
Does the comma operator influence the execution context in Javascript?
var a = 1;
var b = {
a : 2,
c : function () {
console.log(this.a);
}
};
b.c(); // logs 2
(b.c)(); // logs 2
(0, b.c)(); // logs 1
第一个是可以理解的,因为"this"指向对象"b"。但是为什么第二个记录相同的结果呢?我认为 "this" 应该指向全局执行上下文。第三个,逗号运算符似乎影响了执行上下文。
你那里真的有一个很好的角落案例!
我的看法:
- 第一个很简单。只是一个标准的电话。这 '。'运算符允许您调用函数设置
b
作为执行上下文。
- 第二个是完全相同的东西:括号完全是可选的,解释器将其中的表达式视为绑定函数调用。其实我没想到这一点:我以为解释器会重置
this
到全局对象,但实际上它保持链接。可能只是为了 "casual" 语言用户不会惊慌失措。
- 第三个更标准(至少对于生活在 JavaScript 土地上的人来说):只要你的函数在表达式中传递(在本例中是
,
运算符) this
值丢失。这是因为 b.c
是 Property Reference
(规范中的深兔子洞细节,here,由 T.J.Crowder 提供)。因此,您实际上是在传递函数本身,不再绑定到声明对象。因此,当您调用它时,this
将作为全局对象传入。
这样看:(object.function)()
被简单化为 object.function()
,因为封闭的括号是完全可选的; (0, object.function)()
被解析为 (expression yielding a function)()
,它将失去 object
绑定到 this
,因为函数已经解除绑定。
很好的例子!
参考Indirect eval call,其中提供了更多详细信息。
( 0 , b.c ) ( )
|____| |_____| |_____|
Literal Operator Identifier
|_________________________|
Expression
|______________________________|
PrimaryExpression
|______________________________| |________|
MemberExpression Arguments
|________________________________________________|
CallExpression
我们可以使用逗号运算符来间接调用b.c
,这将强制它在global context
中执行,a
的值为1
在 global context
.
(b.c = b.c)()
的结果也是1
> (b.c = b.c)()
1
Speaking in terms of ECMAScript, this is because both — comma operator (in (0, b.c)
example) and =
operator (in (b.c = b.c)
example) perform GetValue on its operands.
其他间接调用格式如下
> (b.c, b.c)()
1
> (1? b.c: 0)()
1
> (__ = b.c)()
1
var a = 1;
var b = {
a : 2,
c : function () {
console.log(this.a);
}
};
b.c(); // logs 2
(b.c)(); // logs 2
(0, b.c)(); // logs 1
第一个是可以理解的,因为"this"指向对象"b"。但是为什么第二个记录相同的结果呢?我认为 "this" 应该指向全局执行上下文。第三个,逗号运算符似乎影响了执行上下文。
你那里真的有一个很好的角落案例! 我的看法:
- 第一个很简单。只是一个标准的电话。这 '。'运算符允许您调用函数设置
b
作为执行上下文。 - 第二个是完全相同的东西:括号完全是可选的,解释器将其中的表达式视为绑定函数调用。其实我没想到这一点:我以为解释器会重置
this
到全局对象,但实际上它保持链接。可能只是为了 "casual" 语言用户不会惊慌失措。 - 第三个更标准(至少对于生活在 JavaScript 土地上的人来说):只要你的函数在表达式中传递(在本例中是
,
运算符)this
值丢失。这是因为b.c
是Property Reference
(规范中的深兔子洞细节,here,由 T.J.Crowder 提供)。因此,您实际上是在传递函数本身,不再绑定到声明对象。因此,当您调用它时,this
将作为全局对象传入。
这样看:(object.function)()
被简单化为 object.function()
,因为封闭的括号是完全可选的; (0, object.function)()
被解析为 (expression yielding a function)()
,它将失去 object
绑定到 this
,因为函数已经解除绑定。
很好的例子!
参考Indirect eval call,其中提供了更多详细信息。
( 0 , b.c ) ( )
|____| |_____| |_____|
Literal Operator Identifier
|_________________________|
Expression
|______________________________|
PrimaryExpression
|______________________________| |________|
MemberExpression Arguments
|________________________________________________|
CallExpression
我们可以使用逗号运算符来间接调用b.c
,这将强制它在global context
中执行,a
的值为1
在 global context
.
(b.c = b.c)()
的结果也是1
> (b.c = b.c)()
1
Speaking in terms of ECMAScript, this is because both — comma operator (in
(0, b.c)
example) and=
operator (in(b.c = b.c)
example) perform GetValue on its operands.
其他间接调用格式如下
> (b.c, b.c)()
1
> (1? b.c: 0)()
1
> (__ = b.c)()
1