ES6中的关键字super该如何理解?

说起ES6的继承和super的用法大家都不会陌生,可一问到super到底是什么,很多人就很模糊了,比如java
中的superthis不同点包括: super()主要是对父类构造函数的调用,this()是对重载构造
函数的调用;super()主要是在继承了父类的子类的构造函数中使用,是在不同类中的使用;this()主要是
在同一类的不同构造函数中的使用 ;相同的是二者都必须在构造函数的第一行进行调用,否则就报错。但是在
ES6中,super是一个特殊的语法,而且它比this还要特殊,很多用法上限制。

有时能被当作函数来调用,有时又能当作对象来访问,实在让人糊涂…那么怎么描述这一关键字比较容易理解呢?

 class Cat { 
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Lion extends Cat {
  constructor(name, color) {
     super(name); // 这个super指向什么呢
     this.color = color;
  }

  speak() {
    super.speak(); // 这个super又指向什么?
    console.log(this.name + ' roars.');
  }
}

let a = {
   toString(){
      return 'My little pony' + super.toString(); //这里的super又指向什么
   }
}

super关键字只能够以指定的形式出现在以下地点,否则代码会出现SyntaxError,无法通过编译:

  1. class语句块内的constructor函数的定义内,例如:

    class A{                              
        constructor(name){                
            this.name=name;               
        }                                 
        getName(){                        
            return this.name;             
        }                                 
    }                                     
    
    class B extends A {                   
        constructor(name,age){            
            super(name);    
     //注意:如果super不是在第一个this调用之前,就会报:ReferenceError: this is not defined               
            this.age = age;               
        }                                 
        getAge() {                        
            return this.age;              
        }                                 
    }                                     
    
    var b = new B('hank',50);             
    console.log(b.getName());  // hank    
    console.log(b.getAge());   // 50      
    

建立class时,当且仅当“使用了extends关键字并指定了constructor函数”,super关键字必须以super([arg1,....])的形式使用一次。此时super([arg1,....])相当于创建了一个对象,且以该对象为context调用extends关键字指示的函数(以new的形式),随后这个对象成为constructor函数的context。因此super([arg1,....)必须出现在constructor函数内的第一个this关键字之前,否则会报ReferenceError: this is not defined
也可以以super.IdentifierName的形式出现(这就与是否使用了extends关键字无关了)。

  • super.IdentifierName作为getter使用时,表示函数Bprototype属性对象的[[prototype]];
  • super.IdentifierName作为setter使用时, super表示this;

2.class语句块哪的static函数的定义内,例如:

class C extends A {
    static foo() {                        
     super.say();                      
     console.log(super.say === A.say); 
      }                                       
}
var c= new C();  

必须以super.IdentifierName的形式出现。super.IdentifierName作为getter时,super表示该函数B的[[prototype]](本例中C的[[prototype]]即A)。若通过super.IdentifierName()来调用函数,则此函数的相当于通过.call(this)调用。super.IdentifierName作为setter使用时,super表示this。

3.class语句块内的一般方法(非static或constructor函数)的定义内,例如:

class D extends A {
    foo() {                        
     super.say();                      
     console.log(super.say === A.say); 
      }                                       
}
var D= new D();  

必须以super.IdentifierName作为getter时,super表示该函数D的prototype属性对象的[[prototype]]。同样,若通过super.IdentifierName()来调用函数,则此函数的相当于通过.call(this)调用;super.IdentifierName作为setter使用时,super表示this。

4.在对象字面量的方法的定义内,例如:

let a = {
    foo() {
        super.test()
    }
}

let b = {
    test() {
        console.log("I'm hank")
    }
}

Object.setPrototypeOf(a, b);
a.foo(); // "I'm hank"

必须以super.IdentifierName的形式出现,super.IdentifierName作为getter时,super表示该对象的[[prototype]]。同样,若通过super.IdentifierName()来调用函数,则此函数的相当于通过.call(this)调用。super.IdentifierName作为setter使用时,super表示this

以上都是在node6.2下测试

文章目录