"不安全的出版物"存在于Javascript中?

时间:2016-08-26 00:02:11

标签: javascript class constructor safe-publication

我刚写了以下Javascript代码......

class Team {
    constructor(id, eventHandler) {
        this.id = id;
        this._eventHandler = eventHandler;
        this._eventHandler.trigger("NewTeam", this); // my concerning line
    }
}

我有Java背景。在Java中,对象从其构造函数(" unsafe publication ")共享对自身的引用被认为是危险的。这是因为其他线程可能在对象处于有效状态之前对其进行操作。

在Javascript中它也有风险吗?这被认为是不好的做法吗?

我只能想到一个问题:如果我们想要扩展Team,那么让eventHandler.trigger("NewTeam",__)可以看到其他属性会很棘手。

1 个答案:

答案 0 :(得分:2)

由于Javascript是单线程的(除了这里没有使用的webWorkers),你提到的Java问题并不适用于Javascript。没有其他代码将与构造函数同时运行。这是Javascript单线程和事件驱动性质的极大简化之一。

如果您同步触发事件或进行函数调用并将未完成的对象传递给该事件处理程序或函数调用,那么您当然会遇到麻烦,因为您将未完成的对象引用传递给其他代码将在您完成构造函数之前运行。

只要您传递的对象在传递时处于有效状态,这不是问题,但如果您传递了未完成的对象,那么您确实在寻找麻烦,但这实际上只是常识编程,与线程或并发无关。

在您的具体案例中:

class Team {
    constructor(id, eventHandler) {
        this.id = id;
        this._eventHandler = eventHandler;
        this._eventHandler.trigger("NewTeam", this); // my concerning line
    }
}

您已创建漏洞。如果Team是子类,那么在子类必须完成其构造函数之前,您将调用this._eventHandler.trigger("NewTeam", this);并传递this。根据具体实施情况,这可能是一个问题,因此练习并不总是安全的。如果.trigger()可以在下一个tick上调用(使用setImmediate()nextTick()之类的东西,那么这将始终是安全的,因为对象和任何子类总是在它之前构造完成被叫了。