总结一下JS中的继承

197 阅读2分钟

正好在复习的过程中复习有关js的继承方面的知识,写下博客来总结下。

原型链继承

原型链继承就是在子类的原型上添加父类,就比如这样Chile.prototype = new Parent

/**
 * 原型链继承
 */
function Parent() {
  this.name = 'Zeekg';
}

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

function Child() {}

Child.prototype = new Parent();

var child1 = new Child();

console.log(child1.getName()) // Zeekg

不知道发现没有,如果用这种继承方法,在创建实例的时候是无法向父类传递参数的。

采用构造函数

在子类中使用call()方法,调用父类中的属性和方法。这种方法就可以向父类传参。但是方法都是在构造函数中定义的,所以每次创建实例的时候都会创建一遍方法。

/**
 * 采用构造函数
 */
function Rectangle(height, width) {
  this.height = height
  this.width = width
}

function Square(length) {
  Rectangle.call(this, length, length)
}

let square = new Square(5)
console.log(square.height);

组合继承

这种组合继承就是原型链继承和采用构造函数组合起来。这种继承方式还是比较常见的。 但是这种就会调用两次父构造函数。

/**
 * 组合继承
 */
function Rectangle(height, width) {
  this.height = height
  this.width = width
}

Rectangle.prototype.getArea = function () {
  return this.height * this.width
}

function Square(length) {
  Rectangle.call(this, length, length) // 这里调用一次父构造函数
}

Square.prototype = new Rectangle() // 这里调用一次父构造函数

let square = new Square(5)
console.log(square.getArea());

但是这种方法还有一点,就是当你打印square的时候,会发现实例squareSquare.prototype都会有heightwidth这两个属性。

寄生组合式继承

上面组合继承的方式还是有一点不妥。寄生组合继承方式采用了Object.creaet()这个方法。

/**
 * 寄生组合式继承
 */
function Rectangle(height, width) {
  this.height = height
  this.width = width
}

Rectangle.prototype.getArea = function () {
  return this.height * this.width
}

function Square(length) {
  Rectangle.call(this, length, length)
}

Square.prototype = Object.create(Rectangle.prototype)
Square.prototype.constructor = Square

let square = new Square(5)
console.log(square.getArea());

ES6的继承

这种方法比较简单,但是是一种语法糖,底层实现原理还是上面那样。

/**
 * class继承
 */
class Rectangle {
  constructor(height, width) {
    this.height = height
    this.width = width
  }
  getArea() {
    return this.height * this.width
  }
}

class Square extends Rectangle {
  constructor(length) {
    super(length, length)
  }
}

let square = new Square(5)
console.log(square.getArea());

关于super():

在构造函数中访问this之前一定要调用super(),因为它负责初始化this

如果不在派生类中的构造函数使用super(),就会报错。

若有不正确的地方,欢迎在评论区中指出。