es6的super关键字解析

150 阅读2分钟

constructor

在讲class关键字super之前,我们先介绍一下constructor这个方法。当你通过new命令创建实例对象时,会运行constructor这个方法,并且其一般返回实例对象this,当返回一个全新对象时,其返回的对象不是该类的实例。每个class类一定要有一个constructor方法,如果没写,会默认添加一个默认的constructor方法,并返回实例对象this

super关键字(可以当函数使用,也可以当对象使用)

1、super为函数时

class Parent{

}
class Son extends Parent{
  constructor() {

    super() // 在es6的class类继承中,子类必须调用一次super方法,否则会报错
  }
}

es6的class类继承中,在子类的constructor方法中必须调用super,因为此时的子类是没有子级的this,必须去继承父类的this,并对其进行加工。而此时super就代表着父类的构造函数。虽然这是super代表父类的构造函数,但其返回的却是子类的实例。

class Parent{
  constructor() {
    console.log(new.target.name);
  }
}
class Son extends Parent{
  constructor() {
    super(); // 在es6的class类继承中,子类必须调用一次super方法,否则会报错
  }
}
const parent = new Parent(); // Parent
const son = new Son(); // Son

由上可以,当执行new Son()时,super内部的this是指向Son的。

2、super为对象时

当调用父类方法时,super会绑定子类的this,若访问的属性子类原型上没有,会通过原型链找父类的

class Parent{
  constructor(name) {
    this.name = name;
  }
  getName() {
    console.log(this.name) // 张三
  }
}
class Son extends Parent{
  constructor(name, age) {
    super(name); 
    this.age = age;
    super.getName();
  }
}
const son = new Son('张三', 23); // Son
class Parent{
  constructor(name) {
    this.name = name;
  }
  getName() {
    console.log(this.name) // 李四
  }
}
class Son extends Parent{
  constructor(name, age) {
    super(name); 
    this.age = age;
    this.name = '李四';
    super.getName();
  }
}
const son = new Son('张三', 23); 

由于super绑定的是子类的this,因此通过super对某个属性赋值,这时的super等于this,赋值的属性会变成子类实例的属性。

class Parent{
  constructor() {
    this.name = '李四';
  }
}
class Son extends Parent{
  constructor() {
    super(); 
    this.name = '张三';
    super.name = '王五';
  }
  getName() {
    console.log(super.name); // undefined
    console.log(this.name); // 王五
  }
}
const son = new Son(); 
son.getName()

上述代码使用super对name属性赋值,即改变了子类实例对应属性的值,所以输出this.name为王五,而访问super.name相当于访问Parent.prototype.name方法,由于Parent类的原型上并没有name方法,所以输出undefined。

总结:

es6的class类实际上是es5的构造函数的语法糖,所以只要理解了JavaScript的面向对象的思想,用起来就会简单许多。