JS实现继承的几种方式

93 阅读1分钟

1:构造函数继承

function Parent1(){
  this.name = "parent1";
}
Parent1.prototype.age = 18;
function Child1(){
  Parent1.call(this);//核心:call,apply
  this.type = "child1";
}
let child1 = new Child1;
console.log(child1);
console.log(child1.age);

缺点:只能继承父类构造函数中的属性和方法,对于原型对象无法继承。

2:原型继承

function Parent2(){
  this.name = "parent2";
  this.nums = [1,2,6];
}
function Child2(){
  this.type = "child2";
}
Child2.prototype = new Parent2;//核心:prototype
let child2_1 = new Child2();
let child2_2 = new Child2();
child2_1.nums.push(66);
console.log(child2_1,child2_2);

缺点:所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改!)

3:组合继承

function Parent3(){
  this.name = "parent3";
  this.nums = [1,2,3];
}
function Child3(){
  Parent3.call(this);//核心
  this.type = "child3";
}
Child3.prototype = new Parent3;//核心:prototype
let child3_1 = new Child3();
let child3_2 = new Child3();
child3_1.nums.push(66);
console.log(child3_1,child3_2);

缺点:child3的 constructor 指向Parent3了

4:组合继承优化

function Parent4(){
  this.name = "parent4";
  this.nums = [1,2,3];
}
function Child4(){
  Parent4.call(this);
  this.type = "child4";
}
Child4.prototype = Object.create(Parent4.prototype);

Child4.prototype.constructor = Child4;
let child4_1 = new Child4();
let child4_2 = new Child4();
child4_1.nums.push(66);
console.log(child4_1,child4_2);

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。

5:es6实现继承

class Animal {
    constructor(name){
        this.name = name;
    }
    eat(){
        console.log("eat");
    }
}

class Dog extends Animal {
    constructor(name){
        super(name);
        this.type = "dog"
    }

    say(){
        console.log(this.name +"wang wang");
    }
}

const dog  = new Dog("doubao")
dog.say();
dog.eat();