在 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 区别

  1. class 类必须 new 调用,不能直接执行。

    class 类执行的话会报错,而 ES5 中的类和普通函数并没有区别。

  2. class 类不存在变量提升

    ES5 函数声明会有变量提升,而 class 是没有将类的定义提升到顶部,这也是 TS 将 class 转成 ES5 的时候用到函数表达式的原因。

  3. class 类有 static 静态方法

    static 静态方法只能通过类调用,不会出现在实例上;另外如果静态方法包含 this 关键字,这个 this 指的是类,而不是实例。

    static 静态属性和方法都不可以被子类继承。

参考链接