定义类
类实际上是个“特殊的函数”,就像你能够定义的函数表达式和函数声明一样,类语法有两个组成部分:类表达式和类声明。
类声明
定义一个类的一种方法是使用一个类声明。要声明一个类,你可以使用带有class关键字的类名(这里是“Rectangle”)。
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
提升
函数声明和类声明之间的一个重要区别是函数声明会提升,类声明不会。你首先需要声明你的类,然后访问它,否则像下面的代码会抛出一个ReferenceError:
let p = new Rectangle();
// ReferenceError
class Rectangle {}
类表达式
一个类表达式是定义一个类的另一种方式。类表达式可以是被命名的或匿名的。赋予一个命名类表达式的名称是类的主体的本地名称。
/* 匿名类 */
let Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
/* 命名的类 */
let Rectangle = class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
注意: 类表达式也同样受到类声明中提到的提升问题的限制。
静态方法
static 关键字用来定义一个类的一个静态方法。调用静态方法不需要实例化该类,但不能通过一个类实例调用静态方法。静态方法通常用于为一个应用程序创建工具函数。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
console.log(Point.distance(p1, p2));
实例属性
实例的属性必须定义在类的方法里:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
静态的或原型的数据属性必须定义在类定义的外面。
Rectangle.staticWidth = 20;
Rectangle.prototype.prototypeWidth = 25;
使用 extends 创建子类
extends 关键字在类声明或类表达式中用于创建一个类作为另一个类的一个子类。
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
speak() {
console.log(this.name + ' barks.');
}
}
var d = new Dog('Mitzie');
d.speak();// 'Mitzie barks.'
如果子类中存在构造函数,则需要在使用“this”之前首先调用 super()。
也可以继承传统的基于函数的“类”:
function Animal (name) {
this.name = name;
}
Animal.prototype.speak = function () {
console.log(this.name + ' makes a noise.');
}
class Dog extends Animal {
speak() {
super.speak();
console.log(this.name + ' barks.');
}
}
var d = new Dog('Mitzie');
d.speak();//Mitzie makes a noise. Mitzie barks.
请注意,类不能继承常规(非可构造)对象。如果要继承常规对象,可以改用Object.setPrototypeOf():
var Animal = {
speak() {
console.log(this.name + ' makes a noise.');
}
};
class Dog {
constructor(name) {
this.name = name;
}
}
Object.setPrototypeOf(Dog.prototype, Animal);// If you do not do this you will get a TypeError when you invoke speak
var d = new Dog('Mitzie');
d.speak(); // Mitzie makes a noise.
使用 super 调用超类
super 关键字用于调用对象的父对象上的函数。
class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(this.name + ' roars.');
}
}