for ... in、Object.keys 和 Object.getOwnPropertyNames 的区别
for...in
for...in 语句以任意顺序迭代一个对象的除 Symbol 以外的可枚举属性,包括继承的可枚举属性。
let point = {x: 1, y: 2}
for (var prop in point) {
console.log('property:', prop, ',value:', point[prop])
}
运行程序控制台输出如下:
property: x ,value: 1
property: y ,value: 2
可以看出 point 对象的属性 x 和 y 都被正常遍历输出,现在我们通过 Object.defineProperty
将 x 属性修改为不可枚举,然后再次遍历 point:
// 将 x 改为不可枚举
Object.defineProperty(point, 'x', {
enumerable: false
})
for (var prop in point) {
console.log('property:', prop, ',value:', point[prop])
}
由于 point 对象的 x 属性不可遍历,因此程序输出如下:
property: y ,value: 2
上面提到了 for... in
除了遍历自身可枚举的属性之外还会遍历继承的(即原型链上的)可枚举的属性,下面我们试一下继承:
let parent = {p: 1}
let point = {x: 1, y: 2}
// 让 point 对象继承 parent 对象,继承的方式有多种,这里为了演示方便使用了 __proto__ 实现继承
point.__proto__ = parent
for (var prop in point) {
console.log('property:', prop, ',value:', point[prop])
}
运行程序控制台输出如下:
property: x ,value: 1
property: y ,value: 2
property: p ,value: 1
由于 point 继承了 parent 对象,因此使用 for...in
遍历也会输出 parent 对象中可枚举的属性。
Object.keys
Object.keys
遍历对象自身可枚举的属性,不包括继承的属性。
let a = ['a', 'b', 'c']
console.log(Object.keys(a)) // 输出:['0', '1', '2']
以上用数组演示 Object.keys
的用法,可以看出数组的属性为数组下标,实际上可以将数组 a 看成 {0: 'a', 1: 'b', 2: 'c'}
。
Object.getOwnPropertyNames
Object.getOwnPropertyNames
遍历对象自身的属性(包括不可枚举的属性),不包括继承的属性。
let a = ['a', 'b', 'c']
console.log(Object.getOwnPropertyNames(a)) // 输出:['0', '1', '2', 'length']
比较本例的输出和上一个例子的输出,不难看出本例的输出多了一个 length
属性。这是由于数组的 length 属性是不可枚举的,因此 Object.keys
不会输出 length
属性。
总结
for...in
语句以任意顺序迭代一个对象的除 Symbol 以外的可枚举属性,包括继承的可枚举属性。Object.keys
遍历对象自身可枚举的属性,不包括继承的属性。Object.getOwnPropertyNames
遍历对象自身的属性,包括不可枚举的属性,不包括继承的属性。
注意事项
不建议使用 for...in
遍历数组,我们可以使用 for...of
或者 Array.prototype.forEach
遍历数组。
有问题吗?点此反馈!
温馨提示:反馈需要登录