简体   繁体   English

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

[英]Why does for-of not skip empty slots of a sparse Array? [JavaScript]

As the title says, why does for-of run the loop body with the loop variable bound to undefined for indices not in the Array , while other iteration constructs ( forEach() , for-in , etc.) don't? 如标题所述,为什么for-of不在循环 for-of运行循环体,且循环变量绑定到undefined ,而索引不在Array ,而其他迭代构造( forEach()for-in等)却没有呢?

Clarification : As many misunderstood the question 澄清 :许多人误解了这个问题

It is not about: 不是关于:

  • iterating over TypedArray s TypedArray迭代 (which cannot be sparse) or (不能稀疏)或 any other class 任何其他班级
  • how to "correctly" iterate 如何“正确”地迭代 over a sparse Array (every other method seems to work in the expected way) 在稀疏Array (其他所有方法似乎都按预期方式工作)
  • skipping undefined elements 跳过undefined元素 in an Array Array

Is the following informal description found on MDN incorrect? 在MDN上发现以下非正式描述不正确吗?

The for...of statement [...] invokes a custom iteration hook with statements to be executed for the value of each distinct property of the object. for...of语句使用对象的每个不同属性的值调用要执行的语句的自定义迭代钩子。

Ie it is also invoked for non-existent properties. 即,它也为不存在的属性而调用。

 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. 

Is this the intended behaviour ( Yes ) & why was it designed in this way? 这是预期的行为( ),为什么要这样设计?

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

(2) Let iterator be ObjectCreate(%ArrayIteratorPrototype%, «‍[[IteratedObject]], [[ArrayIteratorNextIndex]], [[ArrayIterationKind]]»). (2)令迭代器为ObjectCreate(%ArrayIteratorPrototype%,«[[IteratedObject]],[[ArrayIteratorNextIndex]],[[ArrayIterationKind]]»)。

(4) Set iterator's [[ArrayIteratorNextIndex]] internal slot to 0. (4)将迭代器的[[ArrayIteratorNextIndex]]内部插槽设置为0。

Then, when the iterator is iterated over, in 22.1.5.2.1 %ArrayIteratorPrototype%.next: : 然后,当迭代器迭代完成后,在22.1.5.2.1%ArrayIteratorPrototype%.next:中

(6) Let index be the value of the [[ArrayIteratorNextIndex]] internal slot of O. (6)令index为O的[[ArrayIteratorNextIndex]]内部插槽的值。

(10) If index ≥ len, then (10)如果index≥len,则

(10) (a) Set the value of the [[IteratedObject]] internal slot of O to undefined. (10)(a)将O的[[IteratedObject]]内部插槽的值设置为undefined。

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

(11) Set the value of the [[ArrayIteratorNextIndex]] internal slot of O to index+1 . (11) 将O的[[ArrayIteratorNextIndex]]内部插槽的值设置为index + 1

(create iterator result object whose value is array[index] ) (创建迭代器结果对象,其值是array[index]

In other words - the iterator iterates starting at index 0, and increments the index by 1 every time .next() is called. 换句话说-迭代器从索引0开始进行迭代,并在每次调用.next()时将索引增加1。 It does not check to see if the array actually has an item at that index (which a sparse array will not) - it just checks that the index is less than the .length of the array. 它不会检查数组是否确实在该索引处一个项目(稀疏数组不会该项目),它只是检查索引是否小于数组的.length

With for..in , on the other hand, all enumerable properties are iterated over, and an array's own enumerable properties do not include sparse array indicies. 另一方面,使用for..in会迭代所有可枚举的属性,并且数组本身的可枚举的属性不包含稀疏数组索引。

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

So yes, this is intended behavior. 是的,这是预期的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM