接昨天继续以class
类作为学习对象,回顾面向对象开发有三要素。
- 继承,子类继承父类
- 封装,数据的权限和保密
- 多态,同一接口不同实现
今天先复习下继承相关。
class
可以通过extends
关键字来实现子类继承父类。
class People{
constructor(name, age){
this.name = name;
this.age = age;
}
static speak(){ //类的静态方法
console.log('I am speaking.');
}
selfIntro(){
console.log(`Hello, my name is ${this.name}, i'm ${this.age} years old.`);
}
}
let nitx = new People('nitx', 30);
nitx.selfIntro();
People.speak();
class Student extends People{
constructor(name, age, score){
super(name, age); // 调用父类的constructor(x, y)
this.score = score;
}
showScore(){
console.log(`${this.name}'s score is ${this.score}, this guy's age is ${this.age}.`);
return super.selfIntro();
}
}
let sxm = new Student('sxm', 21, 'A1');
sxm.showScore();
Student.speak();
/**
打印:
Hello, my name is nitx, i'm 30 years old.
I am speaking.
sxm's score is A1, this guy's age is 21.
Hello, my name is sxm, i'm 21 years old.
I am speaking.
*/
上例可以看到,子类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
方法获取父类的实例。
class Student extends People{
constructor(name, age, score){
this.score = score;
super(name, age); // 调用父类的constructor(x, y)
}
/*
原型方法(实例方法)
*/
}
//打印错误信息
/*
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
*/
子类的实例对象同时是子类和父类这两个类的实例,与es5的行为一致。
console.log(sxm instanceof Student); //true
console.log(sxm instanceof People); //true
上面是知道父类和子类的继承关系的,但有时并不会完全清楚,此时就需要一个方法帮助开发者判断父类子类的关系Object.getPrototypeOf()
console.log(Object.getPrototypeOf(Student)); //[Function: People]
console.log(Object.getPrototypeOf(Student) === People); //true
继承的优势:
People
是父类,公共的,不仅仅服务于Student
类- 继承可将公共方法抽象出来,提高利用,减少冗余
喜欢本文请扫下方二维码,关注微信公众号: 前端小二,查看更多我写的文章哦,多谢支持。