【问题标题】:Javascript evaluation order for operators运算符的 Javascript 评估顺序
【发布时间】:2011-05-10 02:44:00
【问题描述】:

以下哪个表达式在所有浏览器(尤其是 IE6+、F3+、Opera 9+、Chrome)中总是从左到右出现?例如,窗口应始终提醒first function,然后提醒second function。在 C 中,他们总是建议不要依赖于表达式求值的顺序。 JavaScript 是否也是如此,还是运算符优先级一致?

function first(){
    alert('first function');
    return 0;
}
function second(){
    alert('second function');
    return 23;
}
first() + second();
first() - second();
first() * second();
first() / second();
first() < second();
first() > second();

使用mozilla 似乎功能评估应该在所有浏览器中保持一致,但显然并不总是遵循标准。

测试

在 browsershots.org 上进行一些测试后,似乎所有浏览器都遵循该标准。
一般来说 依赖 javascript 中的 valueOf 方法时例外。 ValueOf 在谷歌浏览器的特定情况下肯定会被称为倒退。

// The following alerts second then first in google chrome
first.valueOf = function(){alert('first');};
second.valueOf = function(){alert('second');};
first > second;

【问题讨论】:

    标签: javascript evaluation


    【解决方案1】:

    ECMAScript 5 指定所有运算符的操作数的计算顺序。对于代码片段中的每个运算符,评估顺序是从左到右的。我不确定是否有人可以回答 所有 浏览器的行为。

    编辑:另见ECMAScript 3. 评估顺序的定义方式相同。

    【讨论】:

    • 我对上面列出的前五个运算符特别好奇+ - * / &lt; 其他对我来说相当不关心。
    • + - * / &lt; 都应该从左到右评估它们的操作数。 &gt; 还应该从左到右评估它的操作数,任何表现不同的 modern javascript 引擎都有错误。抱歉,我不知道每个浏览器中每个 javascript 引擎的错误来完全回答这个问题。
    • @Jake:这不是错误,它在 ECMAScript 第 3 版规范中。不过,我更新了我的答案,因为它比我记忆中的要微妙。
    • @Claudiu:不,它一个错误。在 ECMAScript 第 3 版规范中,为 &gt; 运算符明确指定了从左到右的运算符评估。如果您不想相信我的话,请参阅我链接的规范。
    • @Jake:仔细阅读。对于a &gt; b,首先评估a,得出val_a,然后评估b,得出val_b (11.8.2)。那是从左到右。 然后val_b $&lt;$ val_a 被评估 (11.8.2 [5]),其中 $&lt;$ 是原始关系运算符 (11.8.5)。这会将val_b 转换为原语(11.8.5 [1]),然后将val_a 转换为原语(11.8.5 [2])。如果它们是对象,它将按与a &gt; b相反的顺序调用它们的valueOf方法。任何遵守规范的浏览器都会有我在回答中概述的行为
    【解决方案2】:

    将表达式计算为值(例如涉及函数调用)总是从左到右进行。

    但是,一旦您比较了两个值,它们就不会被转换为基元,以便以从左到右的方式进行实际比较。例如,在 Chrome 中尝试以下操作:

    var l = {valueOf: function() { alert("L"); }};
    var r = {valueOf: function() { alert("R"); }};
    
    l < r; //alerts "L", then "R"
    l > r; //alerts "R", then "L"
    

    【讨论】:

    • 那么运营商都同意什么优先级?
    • @Claudiu - 刚刚在 Chrome 和 FF 中测试过,不能那样工作。它总是从左到右
    • 我对上面列出的前五个运算符特别好奇+ - * / &lt; 其他对我来说相当不关心。
    • @Lime: 应该始终从左到右。关于 C 的警告是(至少)因为函数调用通常是从右到左进行的,所以如果你将i++ 作为参数之一,期待它的副作用(比如f(i++,i),你可能会感到惊讶。
    • 感谢您的澄清。当您覆盖 valueOf 方法时,我正要询问订单。领先我1步。 :) 像上面所做的那样覆盖 valueOf 方法是否可以接受,还是不好的做法和令人困惑的做法?我一直想创建一个 time 对象,其 valueOf 返回当前时间,这样我就可以去掉括号和类似的技巧。
    【解决方案3】:

    运算符优先级和求值顺序是两个完全不同的东西。在表达式“sqrt(9) + sqrt(16) * sqrt(25)”中,说“先完成乘法”是一种误导。说“乘法优先于加法”是正确的。

    操作是:

    1. sqrt(9)
    2. sqrt(16)
    3. sqrt(25)
    4. 4 * 5
    5. 3 + 20

    前三个可以按任何顺序完成,或者 -- 喘气 -- 同时 如果您有一个四核 CPU 和一个可以利用它的浏览器。 1必须在5之前完成,2和3必须在4之前完成,4必须在5之前完成。没有其他保证。

    在表达式“a && (b / a)”中,JavaScript 保证首先计算 a,如果 a 为零,则不计算 b / a。包括 Fortran 在内的许多其他语言不保证这一点,并且可能会出现被零除的异常。

    【讨论】:

    • 我理解 C 的工作方式与您在上面描述的一样,但老实说,我不相信这些功能在任何情况下都不会同时发生在 javascript 中。我有一个 4 i5 处理器,在 Firefox、chrome 或 opera 中绝对不会出现这种情况。 Javasrcript 无论如何都是单线程的。在javascript中一次只能出现一个函数。从上面的资料来看,似乎有一个标准,浏览器是否遵循它。
    【解决方案4】:

    我不确定您的用例是什么,但这可能是一种选择:

    function add() {
      var retval = 0;
      for (var i = 0; i < arguments.length; i++) {
        retval += arguments[i];
      }
      return retval;
    }
    
    function echoNum(num) {
      alert("Num: " + num);
      return num;
    }
    
    alert("Result: " + add(echoNum(1), echoNum(2)));
    

    【讨论】:

    • 我目前没有特定的用例,我只是想澄清事实标准。不过想法很酷。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    • 2016-12-31
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    相关资源
    最近更新 更多