逗号运算符会影响 Javascript 中的执行上下文吗?

IT技术 javascript this
2021-03-15 06:27:04
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”应该指向全局执行上下文。第三个,似乎逗号运算符会影响执行上下文。

2个回答

你真的有一个很好的角落案例!我的看法:

  • 第一个很简单。只是一个标准的电话。这 '。' 运算符允许您调用函数设置b作为执行上下文。
  • 第二个完全相同:括号是完全可选的,解释器将其中的表达式视为绑定函数调用。实际上我没想到这一点:我认为解释器会重置this为全局对象,但实际上它保持链接。可能只是这样“随意”的语言用户不会惊慌失措。
  • 第三个更标准(至少对于那些生活在 JavaScript 领域的人来说):只要你的函数在表达式中传递(在这种情况下由,运算符),this值就会丢失。这是因为b.cProperty Reference(规范中的深兔子洞细节,这里,由 TJCrowder 提供)。因此,您实际上是在传递函数本身,不再绑定到声明对象。因此,当您调用它时,它将this作为全局对象传入。

这样看:(object.function)()被简单化为object.function(),因为封闭的括号是完全可选的;(0, object.function)()被解析为(expression yielding a function)()将失去对 的object绑定this,因为函数已经解除绑定。

真的很好的例子!

好的更新,尽管“只要您的函数在表达式中传递(在这种情况下由 , 运算符),绑定到执行上下文的 this 值就会丢失”仍然不正确:我们没有使用this,我们正在使用b,并且最终没有使用对象引用的机制是因为属性引用没有直接用于进行调用。§12.3.4.1 中的详细信息
2021-05-12 06:27:04

请参阅Indirect eval call,其中提供了有关它的更多详细信息。

 (     0        ,          b.c   )        (  )
     |____|   |_____|    |_____|
     Literal  Operator   Identifier

     |_________________________|
     Expression

  |______________________________|
  PrimaryExpression

  |______________________________|        |________|
  MemberExpression                        Arguments

  |________________________________________________|

  CallExpression

我们可以用逗号时尚间接调用b.c,这将迫使它在执行global context,valuea1global context

结果(b.c = b.c)()也是1

> (b.c = b.c)()
  1

就 ECMAScript 而言,这是因为 - 逗号运算符((0, b.c)示例中)和=运算符((b.c = b.c)示例中)都对其操作数执行 GetValue。

其他间接调用格式如下

> (b.c, b.c)()
  1 
> (1? b.c: 0)()
  1
> (__ = b.c)()
  1