使用扩展语法创建一系列自然数

时间:2017-12-31 22:44:29

标签: javascript arrays ecmascript-6 iterator

一方面,缺乏与Python 3 range相当的东西是ES6的烦恼。另一方面,有很多变通方法。我的问题是为什么我试过的一种解决方法实际上有效。举例说明:

[...Array(10).keys()];

如果我发现这个神秘的原因并不明显,请注意Array(10).keys()至少显然是空的。

我知道这会浪费地创建两个数组,就像大多数流行的解决方法一样,并且使用生成器(以创建生成器函数为代价)可以避免这种情况。例如,

[...(function*(){let i = 0; while(i<10) yield i++;})()];

我的问题只是为什么第一个解决方法产生了预期的结果。

修改

从答案来看,有些人认为Array(10)的评估等同于Array.apply(null,Array(10))的评估。他们不是。例如,前者.hasOwnProperty(0)false,后者为true。但是,我很乐意被说服他们在某些方面与此相同,因为我的理解显然缺乏某些关键点。我怀疑答案是迭代密钥的结果是由length属性确定的,它们共享,而不是已经定义的实际数组索引。如果是这样,我想知道这种行为是规范性的。

3 个答案:

答案 0 :(得分:4)

Array#keys会返回Array 迭代器。然后,通过访问迭代器中的下一个值,直到没有更多值,Spread语法完全耗尽了迭代器。然后它从迭代器中收集所有值并将它们传播到一个新数组中。

Array(10)创建一个array exotic object,它没有任何实际的整数索引键,只有length属性 - 所以它会清空#39;但Array(10).keys()不是。事实是使用Array#keys doesn't depend on actual elements, just the length property。内部操作CreateArrayIterator通过内部%ArrayIteratorPrototype% object创建迭代器,从数组创建一个键迭代器。查看%ArrayIteratorPrototype%.next(),您将看到使用数组的长度。对于Array#keys,索引会不断递增,直到达到数组的长度。这就是如何创建迭代器,它为您提供了数组的所有键,而不是首先实际拥有所述整数键。

如果您对抽象步骤感到好奇,请参阅ECMAScript语言规范的Section 12.2.5.2 ArrayAcculumation,特别是 SpreadElement : ... AssignmentExpression 制作,其中概述了逐步完成的过程。与扩展语法结合使用的迭代器。

要查看将这些值收集到新数组中的抽象步骤,请参阅Section 12.2.5.3 Evaluation。具体而言, ArrayLiteral : [ ElementList ] 生产是生产[...Array.keys()]。执行前面提到的ArrayAcculumation过程,该过程通过迭代器聚合迭代并将它们设置为新数组。

答案 1 :(得分:1)

Array.prototype.keys正在返回一个新的Array Iterator Array(10)是一个包含10个()广告位的数组。

当您展开数组的键时,您将迭代它并创建一个新数组。但这次新数组的项目是第一个数组的插槽。

您可以使用for of循环查看它:

const arr = Array(10).keys();
for (let key of arr) {
  console.log(key);
}

顺便说一句,您可以使用Array.from作为第二个参数,它使用map函数。所以你可以只返回索引或任何你想要的东西:

const arr = Array.from(Array(10), (_, idx) => idx);
console.log(arr);

修改
作为有关Array(10)结果的已编辑问题的后续内容:
DOCS提及:

  

如果传递给Array构造函数的唯一参数是整数   在0到232-1(含)之间,这将返回一个新的JavaScript数组   将其length属性设置为该数字(注意:这意味着一个   arrayLength空槽的数组,而不是实际未定义的槽   值)。如果参数是任何其他数字,则为RangeError异常   扔了。

所以你真的得到了:

  • 新阵列
  • 使用提供给的数字更新length属性 功能

  • 你得到 n -slots

现在.keys将创建一个迭代器,它将返回每个插槽索引作为值 例如:

let it = Array(10).keys();  

并致电:

it.next();

将返回:

{value: 0, done: false}  

一次又一次地调用它会产生

{value: n, done: false}

直到它到达最后一个插槽:

{value: 9, done: false}

然后下一个.next来电将返回

{value: undefined, done: true} 

将标记这是迭代的结束。

运行示例:

const it = Array(10).keys();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next()); // done: true

答案 2 :(得分:0)

Array(10)创建一个长度为10的数组,其中每个元素都是undefined

Array(10).keys()返回一个迭代器,它迭代数组的键......数字09

当扩展语法用于定义数组文字(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator)时,它会完全迭代它给定的任何迭代器,并将迭代器的返回值添加到创建的数组中(按顺序)。