js继承与属性

2019-11-07  本文已影响0人  疯狂吸猫

相关知识点链接与参考链接:
一篇文章理解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)
image.png
对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)]
上一篇 下一篇

猜你喜欢

热点阅读