1

正如标题所说,为什么for-of运行循环体时将循环变量绑定到undefined不在 中的索引Array,而其他迭代构造(forEach()for-in等)却没有?

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

不是关于:

  • 迭代TypedArrays(不能稀疏)或任何其他班级
  • 如何“正确”迭代在稀疏上Array(所有其他方法似乎都以预期的方式工作)
  • 跳过undefined元素在一个Array

在 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.

这是预期的行为()以及为什么以这种方式设计?

4

1 回答 1

2

for..of调用 Array 迭代器方法,该方法在 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另一方面,使用,所有可枚举属性都被迭代,并且数组自己的可枚举属性不包括稀疏数组索引。

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

所以是的,这是预期的行为。

于 2019-04-28T00:01:10.813 回答