为什么for-of不能跳过稀疏数组的空插槽? [JavaScript]

时间:2019-04-27 23:51:10

标签: javascript iteration sparse-matrix for-of-loop

正如标题所述,对于for-of以外的索引,为什么undefined循环变量绑定到Array来运行循环体迭代构造(forEach()for-in等)

澄清:被很多人误解了这个问题

关于 不是

  • 迭代TypedArray s (不能稀疏)或 任何 其他类 < / li>
  • 如何在稀疏的Array上“正确”迭代(其他所有方法似乎都可以按预期的方式工作)
  • 跳过undefined
  • 中的Array个元素

以下非正式说明found on MDN不正确吗?

  

for...of语句[...]调用一个自定义迭代钩子,该钩子将针对对象的每个不同属性的值执行语句。

即还会为不存在的属性调用它。

const sparse = [0, 1, 2] // Was [0, , 2], but some are unfamiliar with this syntax 
                         // or think it creates the array [0, undefined, 2]
delete sparse[1]
for (let e of sparse) console.log('for-of', e)
// Contrast with:
sparse.forEach(e => console.log('forEach', e))
for (let i in sparse) console.log('for-in', sparse[i])
console.log('map', sparse.map(e => e)) // Note, prints incorrectly in the snippet
                                       // console, check browser console
// etc.

这是预期的行为(Yes)吗,为什么要这样设计?

1 个答案:

答案 0 :(得分:1)

for..of调用Array迭代器方法,该方法在in the spec中进行了描述。

  

(2)让迭代器成为ObjectCreate(%ArrayIteratorPrototype%,«‍ [[IteratedObject]],[[ArrayIteratorNextIndex]],[[ArrayIterationKind]]»)。

     

(4)将迭代器的[[ArrayIteratorNextIndex]]内部插槽设置为0。

然后,当迭代器被迭代时,在22.1.5.2.1 %ArrayIteratorPrototype%.next:中:

  

(6)令index为O的[[ArrayIteratorNextIndex]]内部插槽的值。

     

(10)如果index≥len,则

     

(10)(a)将O的[[IteratedObject]]内部插槽的值设置为undefined。

     

(10)(b)返回CreateIterResultObject(undefined,true)。

     

(11)将O的[[ArrayIteratorNextIndex]]内部插槽的值设置为index + 1

     

(创建值为array[index]的迭代器结果对象)

换句话说,迭代器从索引0开始进行迭代,并在每次调用.next()时将索引增加1。它不检查该数组在该索引处是否真的有一个符号(稀疏数组不会),它只是检查该索引是否小于该数组的.length

另一方面,使用for..in会迭代所有 enumerable 属性,并且数组本身的可枚举属性不包含稀疏数组索引。 / p>

const sparse = [0, , 2];
console.log(sparse.hasOwnProperty('0'));
console.log(sparse.hasOwnProperty('1'));

是的,这是预期的行为。