首页 > 解决方案 > 动态数组元素的求值顺序是否有保证?

问题描述

我试图找到一种简洁的方法将数组的最后一个元素移动到第一个位置,并提出了一个单行解决方案popping 元素并传播到数组中:

arr1 = [arr1.pop(), ...arr1];

我的问题是:跨浏览器的评估顺序是否得到保证?

我问是因为如果之前...arr1评估 arr1.pop(),那么数组将在开头和结尾处以相同元素的副本结束(例如。[1, 2, 3, 4, 5, 1])。

我知道在 Javascript 中,评估总是从左到右线性进行,这在表达式和函数 arg 列表中是有意义的。我找不到的是并发数组元素是否计入这种线性性质,或者是否有可能同时评估它们(或者是否取决于标准的实现)。

标签: javascriptsyntaxsemantics

解决方案


概览语法概述:Array Initializer Syntax

(注意:在下面,为了简洁起见,我从语法中排除了 Elision_opt,它解释了连续的逗号或没有前面定义的元素的逗号以允许空元素,
例如[el1,,el2]=[el1,(empty),el2]:)

首先,根据12.2.5.2 运行时语义:评估

[ arr1.pop(), ...arr1 ]
[ ElementList ]

12.2.5.1 运行时语义:ArrayAccumulation
arr1.pop() , ...arr1
ElementList: ElementList, SpreadElement

  1. 将 nextIndex 设置为使用参数数组和 nextIndex 对 ElementList 执行 ArrayAccumulation 的结果。

[...]

  1. 返回使用参数数组和 nextIndex 对 SpreadElement 执行 ArrayAccumulation 的结果。

因此在步骤 1.ArrayAccumulation必须在arr1.pop(), 在它评估之前执行...arr1。您会注意到,在这种情况下,SpreadElement偶数的评估取决于nextIndex从调用ArrayAccumulation第一部分派生的值。并且语法评估以这样一种方式递归,即从左到右评估它,从右边的部分分支出来。
(这只是语法分析的一个特性。)
还要注意:
ElementList: ElementList, AssignmentExpression
ElementList: ElementList, ...AssignmentExpression的结构相同。

(注意:以上已经是保证评估顺序的证明)
其余的评估如下:
arr1.pop()
ElementList: AssignmentExpression

  1. 让创造成为!CreateDataPropertyOrThrow(数组,!ToString(nextIndex),initValue)。
  2. 返回下一个索引 + 1。

接下来SpreadElement ArrayAccumulation调用arr1带有arr1.pop()' 的返回值的参数数组和nextIndex + 1
SpreadElement ArrayAccumulation,粗略总结,在arr1( AssignmentExpression) 上获取一个迭代器,对其进行迭代,并且:

d。履行 !CreateDataPropertyOrThrow(数组,!ToString(nextIndex),nextValue)。

在每个迭代值上。


推荐阅读