super 关键字指向当前对象的原型对象。
1.super的简单应用
const person = {
name:'jack'
}
const man = {
sayName(){
return super.name;
}
}
Object.setPrototypeOf( man, person );
let n = man.sayName(); //jack
注意,super 关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。目前,只有对象方法的简写法可以让 JavaScript 引擎确认,定义的是对象的方法,其他写法会报错。
2.super的另类实现
super.name
等同于
Object.getPrototypeOf(this).name【属性】
等同于
Object.getPrototypeOf(this).name.call(this)【方法】
3.super中的this指向(易混淆)
super.name 指向的是原型对象 person 中的name,但是绑定的this还是当前的man对象。
const person = {
age:'20多了',
name(){
return this.age;
}
}
const man = {
age:'18岁了',
sayName(){
return super.name();
}
}
Object.setPrototypeOf( man, person );
let n = man.sayName(); //18岁了
Object.getPrototypeOf(this).name 指向的是person的name,绑定的this也是person
const person = {
age:'20多了',
name(){
return this.age;
}
}
const man = {
age:'18岁了',
sayName(){
return Object.getPrototypeOf(this).name();
}
}
Object.setPrototypeOf( man, person );
let n = man.sayName(); //20多了
4.Class中的super
super 关键字,既可以当作函数使用,也可以当作对象使用。两种情况,含义完全不一样。
- super 作为函数调用时,表示父类的构造函数;
- super 作为对象时,在普通方法中,指向父类的原型对象,在静态方法中指向父类。
(1)Class中的 super(),它在这里表示父类的构造函数,用来新建父类的 this 对象
super() 相当于 Parent.prototype.constructor.call(this)
class Demo{
constructor(x,y) {
this.x = x;
this.y = y;
}
customSplit(){
return [...this.y]
}
}
class Demo2 extends Demo{
constructor(x,y){
super(x,y);
}
customSplit(){
return [...this.x]
}
task1(){
return super.customSplit();
}
task2(){
return this.customSplit();
}
}
let d = new Demo2('hello','world');
d.task1() //["w", "o", "r", "l", "d"]
d.task2() //["h", "e", "l", "l", "o"]
(2)在子类的构造函数中,只有调用了 super 方法之后,才可以使用 this 关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有 super 方法才能返回父类实例。
class Demo2 extends Demo{
constructor(x,y){
this.x = x; //this is not defined
}
}
ES5的继承,实质上是先创造子类的实例对象this,然后再将父类的方法添加到this上(Parent.call(this)).
ES6的继承,需要先创建父类的this,子类调用super继承父类的this对象,然后再加工。
如果子类没有定义 constructor 方法,这个方法会被默认添加,其中的 super 方法也会自动调用:
class Demo{
constructor(x) {
this.x = x;
}
}
class Demo2 extends Demo{}
// 等同于
class Demo2 extends Demo{
constructor(...args) {
super(...args);
}
}
let d = new Demo2('hello');
d.x //hello
(3) super 在静态方法之中指向父类,在普通方法之中指向父类的原型对象
class Parent {
static myMethod(msg) {
console.log('static', msg);
}
myMethod(msg) {
console.log('instance', msg);
}
}
class Child extends Parent {
static myMethod(msg) {
super.myMethod(msg);
}
myMethod(msg) {
super.myMethod(msg);
}
}
Child.myMethod(1); // static 1
var child = new Child();
child.myMethod(2); // instance 2
(4)ES6 规定,通过 super 调用父类的方法时,方法内的 this 指向子类。