为什么 non-enumerable 属性不影响数组 built-in 方法?
Why non-enumerable properties don't affect the array built-in methods?
我在玩Object.defineProperty() 和descriptor
参数的enumerable
属性 方法。在 MDN
你可以阅读下一个描述:
enumerable: true
if and only if this property shows up during enumeration of the properties on the corresponding object. Defaults to false
.
但是,我想知道为什么它不影响遍历可迭代 objects 的方法,例如 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;}
我并不是说这是错误的或意外的行为,只是在寻找对这种情况的解释,谢谢!
因为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
不使用迭代器,非数组也不受数组迭代器的影响(尽管它们可能有自己的迭代器)
我在玩Object.defineProperty() 和descriptor
参数的enumerable
属性 方法。在 MDN
你可以阅读下一个描述:
enumerable:
true
if and only if this property shows up during enumeration of the properties on the corresponding object. Defaults tofalse
.
但是,我想知道为什么它不影响遍历可迭代 objects 的方法,例如 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;}
我并不是说这是错误的或意外的行为,只是在寻找对这种情况的解释,谢谢!
因为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
不使用迭代器,非数组也不受数组迭代器的影响(尽管它们可能有自己的迭代器)