逗号运算符是否影响 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.cProperty 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的值为1global 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