JavaScript 中的几种继承实现

59 阅读2分钟

背景:

什么是继承: 如果B继承了A,那么B就是A的子类,好处是子类可以使用父类的方法和属性,可覆盖,可重写

继承的实现:

1组:

  • 原型链继承:
    • 如果原型上有引用对象: 会共享内存
  • 构造函数继承:
    • 解决了1的问题,但无法继承 父类 原型对象 上的方法和属性
  • 组合继承:前两个的组合,但子类的原型上有父类方法属性,子类上也有父类方法属性,执行了2遍

2组:使用Object.create(指定的原型对象)进行继承

  • 原型继承:存在共享对象问题
  • 寄生继承:语法上优化1,但是还是有共享的问题
  • 寄生组合继承(最优解):ES6的extends就是这个实现,为了解决1组的问题,也为了解决2组前两种方式

代码:

  1. 父类:
function Parent(){
    this.arr = [1,2,3];
    this.name = 'parent1';
}
Parent.prototype.getName = function () {
    return this.name;
}

Parent.prototype.school = {
    name:"小学"
}

1组代码:

1.1 原型链继承:

ProChainChild.prototype = new Parent();

function ProChainChild(){
    this.name = '我是子类'
}
// !!!! 子类实现了对父类的继承
ProChainChild.prototype = new Parent();

let pro_child1 = new ProChainChild();
let pro_child2 = new ProChainChild();

pro_child1.arr.push(4);

console.log("1.原型链继承:原型属性会被共享", pro_child1.arr, pro_child2.arr, pro_child1.school);  

1.2 构造函数继承:为了解决1使用构造函数继承:

Parent.call(this);

// !!!!!子类对父类的继承
function Child1(){
    Parent.call(this);
    this.name = '我是构造函数继承的子类';
}

let new_child = new Child1();
let new_child1 = new Child1();

new_child1.arr.push(4)
console.log("2.构造函数继承:不继承父类原型链上的属性和方法", new_child.arr, new_child1.arr, new_child.school)


1.3 组合继承(1+2):

Parent.call(this); +ChildGroup.prototype = new Parent();

function ChildGroup(){
    // !!!!! 子类实现继承2
    Parent.call(this);
    this.name = '我是组合继承的子类';
}
 // !!!!! 子类实现继承1
ChildGroup.prototype = new Parent();

let group_child = new ChildGroup();
let group_child1 = new ChildGroup();
group_child1.arr.push(4);

console.log("3.组合继承:执行2次parent", group_child.arr, group_child1.arr, group_child.school)



2组代码:

2.1 寄生组合继承:最优解

为了解决组1的所有问题Parent.call(this);+ Object.create(Parent.prototype)


function ChildParGroup(){
    // !!!!! 子类实现继承
    Parent.call(this);
    this.name = '我是寄生组合继承的子类';
}

ChildParGroup.prototype.age = 18;
// !!!!! 子类实现继承
ChildParGroup.prototype = Object.create(Parent.prototype); // 创建一个空对象, 并指向某个原型对象

ChildParGroup.prototype.constructor = ChildParGroup;

let pro_group_child = new ChildGroup();
let pro_group_child1 = new ChildGroup();
pro_group_child1.arr.push(4);

console.log("4.寄生组合继承:child 原型上的属性和方法会丢失", pro_group_child.arr, pro_group_child1.arr, pro_group_child.school, pro_child1.age)

2.2 原型式继承:

有共享问题

let parent4 = {
    name: "parent4",
    friends: ["p1", "p2", "p3"],
    getName: function() {
      return this.name;
    }
  };
  let person4 = Object.create(parent4);

2.3 寄生式继承:

2.2 的优化,但依然有共享问题

let parent5 = {
    name: "parent5",
    friends: ["p1", "p2", "p3"],
    getName: function() {
        return this.name;
    }
};

function clone(original) {
    let clone = Object.create(original);
    clone.getFriends = function() {
        return this.friends;
    };
    return clone;
}