對象遍歷
為了便于對象遍歷的測試,我在下面定義了一個測試對象 obj。
測試對象
// 為 Object 設置三個自定義屬性(可枚舉)Object.prototype.userProp = 'userProp';Object.prototype.getUserProp = function() { return Object.prototype.userProp;};// 定義一個對象,隱式地繼承自 Object.prototypevar obj = { name: 'percy', age: 21, [Symbol('symbol 屬性')]: 'symbolProp', unEnumerable: '我是一個不可枚舉屬性', skills: ['html', 'css', 'js'], getSkills: function() { return this.skills; }};// 設置 unEnumerable 屬性為不可枚舉屬性Object.defineProperty(obj, 'unEnumerable', { enumerable: false});ES6 之后,共有以下 5 種方法可以遍歷對象的屬性。
for…in: 遍歷對象自身的和繼承的可枚舉屬性(不含 Symbol 類型的屬性)
for (let key in obj) { console.log(key); console.log(obj.key); // wrong style console.log(obj[key]); // right style}不要使用 for…in 來遍歷數組,雖然可以遍歷,但是如果為 Object.prototype 設置了可枚舉屬性后,也會把這些屬性遍歷到,因為數組也是一種對象。
Object.keys(obj):返回一個數組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含 Symbol 類型的屬性)
Object.keys(obj); // ["name", "age", "skills", "getSkills"]
Object.getOwnPropertyNames(obj):返回一個數組,包含對象自身的所有屬性(不含 Symbol 類型的屬性,不包含繼承屬性,但是包括不可枚舉屬性)
Object.getOwnPropertyNames(obj);// ["name", "age", "unEnumerable", "skills", "getSkills"]
Object.getOwnPropertySymbols(obj):返回一個數組,包含對象自身的所有 Symbol 類型的屬性(不包括繼承的屬性)
Object.getOwnPropertySymbols(obj);// [Symbol(symbol 屬性)]
Reflect.ownKeys(obj):返回一個數組,包含對象自身的所有屬性(包含 Symbol 類型的屬性,還有不可枚舉的屬性,但是不包括繼承的屬性)
Reflect.ownKeys(obj);// ["name", "age", "unEnumerable", "skills", "getSkills", Symbol(symbol 屬性)]
以上的5種方法遍歷對象的屬性,都遵守同樣的屬性遍歷的次序規則
首先遍歷所有屬性名為數值的屬性,按照數字排序 其次遍歷所有屬性名為字符串的屬性,按照生成時間排序 最后遍歷所有屬性名為Symbol值的屬性,按照生成時間排序如何判斷某個屬性是不是某個對象自身的屬性呢?
用 in 操作符(不嚴謹,它其實判定的是這個屬性在不在該對象的原型鏈上)
'age' in obj; // true'userProp' in obj; // true (userProp 是 obj 原型鏈上的屬性)'name' in Object; // true // 上面這個也是 true 的原因是,Object 是一個構造函數,而函數恰巧也有一個 name 屬性Object.name; // 'Object'Array.name; // 'Array'
新聞熱點
疑難解答
圖片精選