关于JS中的继承

166 阅读2分钟

JS继承可以通过原型和 class 来实现,对于class,JS中其实并不存在类,class只是语法糖,本质还是函数。

class Person {};
Person instanceof Function; // true

1、组合继承

组合继承是最常用的继承方式

function Parent(value) {
  this.val = value;
};
Parent.prototype.getValue = function() {
  console.log(this.val);
};
function Child(value) {
  Parent.call(this, value)
};
Child.prototype = new Parent();    

const child = new Child(1);

child.getValue(); // 1
child instanceof Parent // true

以上继承方式核心是在子类的构造函数中通过 Parent.call(this) 继承父类的属性,然后改变子类的原型为 new parent() 来继承父类的函数。

这种继承方式优点在于构造函数可以传参,不会与父类引用属性共享,可以复用父类的函数,但也存在一个缺点就是继承父类函数的时候调用了父类的构造函数,导致子类的原型上多了不需要的父类属性,存在内存上当浪费。

2、寄生组合继承

这种继承方式对组合继承进行了优化,组合继承缺点在于继承父类函数时调用了构造函数,这时候只需优化掉这一点就好了。

function Parent(value) {
  this.val = value;
};
Parent.prototype.getValue = function() {
  console.log(this.val);
};

function Child(value) {
  Parent.call(this, value);
};
Child.prototype = Object.create(Parent.prototype, {
  constructor: {
    value: Child,
    enumerable: false,
    writable: true,
    configurable: true
  }
});

const child = new Child(1);

child.getValue(); // 1
child instanceof Parent // true

以上继承实现的核心就是将父类的原型赋值给了子类,并且将构造函数设置为子类,这样即解决了无用的父类属性问题,还能正确的找到子类的构造函数。

3、class继承

以上两种都是通过原型解决的,在ES6中,就可以通过class去实现继承

class Parent {
  constructor(value) {
    this.val = value;
  }
  getValue() {
    console.log(this.val);
  }
};
class Child extends Parent{
  constructor(value) {
    super(value)
    this.val = value
  }
};

let child = new Child(1);

child.getValue(); // 1
child instanceof Parent // true

class 实现继承的核心在于使用 extends 继承自哪个父类,并且在子类构造函数中必须调用super,因为这段代码可以看成 Parent.call(this, value)。

---END---