在javascript中强制执行新的模式

Jam*_*aly 13 javascript

我一直在阅读Stoyan Stefanov撰写的JavaScript Patterns一书,其中一个强制构造函数的新运算符的模式就像这样

function Waffle() {
if (!(this instanceof Waffle)) {
return new Waffle();
}
this.tastes = "yummy";
}
Waffle.prototype.wantAnother = true;
Run Code Online (Sandbox Code Playgroud)

以这种方式书写时,您可以使用其中一种方式调用Waffle

var first = new Waffle(),
second = Waffle(); 
Run Code Online (Sandbox Code Playgroud)

我认为这是一个有用的功能,不确定它是否在未来版本的ecma/javascript中实现

我想出了一些东西,我认为每次创建构造函数时都可以复制和粘贴

这样的事情

function checkInstance (name) {
    if (name.constructor.name === undefined) {
       return "construct it"
    } else {
       return false;
    }
}

function Waffle() {
    var _self = checkInstance.call(this, this);
    if (_self === "construct it") {
       return new Waffle()
    }
    this.tastes = "yummy"
}

var waffle = Waffle()
waffle
Run Code Online (Sandbox Code Playgroud)

因此我可以调用Waffle新的Waffle或Waffle()并且仍然让它返回一个对象

我遇到的问题就在这里

  if (_self === "construct it") {
       return new Waffle()
       }
Run Code Online (Sandbox Code Playgroud)

无论如何我可以参考new Waffle()而不参考构造函数的实际名称,这意味着我每次都可以复制和粘贴它,而不必改变任何东西.意思是我可以将Waffle()保存为变量并执行类似的操作

return new var
Run Code Online (Sandbox Code Playgroud)

我希望我可以使用this.name但是在调用之前它不起作用.

我有一种感觉,我不得不至少问一些有关堆栈溢出的人,如果有可能的话

再次,您的意见和反馈表示赞赏

Aad*_*hah 8

我有一个更好的解决方案.这就是你目前正在做的事情:

function Waffle() {
    if (!(this instanceof Waffle))
        return new Waffle;
    this.tastes = "yummy";
}

Waffle.prototype.wantAnother = true;
Run Code Online (Sandbox Code Playgroud)

这种模式并不是很好,因为你混合代码来构造一个新的对象,用代码检查new关键字是否被使用.

我之前提到过,你不应该new在JavaScript中使用关键字,因为它会破坏功能特性.相反,让我们创建另一个做同样事情的函数:

Function.prototype.new = (function () {
    return function () {
        functor.prototype = this.prototype;
        return new functor(this, arguments);
    };

    function functor(constructor, args) {
        return constructor.apply(this, args);
    }
}());
Run Code Online (Sandbox Code Playgroud)

此函数允许您创建函数的实例,如下所示:

var waffle = Waffle.new();
Run Code Online (Sandbox Code Playgroud)

但是我们根本不想使用new.因此,为了消除它,我们将创建一个包装构造函数的函数,如下所示:

function constructible(constructor) {
    function functor() { return Function.new.apply(constructor, arguments); }
    functor.prototype = constructor.prototype;
    return functor;
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以定义Waffle函数如下:

var Waffle = constructible(function () {
    this.tastes = "yummy";
});

Waffle.prototype.wantAnother = true;
Run Code Online (Sandbox Code Playgroud)

现在您可以创建或不使用new以下对象:

var first = new Waffle;
var second = Waffle();
Run Code Online (Sandbox Code Playgroud)

注意:该constructible功能非常慢.请使用以下版本constructible- 它更快一点:

function constructible(constructor) {
    constructor = Function.bind.bind(constructor, null);
    function functor() { return new (constructor.apply(null, arguments)); }
    functor.prototype = constructor.prototype;
    return functor;
}
Run Code Online (Sandbox Code Playgroud)

我个人不会使用这两种方法中的任何一种.我只记得写new,或者(更有可能)我会重构我的代码如下:

var waffle = {
    create: function () {
        var waffle = Object.create(this);
        waffle.tastes = "yummy";
        return waffle;
    },
    wantAnother: true
};

var first = waffle.create();
var second = waffle.create();
Run Code Online (Sandbox Code Playgroud)

如果您想了解有关此模式的更多信息,请阅读以下答案:https://stackoverflow.com/a/17008403/783743