关于使用扩展运算符包含 1...N 的数组的 Javascript 异常行为

标签 javascript arrays object key

在 Javascript 中,我通过扩展运算符创建了这个简单的升序数组。

[...Array(5).keys()]
// printed list
[0, 1, 2, 3, 4]

但我只是添加了 1,就生成了这个意外的数组。 (我只是预计这会是一个错误)

[...Array(5).keys() + 1] 
// printed list
["[", "o", "b", "j", "e", "c", "t", " ", "A", "r", "r", "a", "y", " ", "I", "t", "e", "r", "a", "t", "o", "r", "]", "1"]

我想知道是什么导致了这种行为。

最佳答案

首先,计算 ... 右侧的表达式。也就是说,Array(5).keys() + 1 被评估,然后该评估的结果被传播。对表达式进行分组可能会让事情变得更清晰:

[...(Array(5).keys() + 1)] 

因此,上面我们首先计算 Array(5).keys() + 1 的结果。 + 运算符在原始操作数之间工作。当您执行 Array(5).keys() 时,您会得到一个未归类为基元的迭代器。因此,JS 会尝试将其转换为原始类型。当 JS 尝试在此上下文中将迭代器转换为原语时,它会尝试:

  1. 调用迭代器的Symbol.toPrimitive方法,由于该方法不存在,因此它会继续尝试下一步
  2. 调用迭代器的.valueOf() 方法。这成功了,但它返回了迭代器,它不是原语,所以我们进入下一步
  3. 调用 .toString() 方法。这会产生非对象类型(即:字符串),因此这是成功的。

当迭代器的 .toString() 方法被调用时,它的计算结果为 "[object Array Iterator]"。当它与数字1相加时,我们将字符串与数字连接起来(而不是相加),给出:

[..."[object Array Iterator]1"]

由于字符串是可迭代的,扩展语法将使用字符串的迭代器循环遍历字符串中的代码点,从而使字符串的每个字符成为其自己的元素:

["[", "o", "b", "j", "e", "c", "t", " ", "A", "r", "r", "a", "y", " ", "I", "t", "e", "r", "a", "t", "o", "r", "]", "1"]

为了给迭代器中的每一项添加一个,您可以使用 Array.from()它可以采用迭代器,并对每个元素应用映射函数:

const res = Array.from(Array(5).keys(), i => i+1);
console.log(res);

由于 Array.from() 的参数不必是迭代器,因此您也可以使用 Array(5) 代替,并使用索引作为要添加到的值:

const res = Array.from(Array(5), (_,i) => i+1);
console.log(res);

关于关于使用扩展运算符包含 1...N 的数组的 Javascript 异常行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65868308/

相关文章:

javascript - jQuery 文件上传在 IE 8 和 9 中不起作用

javascript - Chrome/Tampermonkey 用户脚本存储在文件系统的什么位置?

php - 如何从 MySQL 获取并组合数据,然后插入到 PHP 数组中

java - java中如何比较数组的特定元素

python - 在 JSON 文件的现有列表中附加生成的对象的有效方法?

javascript - 单页应用程序 - 我应该在服务器端使用 MVC 框架吗?

javascript - 通过Android WebView中的javascript检测点击HTML按钮

python - 提取 Nx3 数组的特定行,每列都满足条件

JAVA - 类及其对象, super

javascript - 将键值对添加到 javascript 中的对象数组?