JS实现继承的6种方式

1,976 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情

今天又是忙碌的一天,就不写长篇大论了,继续分享javascript基础知识,本篇是关于继承的,面试八股文,希望大家可以拿到自己满意的offer。

实现继承的6种方式

原型链

脑图

原型链继承

function Parent() {
    this.name = 'parent';
    this.arr = [1, 2, 3];
}

Parent.prototype.getName = function() {
    return this.name;
}

function Child() {
}

Child.prototype = new Parent();
const child1 = new Child();
const child2 = new Child();
child1.arr.push(999);
console.log('child1', child1);
console.log('child2', child2);

缺点:

  1. 原型上的变量被所有实例共享,当一个实例改变引用类型里面的值时会影响其他实例
  2. 不能向父类构造函数传参

构造函数继承

优化了原型链继承共享原型变量的问题,也可以向父类构造函数传参

function Parent() {
    this.name = 'parent';
    this.arr = [1, 2, 3];
}

Parent.prototype.getName = function() {
    return this.name;
}

function Child() {
    Parent.call(this); //* 调用父类的构造器
}

const child1 = new Child();
const child2 = new Child();
child1.arr.push(999);
console.log('child1', child1);
console.log('child2', child2)

缺点:

  1. 无法复用父类的方法

组合继承

把原型链继承和构造器继承结合起来

function Parent() {
    console.log('call Parent');
    this.name = 'parent';
    this.arr = [1, 2, 3];
}

Parent.prototype.getName = function() {
    return this.name;
}


function Child() {
    Parent.call(this); //* 1
}

Child.prototype = new Parent(); //* 2
const child1 = new Child();
const child2 = new Child();
child1.arr.push(999);
console.log('child1', child1);
console.log('child2', child2);

缺点:

  1. 多调用了一次构造函数

原型继承

以上是基于函数的继承,现在基于现有的对象继承

let parent = {
    name: 'parent'
}

// 通过Object.create()
let child = Object.create(parent);
// 或者通过下面的方法create也是一样
function create(parent) {
    function F() {};
    F.prototype = parent;
    return new F();
}
console.log(child);

缺点:

  1. 也是共享了父类的变量

寄生式继承

在原型继承的基础上增强

let parent = {
name: 'parent'
}
// 通过Object.create()
function extend(parent) {
    let child = Object.create(parent);
    child.getName = function() { // *只是上面的增强
        return this.name;
    }
    return child;
}
console.log(child);

寄生组合式继承

优化了组合继承需要多调一次构造方法的缺点

同时也不会共享父类的变量

也能做到函数的复用

function Parent() {
    this.name = 'parent';
}
Parent.prototype.getName = function() {
    return this.name;
}
function Child() {
    Parent.call(this);
    this.age = 18;
}
function extend(Child, Parent) {
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.contructor = Child;
}
extend(Child, Parent);
const obj = new Child();

babel将ES6的extend转换成ES5代码的时候,使用的就是寄生组合继承