JS的类模块
2021 javascript在 es5 中主要是通过构造函数方式和原型方式来定义一个类,在 es6 中我们可以通过 class 来定义一个类。
ES5
在 es5 中主要是通过构造函数方式和原型方式来定义一个类,且一般以大写字母开头。
ES6 中的类模块转换成 ES5。以下是根据 TSC 转换情况,
- 类 -> 函数
- 方法 -> prototype 方法
- 构造器参数 -> 参数
- 静态方法 -> 属性
class Log {
constructor(height, width) {
this.height = height;
this.width = width;
}
static displayName = 'Point';
run(value) {
console.log(value);
return value;
}
}
TS 编译之后的结果
var Log = /** @class */ (function () {
function Log(height, width) {
this.height = height;
this.width = width;
}
Log.prototype.run = function (value) {
console.log(value);
return value;
};
Log.displayName = 'Point';
return Log;
})();
ES6
在 ES6 中定义一个类使用关键字 class。
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
构造器
constructor
构造器是用于创建和初始化一个使用 class
创建的对象。一个类中只能包含一个构造器。
一个构造器可以使用 super
关键字来调用父类的构造函数。
对于类和子类来说,构造器并不是必须的。如果省略的话,那么二者都会自动提供一个默认构造器。具体来说,默认子类构造器会自动调用父类的构造器并传递所有参数。类似代码如下:
constructor(...args) {
super(...args);
}
static
通过 static
关键字定义静态方法和静态属性。静态成员(属性和方法)的调用不需要实例化他们的类,也不能通过类的实例来调用。静态方法通常用于为应用创建实用性函数,而静态属性通常用于缓存、固定配置或者其他不需要重复的实例数据。
在类生命了 static 方法其实就是直接添加到这个类的函数对象上,而不是在这个函数对象的 protytpe 对象上。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
// 静态域
static Name = 'Point';
// 静态方法
static getName() {
return this.Name;
}
static position(p) {
return `(${p.x}, ${p.y})`;
}
}
// 实例化 p1
const p1 = new Point(2, 5);
// 访问静态域和静态方法
console.log(Point.Name); // "Point"
console.log(Point.getName()); // "Point"
console.log(Point.position(p1)); // (2, 5)
extends
extends
关键字在类声明或类表达式中用于创建一个类的子类。
class Foo {
constructor(a, b) {
this.x = a;
this.y = b;
}
gimmeXY() {
return this.x * this.y;
}
}
class Bar extends Foo {
constructor(a, b, c) {
super(a, b);
this.z = c;
}
gimmeXYZ() {
return super.gimmeXY() * this.z;
}
}
var b = new Bar(5, 15, 25);
b.x; // 5
b.y; // 15
b.z; // 25
b.gimmeXYZ(); // 1875
在 extends 经常会使用 super,那是因为子类中经常会调用父类的的属性或者方法。
super
super
关键字被用来调用父类相应的方法。super 在构造器中,自动指向“父构造器”,在上面的例子中就是 Foo(..)。在方法中,super 会指向 “父对象”,这样就可以访问其属性/方法了,比如上面的 super.gimmeXY()。
如果子类中定义了构造函数,那么它必须先调用 super
才能使用 this
。注意,是在子类的构造函数才需要。
ES5 的类与 ES6 的 class 区别
-
class 类必须 new 调用,不能直接执行。
class 类执行的话会报错,而 ES5 中的类和普通函数并没有区别。
-
class 类不存在变量提升
ES5 函数声明会有变量提升,而 class 是没有将类的定义提升到顶部,这也是 TS 将 class 转成 ES5 的时候用到函数表达式的原因。
-
class 类有 static 静态方法
static 静态方法只能通过类调用,不会出现在实例上;另外如果静态方法包含 this 关键字,这个 this 指的是类,而不是实例。
static 静态属性和方法都不可以被子类继承。
参考链接
- MDN: Classes
- 《你不知道的 Javascriopt(下)》第二部分 3.4
- es5 中的类和 es6 中的 class 有什么区别?