我正在使用方法Object.defineProperty()和enumerable
参数的descriptor
属性。在MDN
上,您可以阅读以下说明:
可枚举:
true
当且仅当在枚举相应对象的属性期间显示此属性时。默认为false
。
但是,我想知道它不影响遍历可迭代对象的方法(例如for ... of)的原因。在下一个示例中,您可以看到使用for ... of
和for ... in
遍历数组的比较。
let arr = [1, 2, 3, 4, 5];
Object.defineProperty(arr, "4", {value: 99, enumerable: false});
console.log("For ... of traverse non-enumerable properties:");
for (const ele of arr)
{
console.log(ele);
}
console.log("For ... in don't traverse non-enumerable properties:");
for (const key in arr)
{
console.log(arr[key]);
}
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
此外,作为该问题的标题,built-in
数组方法也忽略了此设置,但是object
方法却没有:
let arr = [1, 2, 3, 4, 5];
Object.defineProperty(arr, "4", {value: 99, enumerable: false});
console.log("forEach(): ");
arr.forEach(x => console.log(x));
console.log("map(): ", arr.map(x => x + 1));
console.log("reduce(): ", arr.reduce((acc, x) => `${acc + x},` , ""));
console.log("Object.keys(): ", Object.keys(arr));
console.log("Object.values(): ", Object.values(arr));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
我并不是说这是错误或意外的行为,而是在寻找这种情况的解释,谢谢!
答案 0 :(得分:3)
这是因为way the array iterator is specified。虽然定义每个键的密集数组是最常见的,但也支持稀疏数组,其中只定义了几个键。为了支持这一点,数组迭代需要能够迭代过去实际上不存在的键。例如:
const arr = [];
arr[0] = 0;
arr[10] = 10;
console.log('has 0?', arr.hasOwnProperty(0))
console.log('has 1?', arr.hasOwnProperty(1))
for (let val of arr) {
console.log(val);
}
因此,基本上,迭代器的定义方式是使它从一个数字索引移至下一个数字索引,直至达到数组的长度。在此过程中,它不会检查这些索引是否可枚举,甚至根本不存在。
For ... of
使用迭代器,因此受到迭代器的影响,就像某些数组方法一样。 For ... in
不使用迭代器,非数组也不受数组迭代器的影响(尽管它们可能有自己的迭代器)