【问题标题】:Indirect function call in JavaScriptJavaScript 中的间接函数调用
【发布时间】:2011-07-06 21:34:28
【问题描述】:

有些东西

f.call(...)
f.apply(...)

然后就是这个

(1, alert)('Zomg what is this????!!!11')

“1”在这种情况下似乎没有多大意义,以下工作正常:

(null, alert)('Zomg what is this????!!!11')
(1, null, alert)('Zomg what is this????!!!11')
(undefined, alert)('Zomg what is this????!!!11')

您能否指出 ECMAScript 中描述该语法的特定部分?

【问题讨论】:

标签: javascript ecma262


【解决方案1】:

它是comma operator,它计算它的两个操作数并返回第二个操作数的值。

因此,(null, alert) 之类的计算结果为 alert 函数,您可以立即使用括号调用该函数。

ECMA-262 (PDF) 的第 11.14 节中有描述。

【讨论】:

    【解决方案2】:

    comma operator 导致表达式被顺序计算。将表达式括在括号中会返回最后一个表达式的值。所以(1, alert)("hello")在功能上等价于:

    1;
    alert("hello");
    

    在我的脑海中,我想不出这样做的理由。

    【讨论】:

      【解决方案3】:

      你只是在使用The Comma Operator

      该运算符只从左到右计算其操作数,并从第二个返回值,例如:

      (0, 1); // 1
      ('foo', 'bar'); // 'bar'
      

      在调用函数的上下文中,操作数的求值将简单地得到一个值,而不是一个引用,这导致被调用函数内的this值指向全局对象(或者它将是@987654330 @ 在新的 ECMAScript 5 严格模式下)。

      例如:

      var foo = 'global.foo';
      
      var obj = {
        foo: 'obj.foo',
        method: function () {
          return this.foo;
        }
      };
      
      obj.method();      // "obj.foo"
      (1, obj.method)(); // "global.foo"
      

      如您所见,第一次调用是直接调用,method 中的this 值将正确引用obj(返回"obj.foo"),第二次调用,由逗号运算符将使this 值指向全局对象(产生"global.foo")。

      这种模式最近变得非常流行,间接calls to eval,这在 ES5 严格模式下很有用,例如获取对全局对象的引用,(假设你在非浏览器中环境,window 不可用):

      (function () {
        "use strict";
        var global = (function () { return this || (1,eval)("this"); })();
      })();
      

      在上面的代码中,内部匿名函数将在严格模式代码单元内执行,这将导致this 的值为undefined

      || 运算符现在将采用第二个操作数,eval 调用,这是一个间接调用,它将评估全局词法和变量环境中的代码。

      但就个人而言,在这种情况下,在严格模式下我更喜欢使用Function 构造函数来获取全局对象:

      (function () {
        "use strict";
        var global = Function('return this')();
      })();
      

      使用 Function 构造函数创建的函数只有在以 Use Strict 指令开头时才是严格的,它们不会像函数声明或函数表达式那样“继承”当前上下文的严格性。

      【讨论】:

      • 感谢 ECMAScript 链接
      • 关于:“只会得到一个值,而不是一个参考”。这根本不是正在发生的事情。您会看到不同的行为,因为您正在调用没有dot operator 的函数。如果您这样做,您会看到相同的行为:var temp = obj.method; temp();
      • @lwburk:我说的是规范,它会得到一个,而不是Reference,看看逗号运算符返回什么:“步骤4 . 返回 GetValue(rref)。"它使用GetValue 抽象操作。您发布的示例确实是等效的,但略有不同,在这种情况下,temp 是一个没有 base objectreference
      • @lwburk,啊,另外,您可以看到您的示例在 ES5 中并不完全等效:eval('foo')Direct Call to eval,但 (1, eval)('foo')不是,这种情况与. 属性访问器无关。 Kangax 很好地解释了这一点here
      • 非常有趣。我的观点更加平淡无奇:(1, obj.method) === obj.method // true
      猜你喜欢
      • 1970-01-01
      • 2014-07-15
      • 1970-01-01
      • 2013-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      相关资源
      最近更新 更多