1、属性的遍历:for...in 循环
for...in
循环用来遍历一个对象所有可遍历(enumerable)的属性。
var obj = {a: 1, b: 2, c: 3};
for (var i in obj) {
console.log('键名:', i);
console.log('键值:', obj[i]);
}
// 键名: a
// 键值: 1
// 键名: b
// 键值: 2
// 键名: c
// 键值: 3
for...in
循环有两个使用注意点。
- 它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。
- 它不仅遍历对象自身的属性,还遍历继承的属性。
举例来说,对象都继承了toString
属性,但是for...in
循环不会遍历到这个属性。
var obj = {};
// toString 属性是存在的
obj.toString // toString() { [native code] }
for (var p in obj) {
console.log(p);
} // 没有任何输出
上面代码中,对象obj
继承了toString
属性,该属性不会被for...in
循环遍历到,因为它默认是“不可遍历”的。
如果继承的属性是可遍历的,那么就会被for...in
循环遍历到。但是,一般情况下,都是只想遍历对象自身的属性,所以使用for...in
的时候,应该结合使用hasOwnProperty
方法,在循环内部判断一下,某个属性是否为对象自身的属性。
var person = { name: '老张' };
for (var key in person) {
if (person.hasOwnProperty(key)) {
console.log(key);
}
}
// name
2、属性的遍历:Object.getOwnPropertyNames()
Object.getOwnPropertyNames
方法返回一个数组,成员是参数对象自身的全部属性的属性名,不管该属性是否可遍历。
var obj = Object.defineProperties({}, {
p1: { value: 1, enumerable: true },
p2: { value: 2, enumerable: false }
});
Object.getOwnPropertyNames(obj)
// ["p1", "p2"]
上面代码中,obj.p1
是可遍历的,obj.p2
是不可遍历的。Object.getOwnPropertyNames
会将它们都返回。
这跟Object.keys
的行为不同,Object.keys
只返回对象自身的可遍历属性的全部属性名。
3、属性的遍历:Object.keys
Object.keys
只返回对象自身的可遍历属性的全部属性名。
Object.keys([]) // []
Object.getOwnPropertyNames([]) // [ 'length' ]
Object.keys(Object.prototype) // []
Object.getOwnPropertyNames(Object.prototype)
// ['hasOwnProperty',
// 'valueOf',
// 'constructor',
// 'toLocaleString',
// 'isPrototypeOf',
// 'propertyIsEnumerable',
// 'toString']
上面代码中,数组自身的length
属性是不可遍历的,Object.keys
不会返回该属性。第二个例子的Object.prototype
也是一个对象,所有实例对象都会继承它,它自身的属性都是不可遍历的。
4、总结
属性的遍历方法 | 特点 |
---|---|
for...in 循环 | 遍历一个对象所有可遍历(enumerable)的属性。不仅遍历对象自身的属性,还遍历继承的属性。 |
Object.getOwnPropertyNames() | 返回参数对象自身的全部属性的属性名,不管该属性是否可遍历。 |
Object.keys | 返回参数对象自身的可遍历属性的全部属性名。 |