接昨天继续以class
类作为学习对象,回顾面向对象开发有三要素。
今天先复习下继承相关。
class
可以通过extends
关键字来实现子类继承父类。
1class People{
2 constructor(name, age){
3 this.name = name;
4 this.age = age;
5 }
6
7 static speak(){ //类的静态方法
8 console.log('I am speaking.');
9 }
10
11 selfIntro(){
12 console.log(`Hello, my name is ${this.name}, i'm ${this.age} years old.`);
13 }
14}
15
16let nitx = new People('nitx', 30);
17nitx.selfIntro();
18People.speak();
19
20class Student extends People{
21 constructor(name, age, score){
22 super(name, age); // 调用父类的constructor(x, y)
23 this.score = score;
24 }
25
26 showScore(){
27 console.log(`${this.name}'s score is ${this.score}, this guy's age is ${this.age}.`);
28 return super.selfIntro();
29 }
30}
31
32let sxm = new Student('sxm', 21, 'A1');
33sxm.showScore();
34Student.speak();
35/**
36打印:
37Hello, my name is nitx, i'm 30 years old.
38I am speaking.
39sxm's score is A1, this guy's age is 21.
40Hello, my name is sxm, i'm 21 years old.
41I am speaking.
42 */
上例可以看到,子类Student
的constructor
方法和showScore
方法中,都用到了super
关键字,它表示的是父类的构造函数,用来新建父类的this
对象,注意,super
虽然代表了父类的构造函数,但是返回的是子类的实例,即super
内部的this
指的是子类,因此super()
在这里相当于A.prototype.constructor.call(this)
。
子类必须在
constructor
方法中调用super
方法,否则新建实例时报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
ES5 的继承,实质是先创造子类的实例对象this
,然后再将父类的方法添加到this
上面(Parent.apply(this)
)。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this
上面(所以必须先调用super
方法),然后再用子类的构造函数修改this
。
如果子类没有定义constructor
方法,这个方法会被默认添加,也就是说,不管有没有显式定义,任何一个子类都有constructor
方法。
父类的静态方法也会被子类所继承。
这里有个地方需要注意下,在子类的constructor
构造函数中,必须先调用super
方法,才能使用this
,否则就会报错。因为子类实例的构建是基于父类实例的,所以必须先调用super
方法获取父类的实例。
1class Student extends People{
2 constructor(name, age, score){
3 this.score = score;
4 super(name, age); // 调用父类的constructor(x, y)
5 }
6
7 /*
8 原型方法(实例方法)
9 */
10}
11//打印错误信息
12/*
13ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
14*/
子类的实例对象同时是子类和父类这两个类的实例,与es5的行为一致。
1console.log(sxm instanceof Student); //true
2console.log(sxm instanceof People); //true
上面是知道父类和子类的继承关系的,但有时并不会完全清楚,此时就需要一个方法帮助开发者判断父类子类的关系Object.getPrototypeOf()
1console.log(Object.getPrototypeOf(Student)); //[Function: People]
2console.log(Object.getPrototypeOf(Student) === People); //true
继承的优势:
People
是父类,公共的,不仅仅服务于Student
类