继承和原型链

52 阅读2分钟

原型链

JavaScript的每个对象都有__proto__或称[[Prototype]]内部属性,储存引用另一个对象的,层层向上引用直到null。这条层层引用所行成的链,就是原型链。并且可以基于原型链进行基于对象的编程

e.g.

const o = {
  a: 1,
  b: 2,
  // __proto__ 设置了 [[Prototype]]。它在这里被指定为另一个对象字面量。
  __proto__: {
    b: 3,
    c: 4,
  },
};

原型链为{ a: 1, b: 2 } ---> { b: 3, c: 4 } ---> Object.prototype ---> null 其中o.[[prototype]].b为2,访问的属性为原型链第一个有该属性的对象,即访问到了就不会继续向下访问。

__proto__ [[Prototype]]

Object.getPrototypeOf() 和 [Object.setPrototypeOf()]访问

⚠️区别function.prototype,function.prototype是function实例的[[Prototype]]

this

this会指向当前的对象

const parent = {
  value: 2,
  method() {
    return this.value + 1;
  },
};

console.log(parent.method()); // 3
// 当调用 parent.method 时,“this”指向了 parent

// child 是一个继承了 parent 的对象
const child = {
  __proto__: parent,
};
console.log(child.method()); // 3
// 调用 child.method 时,“this”指向了 child。
// 又因为 child 继承的是 parent 的方法,
// 首先在 child 上寻找“value”属性。但由于 child 本身
// 没有名为“value”的自有属性,该属性会在
// [[Prototype]] 上被找到,即 parent.value。

child.value = 4; // 在 child,将“value”属性赋值为 4。
// 这会遮蔽 parent 上的“value”属性。
// child 对象现在看起来是这样的:
// { value: 4, __proto__: { value: 2, method: [Function] } }
console.log(child.method()); // 5
// 因为 child 现在拥有“value”属性,“this.value”现在表示
// child.value
构造函数 Constructor

构造函数就是给新建的对象设置__proto__。同时可以重写为类(语法糖) e.g.

const boxPrototype = {
  getValue() {
    return this.value;
  },
};

const boxes = [
  { value: 1, __proto__: boxPrototype },
  { value: 2, __proto__: boxPrototype },
  { value: 3, __proto__: boxPrototype },
];

使用构造函数简化:

//构造函数
function Box(value){
	this.value=value
}
box.prototype.getValue=function(){
	return this.value
}
const boxes=[new Box(1),new Box(2),new Box(3)]
prototype属性赋值
  • constructor 属性 使用Object.setPrototypeOf赋值,直接赋值新对象会覆盖掉Constructor.prototype除原型外的constructor 属性
function Base() {}
function Derived() {}
// 将 `Derived.prototype` 重新赋值为 `Base.prototype`,
// 以作为其 `[[Prototype]]` 的新对象
// 请不要这样做——使用 Object.setPrototypeOf 来修改它
Derived.prototype = Object.create(Base.prototype);
new 的方式继承和 Object.create() 实现的区别

new 的方式继承会执行constructor里的代码 Object.create 会直接创造新对象

检查

仅检查属性是否为 undefined 是不够的。该属性很可能存在,但其值恰好设置为 undefined

基于原型链的继承

当访问一个对象的属性时,在该对象搜索结束后,会沿着原型链继续搜索,直到搜索到该属性或搜索到null返回为undefined。