上一篇学习了class的概念,在es5时,对象的继承有好几种,原型链继承,借用构造函数继承,组合继承,原型式继承,寄生式继承以及寄生组合式继承,都是按照函数的形式去集成的,现在class也有它的继承方式,简化了操作。
extends关键字extends,直接通过这一个关键字就可以实现继承。
class Person{} class Child extends Person{}上面代码定义了一个Child类,该类通过extends关键字,继承了Person类的所有属性和方法,所以Child就直接复制了一份Person类。简单的开场方式,是不是比es5的继承方式简单多了,哈。。
super关键字在子类中调用super(),说明是表示父类的构造函数,用来新建父类的this对象。
class Person { constructor(name, age) { this.name = name; this.age = age; } say(name) { console.log(`${name} is saying`) } } class Child extends Person { constructor(name, age, color) { super(name, age); this.color = color } jump(name) { console.log(`${this.name} is jumping`) } } var peter = new Child('peter',18,'red'); console.log(peter); // Child {name: "peter", age: 18, color: "red"} peter.jump() // peter is jumping子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
class Person{} class Child extends Person{ constructor(){} } var peter = new Child() // Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor上面代码中,Child继承了父类Person,但是它的构造函数没有调用super方法,导致新建实例时报错。所以说super()是在继承中重要的一环。
另外,如果子类中没有显示constructor,即使不加super,也不会报错,因为class中会默认有constructor,同样的道理,也会有super()
另一个需要注意的地方是,在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例。
class Perosn { constructor(name, age) { this.name = name; this.age = age; } } class Child extends Person { constructor(name, age, color) { this.color = color; // ReferenceError:Person is not defined super(name, age); this.color = color; // 正确 } }super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。
第一种情况,super作为函数调用时,代表父类的构造函数,类似于super()。
ES6 要求,子类的构造函数必须执行一次super函数。
class A { constructor() { console.log(new.target.name); } } class B extends A { constructor() { super(); } } new A() // A new B() // B super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B,因此super()在这里相当于A.prototype.constructor.call(this)。继承了A的this为B所用。上面代码中,new.target指向当前正在执行的函数。可以看到,在super()执行时,它指向的是子类B的构造函数,而不是父类A的构造函数。也就是说,super()内部的this指向的是B。因此super()在这里相当于A.prototype.constructor.call(this)。
super()只能用在子类的构造函数constructor之中,用在其他地方就会报错。
class Person {} class Child extends Person { jump() { super(); // error } }上面的例子,在Child子类中的constructor之外的方法中用了super(),会报错,因为super函数只能用在构造函数constructor中。
第二种情况,super作为对象时,
在普通方法中,指向父类的原型对象
class Person { constructor(name,age) { this.name = name; this.age = age; } say(){ console.log(this.age) } p(){ return 2 } } class Child extends Person { constructor(name,age, color) { super(name,age); //该super代表的是用函数的形式 this.age = 25; this.color = color; console.log(super)//使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。如果只写super,没法判断是对象还是方法 console.log(super.p()); } say1(){ super.say() } } var peter = new Child('peter',18,'red') peter.p() // 2 peter.say1() // 25