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的面向对象的思想,用起来就会简单许多。