js继承与属性
相关知识点链接与参考链接:
一篇文章理解JS继承——原型链/构造函数/组合/原型式/寄生式/寄生组合/Class extends
js继承(原型链、构造、组合、寄生组合)
详解forin,Object.keys和Object.getOwnPropertyNames的区别
1.原型链上的属性与对象上的属性重名
关于对象上与原型链上属性同名的情况基本介绍可以参见《JavaScript高级程序设计》P149
对象自己没有但是从在__proto__上继承的属性,如果对其进行赋值的修改,那么会在对象上添加这个属性。但是如果不是进行赋值的修改,那么原型链上的属性被修改。
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进行push操作就相当于获取到原型链上的hobby再对这个hobby调用函数push,所以原型链上的hobby改变
即使在'同名覆盖'的原则下,我们还是有可能对原型链上的属性做出误改,所以使用student.hasOwnProperty()来判断属性在原型链或者对象上就显得尤为重要
2.for in,Object.keys和Object.getOwnPropertyNames
注意:本次讨论不包括Symbol。因为Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。
参考:详解forin,Object.keys和Object.getOwnPropertyNames的区别
Object知识点:js继承实现之Object.create
属性是否可枚举、属性描述符知识点:读懂属性描述符、对象的扩展-属性的可枚举和遍历
2.1 for in与Object.keys都是为属性的是否可枚举所服务
2.1.1 for in
for in 可以获取对象本身、以及原型链上所有可枚举的属性。并且采用同名覆盖,当对象本身与原型链上拥有同名属性时,仅获取对象本身的属性。
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的补充(也作为 Object.getOwnPropertyNames()的补充)
只能获取到可枚举、在对象本身上的属性
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()与是否可枚举无关,会获得对象本身上的所有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知识点:es6-Symbol
Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。
但是,它也不是私有属性,有一个Object.getOwnPropertySymbols()方法,可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 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)]