【问题标题】:What is the order of evaluation for function arguments in Javascript?Javascript中函数参数的评估顺序是什么?
【发布时间】:2020-06-07 01:40:07
【问题描述】:

根据我的测试,它总是从左到右

>> console.log( console.log(1), console.log(2) );
1
2
undefined undefined

但我在 ECMAScript 标准中找不到确认这一点的相关部分。

【问题讨论】:

  • 这不是按照,的顺序和(&)分组的吗? Operator Precedence ...
  • console.log(1)、console.log(2) 是像自执行函数一样被调用的参数和函数
  • 人们可能会认为f(g(0), g(1)) 几乎可以保证与f.apply(thisObj, [g(0), g(1)]) 做同样的事情。考虑这两个等价物可能是一种有用的心理设备,并且数组元素按从左到右的顺序定义可能对 OP 更有意义。

标签: javascript


【解决方案1】:

JavaScript 中的所有运算符都是从左到右计算其操作数的,包括函数调用运算符。首先评估要调用的函数,然后按从左到右的顺序评估实际参数。

Section 11.2.3 是相关的规范部分。

11.2.3 函数调用

...

2 设 funcGetValue(ref)

3 让 argList 成为评估 Arguments 的结果,生成参数值的内部列表(参见 11.2.4)。

...

您可以看到 ArgumentList 产生式是左递归的

11.2.4 参数列表

...

产生式 ArgumentList : ArgumentList , AssignmentExpression 评估如下

ArgumentListAssignmentExpression 之前被评估,在下面的措辞中..

在 EcmaScript 3 中,一些比较运算符(<<=>>=)从右到左求值,因为 a<=b 是根据 !(b<a) 定义的,但这已被广泛认可作为一个规范错误,主要的解释器没有以这种方式实现它,它在 EcmaScript 5 中得到了修复。

来自语言规范:

11.8.5 The Abstract Relational Comparison Algorithm#Ⓣ

比较x < y,其中xy 是值,产生truefalseundefined(这表明至少一个操作数是NaN)。除了xy 之外,该算法还将一个名为LeftFirst 的布尔标志作为参数。该标志用于控制对xy 执行具有潜在可见副作用的操作的顺序。 这是必要的,因为 ECMAScript 指定从左到右计算表达式。 LeftFirst 的默认值为 true,表示 x 参数对应于出现在y 参数对应表达式的左侧。如果 LeftFirst 为 false,则情况相反,必须在 x 之前对 y 执行操作。这样的比较是这样进行的:

【讨论】:

  • @ŠimeVidas,函数调用运算符。 ()
  • @RightSaidFred:关联性仅决定您是否将a op b op c 消除为((a op b) op c)(a op (b op c)。它与a op b中首先评估a或b无关@
  • @RightSaidFred,您将关联性与评估顺序混淆了。在解析时考虑关联性,但在运行时评估顺序很重要。
  • @RightSaidFred,为了清楚起见,请尝试运行 var x = 1; (x = [])[0] = x;x 现在是一个包含自身的数组,而不是包含 1 的数组,因为 x = [] 在最右边的 x 之前被评估。
  • @RightSaidFred,嗯,否决票是生活中的事实。我很欣赏这个问题。为了帮助您处理,关联性是为什么 x = y = zx = (y = z) 相同,但 1 - 1 - 1(1 - 1) - 1 而不是 1 - (1 - 1)
【解决方案2】:

在这里定义:

生产ArgumentList : ArgumentList , AssignmentExpression 是 评价如下:

  1. precedingArgs 成为评估ArgumentList 的结果。
  2. ref 成为评估AssignmentExpression 的结果。
  3. arg 成为GetValue(ref)
  4. 返回一个List,其长度比precedingArgs的长度大1,并且其项是precedingArgs的项,在 顺序,最后是arg,这是新的最后一项 列表。

阅读这里:http://es5.github.com/#x11.2.4

当一个函数被调用时,传入的参数是从左到右计算的。

【讨论】:

  • 启用评估语句,例如func(a++, ++a, a *= a, a--, --a)。由于上面的规范,它是定义的行为,与 C 语言不同。不过,这不是一个好习惯。
【解决方案3】:

有关历史兴趣,另请参阅 JavaScript 1.1 语言规范的第 4.2 节 Evaluation Order(Brendan Eich,C. Rand Mckinney,96 年 11 月 18 日)。

在函数或构造函数调用中,一个或多个参数表达式 可能出现在括号内,以逗号分隔。每个论点 表达式在任何参数的任何部分之前被完全评估 计算其右侧的表达式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多