[英]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
等)却没有呢?
It is not about: 它不是关于:
TypedArray
s TypedArray
迭代 Array
(every other method seems to work in the expected way) Array
(其他所有方法似乎都按预期方式工作) undefined
elements undefined
元素 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.