关于javascript:javascript的六种继承方式

30次阅读

共计 2883 个字符,预计需要花费 8 分钟才能阅读完成。

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

正文完
 0