# JS 继承

# 原型链继承

缺点:子类共享父类的状态

function Parent() {
  this.path = []
}
function Child() {
  
}
Child.prototype = new Parent(); // 原型链继承
const child1 = new Child();
const child2 = new Child();
child1.path.push(1);
console.log(child1.path===child2.path); // 原型链继承方式所有子类共享父类的状态

# 构造函数继承(借助 call 继承)

缺点:子类无法共享父类原型方法

function Parent1() {
  this.name = "parent1";
}
Parent.prototype.getName = function () {
  return this.name;
}
function Child1() {
  Parent1.call(this);
  this.age = 18;
}
const child3 = new Child1();
child3.getName();  // 报错,借助 call 继承无法获取父类原型上的方法。

# 组合继承(原型继承 + call 继承)

缺点:父类多进行一次构造,造成了性能开销

function Parent2() {
  this.name = "parent2"
}
Parent2.prototype.getName = function () {
  return this.name;
}
function Child2() {
  Parent2.call(this);
  this.age = 18;
}
Child2.prototype = new Parent2();
Child2.prototype.constructor = Parent2;
const child4 = new Child2();
const child5 = new Child2();

# 原型式继承(借助 Object.create)

缺点:子实例可能会篡改父实例的属性内容

let parent3 = {
  name:"parent3",
  path:["p1","p2"],
  getName:function () {
    return this.name;
  }
}
let child6 = Object.create(parent3)
child6.name = "child6";
child6.path.push("p6");
let child7 = Object.create(parent3);
child7.path.push("p7");
console.log(child6.name); // 子实例重写属性
console.log(child6.name===parent3.getName());
console.log(child7.name); // 子实例继承属性
console.log(child6.path===child7.path); // 子实例共享父实例的属性

# 寄生式继承(接着 Object.create)

缺点:子实例可能会篡改父实例的属性内容

let parent4 = {
  name:"parent4",
  path:["p4"],
  getName:function () {
    return this.name;
  }
}
function clone1(original) {
  let clone = Object.create(original);
  clone.getPath = function () {
    return this.path;
  }
  return clone;
}
let child8 = clone1(parent4);
console.log(child8.getName());
console.log(child8.getPath());

# 寄生组合式继承(extends 关键字做法)

function clone(parent,child) {
  child.prototype = Object.create(parent.prototype);
  child.prototype.constructor = child;
}
function Parent5() {
  this.name = "parent5";
  this.paly = [1,2,3];
}
Parent5.prototype.getName = function () {
  return this.name;
}
function Child6() {
  // 子类构造函数中调用父类构造函数,组合的方式添加属性
  Parent5.call(this);
  this.friends = "child6";
}
// 子类原型是父类原型的实例
clone(Parent5,Child6);
Child6.prototype.getFriends = function () {
  return this.friends;
}
let person6 = new Child6();
console.log(person6);
console.log(person6.getName());
console.log(person6.getFriends());

# 总结

sequenceDiagram
	Note over 构造函数继承 : 借助call
	Note over 原型链继承 : 借助prototype
	Note over 构造函数继承,原型链继承 : 不使用Object.create
	Note over 组合继承: 构造函数继承 + 原型链继承
	Note over 寄生式继承 : 使用Object.create
	Note over 寄生组合式继承 : 寄生式继承 + 组合式继承
更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

dmq 微信支付

微信支付

dmq 支付宝

支付宝