ES6中[...Array(10).keys()]生成自然数序列的原理探究
为什么
[...Array(10).keys()]能生成0到9的数组? 这个问题的核心在于理解稀疏数组的本质和**Array.prototype.keys()迭代器的规范行为**,咱们一步步拆解:
1. Array(10)创建的是啥?
当你调用Array(10)时,JavaScript会生成一个长度为10的稀疏数组:
- 它的
length属性被明确设置为10,但数组里并没有0到9这些索引对应的自有属性(所以你调用Array(10).hasOwnProperty(0)会返回false); - 简单说,这就是个只有“长度架子”的空数组,没有实际填充的元素。
2. Array.prototype.keys()的迭代逻辑不依赖实际元素
根据ECMAScript规范,keys()方法返回的数组迭代器,其遍历规则是完全由数组的length属性驱动,根本不关心数组有没有实际元素:
- 迭代器从索引
0开始,每次自动递增1; - 只要当前索引小于数组的
length,就会返回该索引值; - 直到索引等于
length时,迭代才会结束。
所以哪怕是Array(10)这种稀疏数组,keys()的迭代器依然会依次吐出0,1,2,...,9这10个数字。
3. 扩展运算符...的作用
扩展运算符...可以遍历任何可迭代对象(这里就是keys()返回的迭代器),把迭代出的每个值收集到一个新数组里,所以[...Array(10).keys()]最终就得到了[0,1,2,...,9]。
补充:和Array.apply(null, Array(10))的区别
你提到的Array.apply(null, Array(10))会生成一个密集数组:它会把稀疏数组的每个“空位”填充为undefined,所以每个索引都成了数组的自有属性(hasOwnProperty(0)返回true)。但对keys()迭代器来说,不管是稀疏还是密集数组,只要length相同,迭代结果完全一致——因为迭代器只认length,不检查索引是否存在。
规范确认
这个行为是完全符合ECMAScript标准的:ES规范中,数组迭代器的next()方法内部会维护一个index变量,初始值为0,每次调用next()时:
- 如果
index>= 数组的length,返回{ done: true }; - 否则,返回
{ value: index, done: false },然后index加1。
整个过程完全不校验数组在index位置是否有元素,所以稀疏数组的keys()迭代器依然能生成完整的索引序列。
内容的提问来源于stack exchange,提问作者Alan
相关产品推荐
相关产品推荐

