【问题标题】:Why does for-of not skip empty slots of a sparse Array? [JavaScript]为什么 for-of 不跳过稀疏数组的空槽? [JavaScript]
【发布时间】:2019-04-27 23:51:09
【问题描述】:

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

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

不是关于:

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

下面的非正式描述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) 以及为什么以这种方式设计?

【问题讨论】:

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


    【解决方案1】:

    for..of 调用数组迭代器方法,描述为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,所有可枚举属性都被迭代,数组自己的可枚举属性不包括稀疏数组索引。

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

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

    【讨论】:

    • 感谢您的回答。回复:>它不会检查数组是否真的在该索引处有一个项目,我很难解释规范,有14. Let elementValue be Get(a, elementKey)15. ReturnIfAbrupt(elementValue)Get 调用 .[[Get]],它有 2. Let desc be O.[[GetOwnProperty]](P)3. ReturnIfAbrupt(desc).. 所以对于不在数组中的索引,这不会导致突然完成(continue? 或 throw?)
    • Get算法不抛出,返回array.[[Get]](elementKey, array),在任何地方都找不到key,最终到达c. If parent is null, return undefined.。访问对象中不存在的属性只会返回 undefined - 它不会抛出(另一方面,尝试访问 undefinednull 的属性会抛出) - 所以这里没有突然完成.
    • 不抱歉,确实如此
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    相关资源
    最近更新 更多