类的继承
class FxSubFn extends FxFn {
constructor (name, age, salary) {
super(name, age); // 调用父类的构造方法
this.salary = salary
}
// 父类的方法重写
showName () {
console.log('调用子类的构造方法')
console.log(this.name, this.salary)
}
}
let fx1 = new FxSubFn('fx', 18, 88888888)
console.log(fx1) // FxSubFn {name: "fx", age: 18, salary: 88888888}
fx1.showName() // 调用子类的构造方法 fx 88888888
重复声明一个类会引起类型错误。
class Foo {};
class Foo {};
// Uncaught TypeError: Identifier 'Foo' has already been declared
若之前使用类表达式定义了一个类,则再次声明这个类同样会引起类型错误。
let Foo = class {};
class Foo {};
// Uncaught TypeError: Identifier 'Foo' has already been declared
类实质上就是一个函数。类自身指向的就是构造函数。所以可以认为ES6中的类其实就是构造函数的另外一种写法!
console.log(typeof FxFn); // function
console.log(FxFn === FxFn.prototype.constructor); // true
子类必须在constructor
方法中调用super
方法,否则新建实例时会报错。这是因为子类自己的this
对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super
方法,子类就得不到this
对象。
class Point { /* ... */ }
class ColorPoint extends Point {
constructor() {
}
}
let cp = new ColorPoint(); // ReferenceError
如果子类没有定义constructor
方法,这个方法会被默认添加,代码如下。也就是说,不管有没有显式定义,任何一个子类都有constructor
方法。
class ColorPoint extends Point {
}
// 等同于
class ColorPoint extends Point {
constructor(...args) {
super(...args);
}
}
在子类的构造函数中,只有调用super
之后,才可以使用this
关键字,否则会报错。这是因为子类实例的构建,基于父类实例,只有super
方法才能调用父类实例。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
this.color = color; // ReferenceError
super(x, y);
this.color = color; // 正确
}
}
父类的静态方法,也会被子类继承。hello()
是A
类的静态方法,B
继承A
,也继承了A
的静态方法。
class A {
static hello() {
console.log('hello world');
}
}
class B extends A {
}
B.hello() // hello world
Object.getPrototypeOf
方法可以用来从子类上获取父类。可以使用这个方法判断,一个类是否继承了另一个类。
Object.getPrototypeOf(ColorPoint) === Point
// true