没有 new 的 JS Power Constructor 和 instanceof

JS Power Constructor and instanceof without new

为了引用this guy,我们可以使用具有以下形式的幂构造函数

function constructor() {
    var that = {};
    that.data = true;
    that.method = function () {};
    return that;
}

创建在有或没有 new 关键字的情况下都能正确运行的对象。

我的问题是我们如何连接 instanceof 运算符以使用幂构造函数?我认为它与 object.prototype.constructor 属性有关,但我不确定如何在构造函数的范围内编辑它。

constructor() instanceof constructor // false but I want it to be true
new constructor() instanceof constructor // true

你可以使用这个结构

function constructor() {
    if (!(this instanceof constructor))
        return new constructor();
    this.data = true;
    this.method = function () { };
}

您可以在 Node.js 本机模块中找到此构造

示例:

function Hash(algorithm, options) {
    if (!(this instanceof Hash))
        return new Hash(algorithm, options);
    this._handle = new binding.Hash(algorithm);
    LazyTransform.call(this, options);
}

正如我在评论中所说,我个人更喜欢只使用严格模式以确保程序员不会忘记使用 new 关键字。但这里有另一种方法,根本不使用 new 关键字:

function demo() {
    var that = Object.create(demo.prototype);
    that.data = true;
    that.method = function () {};
    return that;
}

var d = demo();
d instanceof demo // true

还有一种替代方法也避免了使用 new:

var demo = {
    init: function() {
        this.data = true;
    },
    method: function() {}
}
var d = Object.create(demo);
d.init();

demo.isPrototypeOf(d) // true

如果你试图相信你不应该使用 new 的 JS 思想流派,那么你就是在选择退出许多语言功能,包括 instanceof

instanceof 与 JavaScript 函数作为构造函数 + 原型继承范式齐头并进。 x instanceof C具体看C.prototype,和x的原型链对比(见OrdinaryHasInstance算法)。 C.prototype 查找旨在与 new 运算符一起使用,当将其应用于任何函数 F 时,将在其原型链中创建一个带有 F.prototype 的新对象,在构造函数 F 将 运行 (this 设置为新分配的对象)。

"Power constructors" 只是 return 对象的函数,不适用于普通语言机制(包括 ES2015 类)。试图与他们一起使用 instanceof 是矛盾的:如果你想发誓不使用 new,你也应该发誓不使用 instanceof

您为使 instanceof 工作而采取的任何技巧,如 Matt Browne 的回答中的技巧,最终都将实质上重新创建 new 已经提供的整个基础架构。 (参见 a similar conversation I've had previously。)