對象屬性分類
對于屬性遍歷而言玖绿,可以將對象屬性分為是否可枚舉斑匪、是否為繼承 兩種
let ary = ['a', 'b', 'c']
在 ary
數(shù)組中蚀瘸,可枚舉屬性是對應(yīng)的索引 0, 1, 2
庶橱,不可枚舉的是 length
對象屬性配置
對象中,屬性是否可枚舉可以通過 Object.defineProperty
設(shè)定
class Car { // 創(chuàng)建類
constructor(brand, model, color) {
this.brand = brand
this.model = model
this.color = color
}
}
let mycar = new Car('Tesla', 'model 3', 'red') // 沒有的話 new 一個(gè)就好啦
Object.defineProperty(mycar ,"color",{
value: "red",
enumerable: false, //是否可枚舉, 默認(rèn)值 false
configurable: false, //是否可配置布近,默認(rèn)值 false
writable: false, //沒有 writable 使用默認(rèn)值 false
});
對象創(chuàng)建完成撑瞧,在控制臺內(nèi)通過顏色可以判斷不可枚舉屬性预伺,但作為一個(gè)嚴(yán)謹(jǐn)?shù)某绦騿T,當(dāng)然需要更科學(xué)的辦法啦
可枚舉屬性
Object.keys(o)
按順序遍歷返回一個(gè)數(shù)組脏嚷,其包含對象 o 自身(不包括原型)的所有可枚舉屬性的名稱
Object.keys(mycar)
// ["brand", "model"]
for...in循環(huán)
該方法會依次訪問一個(gè)對象及其原型鏈中所有可枚舉的屬性父叙,就當(dāng)前對象而言肴裙,效果較Object.keys(o) 相同
for (let i in my car) {
console.log(i)
}
// brand
// model
但如果繼承的原型鏈上已有可枚舉屬性蜻懦,原型上的 'foo'
也被遍歷進(jìn)來了
mycar.__proto__.foo = 'foo'
for (let i in mycar) {
console.log(i)
}
// brand
// model
// foo
Object.keys(mycar)
// ["brand", "model"]
所以得再過濾下宛乃,使用 hasOwnProperty
過濾繼承屬性,返回布爾值
for(let i in mycar){
// 此處可以使用 mycar.hasOwnProperty(i)乔煞,
// 以安全的角度看用 Object.prototype.hasOwnProperty.call(mycar,i)
if(Object.prototype.hasOwnProperty.call(mycar,i)){
console.log(i)
}
}
// brand
// model
所有屬性
Object.getOwnPropertyNames(o)
該方法返回一個(gè)數(shù)組渡贾,其包含對象 o 所有自有的屬性(無論是否可枚舉)的名稱
mycar.__proto__.foo = 'foo'
Object.getOwnPropertyNames( mycar )
// ["brand", "model", "color"]
不可枚舉屬性
那既然可枚舉和全部自有屬性都有辦法獲取空骚,要獲取不可枚舉屬性就簡單了
mycar.__proto__.foo = 'foo'
Object.getOwnPropertyNames(mycar).filter(val =>
!Object.keys(mycar).includes(val)
)
// ["color"]
遍歷順序
值得注意的是,Object.keys()
遍歷順序?qū)Σ煌瑢傩灶愋蜁r(shí)熬甚,先后順序不同
let a = {'zz': 3, 3: 99, 1: 100, 'bb': 0}
//["1", "3", "zz", "bb"]
引用 MDN 中說明:
一個(gè)對象的屬性名可以是任何有效的 JavaScript 字符串肋坚,或者可以被轉(zhuǎn)換為字符串的任何類型智厌,包括空字符串
也就是說,對象的所有屬性都會通過轉(zhuǎn)換變化為字符串敷扫,而由數(shù)字轉(zhuǎn)過來字符串排序優(yōu)先(此處略有疑問)而 for...in循環(huán)
遍歷順序與 Object.keys()
一致
// 同時(shí)創(chuàng)建多個(gè)變量
let myObj = new Object(),
str = "myString",
rand = Math.random(),
obj = new Object(),
num1 = 23,
num2 = 99,
ary = [1,2];
myObj.type = "Dot syntax";
myObj["date created"] = "String with space";
myObj[str] = "String value";
myObj[rand] = "Random Number";
myObj[obj] = "Object";
myObj[ary] = 'here is a ary'
myObj[num2] = 'here is a number_2'
myObj[""] = "Even an empty string";
myObj[num1] = 'here is a number_1'
for(let i in myObj){console.log(typeof i,' --- ', i, ' --- ',myObj[i])}
// 去下圖...
小結(jié)
-
遍歷自有屬性:
- 可枚舉:
-
Object.keys(o)
遍歷 對象o
上的所有可枚舉自有屬性 -
for...in
遍歷對象o
上所有自有屬性(包括繼承屬性)
-
- 可枚舉 + 不可枚舉:
-
Object.getOwnPropertyNames(o)
遍歷對象o
上所有自有屬性(無論是否可枚舉)
-
- 不可枚舉:
- 通過
Object.getOwnPropertyNames(o)
獲取所有自有屬性,在通過Object.keys(mycar)
獲取 自有可枚舉屬性合溺,在使用filter
過濾
- 通過
- 可枚舉:
遍歷順序:以屬性設(shè)定時(shí)順序?yàn)闇?zhǔn)棠赛,數(shù)字例外優(yōu)先排序(僅參考)
- 判斷是否屬于自有屬性(返回布爾值):
- 普通做法
mycar.hasOwnProperty(i)
- 更安全的做法
Object.prototype.hasOwnProperty.call(mycar,i)
- 普通做法
統(tǒng)計(jì)表
源自 MDN ,關(guān)于屬性的 枚舉,繼承 統(tǒng)計(jì)表