charleyup

为自己吹过的🐮🍺奋斗终生.

javascript实现继承的几种方式

2016/03/21

继承可以使得子类具备父类的各种方法和属性

原型链继承

最常见的继承方式,继承成员定义在prototype

const Parent = function () {
    this.value = "value from parent"
}
const Child = function () {}
Child.prototype = new Parent()
const childInstance = new Child()
console.log(childInstance.value) // "value from parent"

缺点是

  1. 引用类型的属性被所有实例共享,修改时影响所有实例
  2. 创建子类时不能向父类传递参数
    const Parent = function () {
     this.values = [1, 2, 3]
    }
    const Child = function () {}
    Child.prototype = new Parent()
    const instance1 = new Child()
    const instance2 = new Child()
    console.log(instance1.values) // [1, 2, 3]
    console.log(instance2.values) // [1, 2, 3]
    instance1.values.push(4)
    console.log(instance2.values) // [1, 2, 3,4 ]
    console.log((new Child()).values) // [1, 2, 3, 4]

构造函数继承

const Parent = function (a, b) {
    this.value = "value from parent"
    this.a = a
    this.b = b
}
const Child = function () {
    Parent.call(this, ...arguments)
}
const instance = new Child(1, 2)
console.log(instance)

构造函数继承的优点是引用类型的属性不会被共享并且可以传参,缺点是只继承父类,不继承原型

const Parent = function () {
    this.values = [1, 2, 3]
    this.getValue1 = function () {
        return this.values
    }
}
Parent.prototype.getValue2 = function () {
    return this.values
}
const Child = function () {
    Parent.call(this)
}
const instance = new Child()
console.log(instance.getValue1()) // [1, 2, 3]
console.log(instance.getValue2()) // 报错

es6继承-extends

Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {}
}

class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y);
    this.color = color; // 正确
  }
  toString() {
    return this.color + ' ' + super.toString(); // 调用父类的toString()
  }
}