15.6 有关类的常见问题解答

15.6.1 为什么类不能像函数一样调用?

目前禁止用函数的方式调用类。这样做是为将来做准备,为了最终通过类来添加一种处理函数调用的的方式。一种这样做的可能方式是通过一个特殊的方法(例如 [Symbol.functionCall] )。

15.6.2 究竟如何实例化一个类,传递一组参数?

什么是 Function.prototype.apply() 的类模拟?那就是,如果有一个类 TheClass 和一组数组形式的参数 args ,如何实例化 TheClass

一种办法是通过扩展操作符(...):

function instantiate(TheClass, args) {
    return new TheClass(...args);
}

另一种方法是使用 Reflect.construct()

function instantiate(TheClass, args) {
    return Reflect.construct(TheClass, args);
}

15.6.3 如何管理类的私有数据?

两种 ES5 的保持数据私有性的方式对类也有效:

  • 1、可以让私有数据存放在类构造器的作用域环境中。我一直不喜欢因此而被迫添加特殊的实例方法。
  • 2、可以使用命名约定(例如下划线前缀)来标记私有属性。我喜欢这种方式。这不会对私有属性提供完全的保护,并且略微使命名空间杂乱,但是实现的代码很简单。

在 ECMAScript 6 中,可以使用额外的 WeakMaps 来实现私有数据,这会对方法一中的私有数据提供完全地保护,但是代码更加优雅。下面是如何实现的代码,详细原理在关于 WeakMap 的那一章有讲解:

let _counter = new WeakMap();
let _action = new WeakMap();
class Countdown {
    constructor(counter, action) {
        _counter.set(this, counter);
        _action.set(this, action);
    }
    dec() {
        let counter = _counter.get(this);
        if (counter < 1) return;
        counter--;
        _counter.set(this, counter);
        if (counter === 0) {
            _action.get(this)();
        }
    }
}

15.6.4 下一个关于类的内容是什么?

类的设计原则是“最大程度地最小化”。讨论了几种高级的特性,但是最终被放弃了,为了得到一种 TC39 一致认同的设计。

下一个 ECMAScript 版本可以基于这个最小化的设计 - 类将会提供一些基础特性,比如 traits (或者 mixins ),值对象(如果两个不同的对象有相同的内容的话,那么它们是相等的)和常类(生成不可变实例)。

results matching ""

    No results matching ""