相關(guān)知識點(diǎn)鏈接與參考鏈接:
一篇文章理解JS繼承——原型鏈/構(gòu)造函數(shù)/組合/原型式/寄生式/寄生組合/Class extends
js繼承(原型鏈筷登、構(gòu)造魂爪、組合先舷、寄生組合)
詳解forin,Object.keys和Object.getOwnPropertyNames的區(qū)別
1.原型鏈上的屬性與對象上的屬性重名
關(guān)于對象上與原型鏈上屬性同名的情況基本介紹可以參見《JavaScript高級程序設(shè)計》P149
對象自己沒有但是從在__proto__上繼承的屬性,如果對其進(jìn)行賦值的修改,那么會在對象上添加這個屬性滓侍。但是如果不是進(jìn)行賦值的修改,那么原型鏈上的屬性被修改蒋川。
function Person() {
this.name="Jack",
this.friends=["friend1", "friend2", "friend3"],
this.hobby=["hobby1","hobby2"]
}
function Student() {
}
Student.prototype = new Person()
let student1=new Student()
let student2=new Student()
student1.name="Robin"
student1.friends=[]
student2.hobby.push("hobby3")
console.log(student1.name)
console.log(student1.friends)
console.log(student1.hobby)
console.log("____________________________")
console.log(student2.name)
console.log(student2.friends)
console.log(student2.hobby)
對student1.name賦值,不會影響到student2.name也就是不會影響到原型鏈
對引用類型的student1.fridends賦值也不會影響到原型鏈
但是對引用類型student1.hobby進(jìn)行push操作就相當(dāng)于獲取到原型鏈上的hobby再對這個hobby調(diào)用函數(shù)push撩笆,所以原型鏈上的hobby改變
即使在'同名覆蓋'的原則下捺球,我們還是有可能對原型鏈上的屬性做出誤改,所以使用student.hasOwnProperty()來判斷屬性在原型鏈或者對象上就顯得尤為重要
2.for in夕冲,Object.keys和Object.getOwnPropertyNames
注意:本次討論不包括Symbol氮兵。因?yàn)镾ymbol 作為屬性名,遍歷對象的時候歹鱼,該屬性不會出現(xiàn)在for...in泣栈、for...of循環(huán)中,也不會被Object.keys()弥姻、Object.getOwnPropertyNames()秩霍、JSON.stringify()返回。
參考:詳解forin蚁阳,Object.keys和Object.getOwnPropertyNames的區(qū)別
Object知識點(diǎn):js繼承實(shí)現(xiàn)之Object.create
屬性是否可枚舉铃绒、屬性描述符知識點(diǎn):讀懂屬性描述符、對象的擴(kuò)展-屬性的可枚舉和遍歷
2.1 for in與Object.keys都是為屬性的是否可枚舉所服務(wù)
2.1.1 for in
for in 可以獲取對象本身螺捐、以及原型鏈上所有可枚舉的屬性颠悬。并且采用同名覆蓋矮燎,當(dāng)對象本身與原型鏈上擁有同名屬性時,僅獲取對象本身的屬性赔癌。
let parent = Object.create(Object.prototype, {
a: {
value: 1,
writable: true,
enumerable: true,
configurable: true
},
b: {
value: 1.1,
writable: true,
enumerable: true,
configurable: true
},
});
let child = Object.create(parent, {
b: {
value: 2,
writable: true,
enumerable: true,
configurable: true
},
c: {
value: 3,
writable: true,
enumerable: false,
configurable: true
}
});
for(let key in child)
{
console.log(`key:${key},value:${child[key]}`)
}
2.1.2 Object.keys()作為for in的補(bǔ)充(也作為 Object.getOwnPropertyNames()的補(bǔ)充)
只能獲取到可枚舉诞外、在對象本身上的屬性
let parent = Object.create(Object.prototype, {
a: {
value: 1,
writable: true,
enumerable: true,
configurable: true
}
});
let child = Object.create(parent, {
b: {
value: 2,
writable: true,
enumerable: true,
configurable: true
},
c: {
value: 3,
writable: true,
enumerable: false,
configurable: true
}
});
console.log(Object.keys(child));
2.2 Object.getOwnPropertyNames()與是否可枚舉無關(guān),會獲得對象本身上的所有key值
let parent = Object.create(Object.prototype, {
a: {
value: 1,
writable: true,
enumerable: true,
configurable: true
}
});
let child = Object.create(parent, {
b: {
value: 2,
writable: true,
enumerable: true,
configurable: true
},
c: {
value: 3,
writable: true,
enumerable: false,
configurable: true
}
});
console.log(Object.getOwnPropertyNames(child));
3.Symbol作為屬性名
symbol知識點(diǎn):es6-Symbol
Symbol 作為屬性名灾票,遍歷對象的時候峡谊,該屬性不會出現(xiàn)在for...in、for...of循環(huán)中刊苍,也不會被Object.keys()既们、Object.getOwnPropertyNames()、JSON.stringify()返回正什。
但是啥纸,它也不是私有屬性,有一個Object.getOwnPropertySymbols()方法婴氮,可以獲取指定對象的所有 Symbol 屬性名斯棒。該方法返回一個數(shù)組,成員是當(dāng)前對象的所有用作屬性名的 Symbol 值主经。
const obj = {};
let a = Symbol('a');
let b = Symbol('b');
obj[a] = 'Hello';
obj[b] = 'World';
const objectSymbols = Object.getOwnPropertySymbols(obj);
objectSymbols
// [Symbol(a), Symbol(b)]