一方面,缺乏与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
属性确定的,它们共享,而不是已经定义的实际数组索引。如果是这样,我想知道这种行为是规范性的。
答案 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()
返回一个迭代器,它迭代数组的键......数字0
到9
。
当扩展语法用于定义数组文字(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator)时,它会完全迭代它给定的任何迭代器,并将迭代器的返回值添加到创建的数组中(按顺序)。