【ES6】class继承(整理篇)

5,999 阅读2分钟

前言

上一篇整理了关于class的一些基础语法,【ES6】class基础(整理篇)。这一篇整理的是class继承相关。

ES5中繁琐的继承方式——组合继承

用一个例子说明组合继承:


function Super(name, age) {
    this.name = name;
    this.age = age;
}
function Sub(name, age, sex) {
    Super.call(this, name, age);
    this.sex = sex;
}
// 原型继承
Sub.prototype = new Super();
// 构造函数指向
Sub.prototype.constructor = Sub;

class的继承

  • 关键字——extends

举例:

class Point {
}

class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x,y);
        this.color = color
    }
}
  • 继承时没有constructor
class ColorPoint extends Point {
}

// 等同于
class ColorPoint extends Point {
  constructor(...args) {
    super(...args);
  }
}
  • 父类的静态方法也会被子类继承
class A {
  static hello() {
    console.log('hello world');
  }
}

class B extends A {
}

B.hello()
// hello world
  • 关键字——super

super代表的是父类构造函数,但是返回的是子类的实例。比如A是B的父类,那么super的功能相当于A.prototype.constructor.call(this)

super的使用方式:1、当函数使用。2、当对象使用

// 当函数使用
class A {}

class B extends A {
  constructor() {
    super();
  }
}
// 当对象使用
class A {
  p() {
    return 2;
  }
}

class B extends A {
  constructor() {
    super();
    console.log(super.p()); // 2
  }
}

let b = new B();

当对象使用时,相当于引用a原型上的方法。

类的prototype和__proto__方法

在ES5中,每个实例对应的__proto__都是指向对应构造函数的prototype方法。

class中,存在两条链级关系,他们分别是

  • 子类的__proto__指向父类
  • 子类prototype属性的__proto__指向父类的prototype属性
class A {
}

class B extends A {
}

B.__proto__ === A    // true
B.prototype.__proto__ === A.prototype  // true

整体的关系如图所示:

从原型指向分析类继承的原理

下面我们将从继承的原理上来得出原型链的指向。

再聊继承之前,我们先来看一个语法糖——Object.setPrototypeOf()

他的作用是:设置一个指定的对象的原型到另一个对象或null。

Object.setPrototypeOf = function (obj, proto) {
  obj.__proto__ = proto;
  return obj;
}

类的继承模式就是按照上面这个语法糖来的。

class A {
}

class B {
}

// B 的实例继承 A 的实例
Object.setPrototypeOf(B.prototype, A.prototype);

// B 继承 A 的静态属性
Object.setPrototypeOf(B, A);

const b = new B();

所以我们能得到如下结果:

B.__proto__ === A    // true
B.prototype.__proto__ === A.prototype  // true

实例的__proto__方法

子类实例的__proto____proto__指向父类的__proto__。也就说子类实例的原型的原型指向父类实例的原型

class A {
}

class B extends A {
}

const a = new A();
const b = new B();

b.__proto__.__proto__ === a.__proto__  // true

通过修改子类实例的原型的原型会影响到父类实例的原型。

总结

关于类的继承整理篇到此就结束了!!!下一篇将整理proxy这个语法糖,vue3.0中的代理也用到了他。