到 ES6 為止,一共有 5 種方法可以實現物件屬性的遍歷,具體方法如下所示:
-
for...in。
-
Object.keys(obj)。
-
Object.getOwnPropertyNames(obj)。
-
Object.getOwnPropertySymbols(obj)。
-
Reflect.ownKeys(obj)。
我們來詳細看下這 5 種方法的使用方法和差異性。
定義一個擁有範例屬性、繼承屬性的物件,其中包含 Symbol 屬性、可列舉屬性、不可列舉屬性,覆蓋全部的場景,用來測試這 5 種屬性遍歷方法的差異。
// 定義父類別
function Animal(name, type) {
this.name = name;
this.type = type;
}
// 定義子類
function Cat(age, weight) {
this.age = age;
this.weight = weight;
this[Symbol('one')] = 'one';
}
// 子類繼承父類別
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
// 生成子類的範例
let cat = new Cat(12, '10kg');
// 範例增加可列舉屬性
Object.defineProperty(cat, 'color', {
configurable: true,
enumerable: true,
value: 'blue',
writable: true
});
// 範例增加不可列舉屬性
Object.defineProperty(cat, 'height', {
configurable: true,
enumerable: false,
value: '20cm',
writable: true
});
範例 cat 具有的屬性如下所示:
範例屬性: age, weight, Symbol('one'), color
繼承屬性: name, type
可列舉屬性:age, weight, color
不可列舉屬性: height
Symbol 屬性: Symbol('one')
for...in
for...in 用於遍歷物件自身和繼承的可列舉屬性(不包含 Symbol 屬性)。
for (let key in cat) {
console.log(key);
}
// 'age', 'weight', 'color', 'name', 'type'
輸出的結果中包含了自身可列舉屬性 age、weight、color 和繼承屬性 name、type,沒有包含不可列舉屬性 height 和 Symbol 屬性 Symbol('one')。
Object.keys() 函數
Object.keys() 函數返回一個陣列,包含物件自身所有可列舉屬性,不包含繼承屬性和 Symbol 屬性。
Object.keys(cat); // [ 'age', 'weight', 'color' ]
輸出的結果中只包含了自身可列舉屬性 age、weight、color,沒有包含繼承屬性 name、type,以及不可列舉屬性 height 和 Symbol 屬性 Symbol('one')。
Object.getOwnPropertyNames() 函數
Object.getOwnPropertyNames() 函數返回一個陣列,包含物件自身所有可列舉屬性和不可列舉屬性,不包含繼承屬性和 Symbol 屬性。
Object.getOwnPropertyNames(cat); // [ 'age', 'weight', 'color', 'height' ]
輸出的結果中包含了自身可列舉屬性 age、weight、color,以及自身不可列舉的 height 屬性,沒有包含繼承屬性 name 和 type,以及 Symbol 屬性 Symbol('one')。
Object.getOwnPropertySymbols() 函數
Object.getOwnPropertySymbols() 函數返回一個陣列,包含物件自身所有 Symbol 屬性,不包含其他屬性。
Object.getOwnPropertySymbols(cat); // [ Symbol('one') ]
輸出的結果中只包含了物件自身 Symbol 屬性,沒有其他屬性。
Reflect.ownKeys() 函數
Reflect.ownKeys() 函數返回一個陣列,包含可列舉屬性、不可列舉屬性以及 Symbol 屬性,不包含繼承屬性。
Reflect.ownKeys(cat); // [ 'age', 'weight', 'color', 'height', Symbol('one') ]
輸出的結果中包含了自身可列舉屬性 age、weight、color,不可列舉屬性 height,以及 Symbol 屬性 Symbol('one'),沒有包含繼承屬性 name 和 type。