子类通过extends
关键字继承父类。
class Par{
constructor(){
this.num=21;
}
}
class Chil extends Par{
constructor(){
//继承父类的构造函数constructor
super() //这里必须写,否则下面实例会报错。
}
}
var p=new Chil();
console.dir(p.num) //21
注意:子类必须在constructor
方法中调用super
方法,否则新建实例时会报错。这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例。
ES5 继承和ES6 继承对比
- ES5 的继承机制:是先创造子类的实例对象
this
,然后再将父类的方法添加到this
上面(Parent.apply(this))。 - ES6 的继承机制:是先将父类实例对象的属性和方法,加到
this
上面(所以必须先调用super
方法),然后再用子类的构造函数修改this
。
super关键字
1.可以当函数用。
super作为函数调用时,代表父类的构造函数。
class A {}
class B extends A {
constructor() {
super();
}
}
注意:
-
super
虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super
内部的this
指的是B的实例,因此super()
在这里相当于A.prototype.constructor.call(this)
。 -
super
只能用在子类的constructor
中。
2.可以作为对象使用。
super
作为对象使用时, 在普通的方法中,指向的是父类的原型对象。在静态方法中,指向的是父类。
class A {
constructor() {
// 这里是实例上的属性
this.p = 1;
}
// 普通方法,放在A原型上的。
say(){
console.log("普通方法")
}
// 静态方法,能被子类继承,但是不能被实例化对象继承。
static greeting(){
console.log("静态方法")
}
}
// 静态属性
A.age=22;
class B extends A {
constructor(){
super();
}
bsay(){
// p是实例的属性,通过this访问
console.log(this.p) //1
// 在普通方法中,super指向的是父类原型对象,即prototype,
// 所以能访问父类原型上的方法。
super.say() // "普通方法";
}
static bgreeting(){
// 在静态方法中,super指向的是父类,能访问父类的静态属性和静态方法。
super.greeting(); //"静态方法"
console.log(super.age); //22
}
}
let xiao = new B();
xiao.bsay();
B.bgreeting();
要点总结:
- 静态方法,能被子类继承,不能被实例对象继承。
- 因为普通方法中,
super
指向的是父类原型对象。所以子类中,通过super
只能访问到父类原型上的方法。 - 在静态方法中,
super
指向的是父类,只能访问父类的静态属性和静态方法。 - 普通方法中,
this
指向的是当前类的实例对象。 - 静态方法中,
this
指向的是当前类。
类的 prototype 属性和proto属性
类同时有prototype
属性和__proto__
属性,因此同时存在两条继承链。
例子:
class Par{
constructor(){
// ....
}
say(){
console.log("我今年"+this.age+"岁了!")
}
static greeting(){
console.log("hello")
}
}
Par.num=101;
class Chil extends Par{
constructor(){
super()
}
}
console.dir(Chil)
- 子类的
__proto__
属性 ,指向父类。
即Chil.__proto__ === Par
image.png
-
子类
image.pngprototype
属性的__proto__
属性,指向父类的prototype
属性。
即Chil.prototype.__proto__ === Par.prototype
-
子类实例的
__proto__
属性的__proto__
属性,指向父类实例的__proto__
属性。也就是说,子类的原型的原型,是父类的原型。
即Chil.__proto__.__proto__ === Par.__proto__
原生构造函数继承
-
Boolean()
-
Number()
-
String()
-
Array()
-
Date()
-
Function()
-
RegExp()
-
Error()
-
Object()
-
ES5 是先新建子类的实例对象this,再将父类的属性添加到子类上,由于父类的内部属性无法获取,导致无法继承原生的构造函数。
-
ES6 允许继承原生构造函数定义子类,因为 ES6 是先新建父类的实例对象this,然后再用子类的构造函数修饰this,使得父类的所有行为都可以继承。
class MyArray extends Array {
constructor(...args) {
super(...args);
}
}
var arr = new MyArray();
arr[0] = 12;
arr.length // 1
arr.length = 0;
arr[0] // undefined
网友评论