为什么 for-of 不跳过稀疏数组的空槽? [JavaScript]
Why does for-of not skip empty slots of a sparse Array? [JavaScript]
正如标题所说,为什么 for-of
运行 循环 body 与 循环变量 绑定到 undefined
对于不在 Array
中的索引,而其他迭代构造(forEach()
、for-in
等)不?
澄清: 因为很多人误解了问题
不是关于:
遍历 TypedArray
s(不能稀疏)或 any其他class
如何 "correctly" 在稀疏 Array
上迭代(所有其他方法似乎都以预期的方式工作)
在 Array
中跳过 undefined
个元素
以下非正式描述found on 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.
即它还为 non-existent 属性调用。
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.
这是预期的行为吗 () 以及为什么要这样设计?
for..of
调用数组迭代器方法,描述为in the spec.
(2) Let iterator be ObjectCreate(%ArrayIteratorPrototype%, «[[IteratedObject]], [[ArrayIteratorNextIndex]], [[ArrayIterationKind]]»).
(4) Set iterator’s [[ArrayIteratorNextIndex]] internal slot to 0.
然后,当遍历迭代器时,在22.1.5.2.1 %ArrayIteratorPrototype%.next::
(6) Let index be the value of the [[ArrayIteratorNextIndex]] internal slot of O.
(10) If index ≥ len, then
(10) (a) Set the value of the [[IteratedObject]] internal slot of O to undefined.
(10) (b) Return CreateIterResultObject(undefined, true).
(11) Set the value of the [[ArrayIteratorNextIndex]] internal slot of O to index+1.
(create iterator result object whose value is array[index]
)
换句话说 - 迭代器从索引 0 开始迭代,并在每次调用 .next()
时将索引递增 1。它不会检查数组是否确实 在该索引处有 项(稀疏数组不会)——它只是检查索引是否小于 .length
数组的。
与for..in
相反,所有可枚举属性都被迭代,数组自身的可枚举属性不包括 稀疏数组索引。
const sparse = [0, , 2];
console.log(sparse.hasOwnProperty('0'));
console.log(sparse.hasOwnProperty('1'));
所以是的,这是有意为之的行为。
正如标题所说,为什么 for-of
运行 循环 body 与 循环变量 绑定到 undefined
对于不在 Array
中的索引,而其他迭代构造(forEach()
、for-in
等)不?
澄清: 因为很多人误解了问题
不是关于:
遍历(不能稀疏)或TypedArray
sany其他class如何 "correctly" 在稀疏(所有其他方法似乎都以预期的方式工作)Array
上迭代在Array
中跳过
undefined
个元素
以下非正式描述found on 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.
即它还为 non-existent 属性调用。
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.
这是预期的行为吗 (
for..of
调用数组迭代器方法,描述为in the spec.
(2) Let iterator be ObjectCreate(%ArrayIteratorPrototype%, «[[IteratedObject]], [[ArrayIteratorNextIndex]], [[ArrayIterationKind]]»).
(4) Set iterator’s [[ArrayIteratorNextIndex]] internal slot to 0.
然后,当遍历迭代器时,在22.1.5.2.1 %ArrayIteratorPrototype%.next::
(6) Let index be the value of the [[ArrayIteratorNextIndex]] internal slot of O.
(10) If index ≥ len, then
(10) (a) Set the value of the [[IteratedObject]] internal slot of O to undefined.
(10) (b) Return CreateIterResultObject(undefined, true).
(11) Set the value of the [[ArrayIteratorNextIndex]] internal slot of O to index+1.
(create iterator result object whose value is
array[index]
)
换句话说 - 迭代器从索引 0 开始迭代,并在每次调用 .next()
时将索引递增 1。它不会检查数组是否确实 在该索引处有 项(稀疏数组不会)——它只是检查索引是否小于 .length
数组的。
与for..in
相反,所有可枚举属性都被迭代,数组自身的可枚举属性不包括 稀疏数组索引。
const sparse = [0, , 2];
console.log(sparse.hasOwnProperty('0'));
console.log(sparse.hasOwnProperty('1'));
所以是的,这是有意为之的行为。