JavaScript 语法:(0, fn)(args)。

38

我只是在检查Google的JavaScript代码时发现了这种语法:

var myVar = function...;
(0, myVar)(args);

你知道这个语法的含义吗?我找不出以下两者的区别:

(0, myVar)(args); myVar(args);

为了举一个具体的例子,我们有:

_.x3 = function (a, b) {
    return new _.q3(20 * b.x + a.B.B.x, 20 * b.y + a.B.B.y)
};

之后

this.ta = new _.s3((0, _.x3)(this.fa, this.B.B), 0);

可能是 javascript 逗号操作符 的重复问题。 - Otto Allmendinger
出于好奇,你能否发布更多的上下文信息,以便了解这个问题的背景? - Austin
我正在检查 https://www.google.fr/xjs/_/js/s/sy46,zr/rt=j/ver=-wnZQEUYm8E.en_US./d=0/rs=AItRSTNMBUOhWluxPqsKFY9CVTnMlxNz6w 的代码。 - korko
@korko,我编辑了我的答案,如果有帮助的话。 - David G
2
可能是为什么谷歌主页使用(0,func)(args)语法?的重复问题。 - Has QUIT--Anony-Mousse
这使得问题从两端看起来是重复的。在Rails术语中,您会收到一个堆栈级别太深的错误。 - argentum47
2个回答

83

我曾经有同样的问题,后来找到了答案,如下所示:

实际上是为了

(0, foo.fn)();

要记住,在JavaScript中,当调用foo.fn()时,fn内部的this会被绑定到foo。如果你使用了

var g = foo.fn;
g();

然后当上面调用 g 时,this 将绑定到全局对象 (window 在 Web 浏览器的上下文中)。

那么你是否需要像上面那样定义 g?你可以做类似以下的事情吗:

(foo.fn)();

答案是否定的。JavaScript会将它视为与foo.fn();相同,因为它只是带有可以省略的多余的()foo.fn

但有一种方法可以解决这个问题,那就是使用逗号运算符,Mozilla指出:

逗号运算符按从左到右的顺序评估其每个操作数,并返回最后一个操作数的值。

因此使用:

(0, foo.fn)();

(0, foo.fn)将被评估为对函数的引用,就像上面的g一样,然后调用该函数。然后,this未绑定到foo,而是绑定到全局对象。

因此,以这种方式编写的代码是为了“切断绑定”。

示例:

var foo = { 
              fullName: "Peter", 
              sayName:  function() { console.log("My name is", this.fullName); } 
          };

window.fullName = "Shiny";

foo.sayName();       // My name is Peter

(foo.sayName)();     // My name is Peter

(0, foo.sayName)();  // My name is Shiny

现在,为什么会有一些代码想要解除绑定呢?我读到过这样一种情况,即如果我们有一个函数:

function foo() {
  // using `this` here
}

那么this将指向全局对象。但是,如果foo()与其他函数和值一起打包成一个模块,则在使用函数调用时

someModule.foo();

此时,this已经绑定到someModule,并且改变了foo()的行为。为了保持foo()的原始状态,我们解除了绑定关系,这样在foo()内部,this就像以前一样绑定到全局对象。


5
JavaScript像往常一样可预测:'D - Robo Robok
1
表达式可能是任何内容,返回函数(foo.sayName || 0)()的结果相同,(() => foo.sayName)()()也同样。 - webduvet

5
这个语法使用逗号操作符 ,。它会评估所有的操作数并返回最后一个的值。在这种情况下,0 只是作为一个占位符,所以 (0, function() {}) 将返回 (function() {})。当它被评估后,(args) 部分调用函数并给它传递参数。
编辑后的内容:
使用这种编码风格的原因是为了能够快速或在一行上执行代码。以下是一个例子:
var a = 0,
    b = 1,
    c;

c = ( a++, b++, a + 2 ); // a is added, b is added, and a is added then returned

a; // 1
b; // 2
c; // 3

是的,绝对是一个很好的理由,但是…0意味着什么都没有。除了只有fn()外,是否有一些保护、去作用化或其他东西可以给(0, fn)()赋予含义? - korko
抱歉,我想不出任何理由。不过,如果 Google 在使用它,那肯定是有原因的。 - David G
只是一个小澄清:(0, function() {})的评估与(function() {})的评估相同,仅仅因为function() {}的评估恰好返回一个函数对象。因此,我会小心地说(0, function() {})返回(function() {})。实际上,流程如下:评估括号表达式 > 评估内部表达式,这里是逗号表达式,它返回第二个操作数的值(调用GetValue)。例如,(0, foo.bar)的评估不等于(foo.bar)的评估(有关信息请参见接受的答案)。 - Magnus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接