javascript的六种继承方式

Posted 小铭同学丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript的六种继承方式相关的知识,希望对你有一定的参考价值。

1.原型链式继承

function Parent() {
    this.name = \'Parent\';
}

Parent.prototype.introduce = function () {
    console.log(this.name);
};

function Child() {
    this.name = \'Child\';
}

Child.prototype = new Parent();

const children = new Child();

children.introduce();// =>  \'Child\'
console.log(children instanceof Parent); // => true

原理:子类通过prototype继承父类实例的共享属性和方法。

缺点:

1、所有实例都会共享父类的实例,如若共享属性中有引用数据,其中一个子类实例修改,则全部子类实例都会发生修改。

2、继承单一性,只能继承共享到同一父类实例。

3、子类继承无法向父类传参。

2.构造函数式继承

function Parent(name) {
    this.name = name;
}

Parent.prototype.introduce = function () {
    console.log(this.name);
};

function Child(name) {
    Parent.call(this,name);
}


const children = new Child(\'Child\');

console.log(children.name);// => \'Child\'
children.introduce(); // => 报错
console.log(children instanceof Parent); // => false

原理:通过改变父类构造函数的this指向来将父类的构造函数的共享属性/方法复制到子类。

缺点:

1、每次新生成子类实例都会调用父类的构造函数,所以每个子类实例都是独体。

2、只能继承父类构造函数中的静态属性/方法,不能继承父类的原型。

3.组合式继承

function Parent(name) {
    this.name = name;
}

Parent.prototype.introduce = function () {
    console.log(this.name);
};

function Child(name) {
    Parent.call(this,name);
}

Child.prototype = new Parent();

const children = new Child(\'Child\');

children.introduce();// =>  \'Child\'
console.log(children instanceof Parent); // => true

原理:通过改变父类构造函数this指向,复制父类构造函数里的共享属性/方法,然后通过prototype继承父类实例的原型。

缺点:

1、一次继承中调用了两次父类,消耗内存。

4.原型式继承

function Parent(name) {
    this.name = name;
}

Parent.prototype.introduce = function () {
    console.log(this.name);
};

function Child(obj) {
    function Transition () { }
    Transition.prototype = obj;
    return new Transition();
}

const parent1 = new Parent(\'parent\');
const children = new Child(parent1);

children.introduce();// =>  \'Child\'
console.log(children instanceof Parent); // => true

原理:通过用一个函数包装,在函数体内用过渡函数继承父类实例,这个过渡函数就变成了可以随意添加属性的实例或者对象。核心原理和Object.create()一样,类似于复制一个对象。

缺点:

1、无法实现复用,新实例的属性都是后面添加的。

5.寄生式继承

function Parent(name) {
    this.name = name;
}

Parent.prototype.introduce = function () {
    console.log(this.name);
};

function Child ( obj ) {
    let children = Object.create( obj );
    children.name = "Child";
    return children;
}

const parent1 = new Parent(\'Parent\');
const children = new Child( parent1 );

children.introduce();// =>  \'Parent\'
console.log(children instanceof Parent); // => true

原理:进一步将原型式继承封装成一个函数,进而进行扩展。

缺点:

1、只是通过复制对象属性方法,没有用到prototype,不是意义上的继承,也无法复用。

6.寄生式组合继承

function Parent(name) {
    this.name = name;
    this.type = \'Parent\';
}

Parent.prototype.introduce = function () {
    console.log(this.name);
};

Parent.prototype.clone = function () {
    return new this.constructor();
}

const transition = Object.create( Parent.prototype ); // 生成父类prototype副本,构造函数指向父类

function Child ( name) {
    Parent.call( this, name );// 继承父类构造函数的属性
    this.type = \'children\'; // 新增构造属性属性
}

Child.prototype = transition; // 通过原型链继承式同时也继承了实例指向

console.log(Child.prototype.constructor); // 未修改继承的父类实例指向  [Function:Parent]

transition.constructor = Child; // 修改继承的父类实例指向

console.log( Child.prototype.constructor ); // 已经修改继承的父类继承指向  [Function:Child]


const children = new Child( \'Child\' );

let Instantion = children.clone(); // 如果没有修复实例指向,则报错,因为子类没有该方法

console.log( Instantion.type );
// 如若没有修正实例的指向,此处打印为 Prarent
// 如若修正实例的指向,此处打印为 children

children.introduce();// =>  \'Parent\'
console.log( children instanceof Parent ); // => true

以上是关于javascript的六种继承方式的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript常见的六种继承方式

javascript的六种继承方式

javascript 中实现继承的六种方式

js学习总结----深入扩展原型链模式常用的六种继承方式

JS定义类的六种方式详解

JS定义类的六种方式详解