super关键字
2020-08-11 本文已影响0人
zhulichao
super关键字,既可以当作函数使用,也可以当作对象使用。使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。由于对象总是继承其他对象的,所以可以在任意一个对象中,使用super关键字。
```
class A {}
class B extends A {
constructor() {
super();
/*
Uncaught SyntaxError: 'super' keyword unexpected here
无法看出super是作为函数使用,还是作为对象使用
*/
console.log(super);
/*
super.valueOf()表明super是一个对象
*/
console.log(super.valueOf() instanceof B); // true
}
}
var obj = {
toString() {
return "MyObject: " + super.toString();
}
};
obj.toString(); // MyObject: [object Object]
```
第一种情况,当作函数使用,代表父类的构造函数,super虽然代表了父类的构造函数,但是返回的是子类的实例,即super内部的this指的是子类。super()只能用在子类的构造函数中,用在其它地方就会报错。ES6要求,子类的构造函数必须执行一次super函数。
```
class A{}
class B extends A {
constructor() {
/*
当作函数使用,代表父类的构造函数,相当于
A.prototype.constructor.call(this)
*/
super();
}
}
```
第二种情况,super作为对象时,在普通方法中指向父类的原型对象,在静态方法中指向父类。ES6规定,通过super调用父类的方法时,super会绑定子类的this。由于绑定子类的this,所以如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
```
class A {
constructor() {
this.q = 2;
}
p() {
return 2;
}
print() {
/*
通过B的super.print()虽然调用的是A.prototype.print(),但是A.prototype.print()会绑定子类B的this,相当于
super.print.call(this)
*/
console.log(this.q);
}
}
class B extends A {
constructor() {
super();
this.q = 3;
/*
当作对象使用,这是普通方法,super指向A.prototype,相当于
A.prototype.p()
q是父类A实例的属性,super.q就引用不到它
*/
console.log(super.p()); // 2
console.log(super.q); // undefined
}
subPrint() {
super.print();
}
}
let b = new B();
b.subPrint(); // 3
```
```
class Parent {
static myMethod(msg) {
console.log('static', msg);
}
myMethod(msg) {
console.log('instance', msg);
}
}
class Child extends Parent {
static myMethod(msg) {
// 静态方法,super指向父类
super.myMethod(msg);
}
myMethod(msg) {
// 普通方法,super指向父类的原型对象
super.myMethod(msg);
}
}
Child.myMethod(1); // static 1
var child = new Child();
child.myMethod(2); // instance 2
```