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

时间:2016-03-18 05:28:04

标签: javascript this

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”指的是Object“b”。但为什么第二个会记录相同的结果呢?我认为“this”应该指向全局执行上下文。第三个,似乎逗号运算符影响执行上下文。

2 个答案:

答案 0 :(得分:17)

你真的有一个漂亮的角落案例! 我接受了它:

  • 第一个是直截了当的。只是一个标准的电话。 '。' operator允许您将函数设置b作为执行上下文调用。
  • 第二个是完全相同的事情:parens完全是可选的,解释器将其中的表达式视为绑定函数调用。实际上我并没有想到这一点:我认为解释器会将this重置为全局对象,但实际上它会保持链接。可能只是这样“随意”的语言用户不会惊慌失措。
  • 第三个更标准(至少对于那些生活在JavaScript领域的人来说):只要你的函数在表达式中传递(在这种情况下由,运算符传递){{1}绑定到执行上下文的值将丢失。因此,您实际上是在传递函数本身,而不再与声明对象绑定。因此,当您调用它时,this将作为全局对象传入。

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

非常好的例子!

答案 1 :(得分:15)

请参阅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
  

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

其他间接通话格式如下

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