var parent = Object.create(Object.prototype, { a: { value: 1, writable: true, enumerable: true, configurable: true } });
parent繼承自Object.prototype,有一個可枚舉的屬性a。下面我們在創建一個繼承自parent的對象child。
var child = Object.create(parent, { b: { value: 2, writable: true, enumerable: true, configurable: true }, c: { value: 3, writable: true, enumerable: false, configurable: true } });
child有兩個屬性b和c,其中b為可枚舉屬性,c為不可枚舉屬性。
下面我們將用四種方法遍歷child對象,來比較四種方法的不同。如下的代碼代表程序的輸出。
for in
for in是es3中就存在,最早用來遍歷對象(集合)的方法。
for (var key in child) {
console.log(key);
}
// > b
// > a
從輸出可以看出,for in會輸出自身以及原型鏈上可枚舉的屬性。
注意:不同的瀏覽器對for in屬性輸出的順序可能不同。
如果僅想輸出自身的屬性可以借助 hasOwnProperty。可以過濾掉原型鏈上的屬性。
for (var key in child) {
if (child.hasOwnProperty(key)) {
console.log(key);
}
}
// > b
上面的代碼,僅輸出了child自己的可枚舉屬性b,而沒有輸出原型parent中的屬性。
Object.keys
Object.keys是es5中新增的方法,用來獲取對象自身可枚舉的屬性鍵。
console.log(Object.keys(child));
// > ["b"]
可以看出Object.keys的效果和for in+hasOwnProperty的效果是一樣的。
Object.getOwnPropertyNames
Object.getOwnPropertyNames也是es5中新增的方法,用來獲取對象自身的全部屬性名。
console.log(Object.getOwnPropertyNames(child));
// > ["b", "c"]
總結
而遍歷對象有5種方法:
(1)for...in
for...in循環遍歷對象自身的和繼承的可枚舉屬性(不含Symbol屬性)。
(2)Object.keys(obj)
Object.keys返回一個數組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含Symbol屬性)。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一個數組,包含對象自身的所有屬性(不含Symbol屬性,但是包括不可枚舉屬性)。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一個數組,包含對象自身的所有Symbol屬性。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一個數組,包含對象自身的所有屬性,不管是屬性名是Symbol或字符串,也不管是否可枚舉。
for...in循環遍歷對象自身的和繼承的可枚舉屬性(不含Symbol屬性)。
(2)Object.keys(obj)
Object.keys返回一個數組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含Symbol屬性)。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一個數組,包含對象自身的所有屬性(不含Symbol屬性,但是包括不可枚舉屬性)。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一個數組,包含對象自身的所有Symbol屬性。
(5)Reflect.ownKeys(obj)