javascript中构造函数的静态方法模式

javascript中构造函数的静态方法模式,javascript,methods,static,design-patterns,Javascript,Methods,Static,Design Patterns,这是向构造函数添加静态方法的唯一模式吗?特别是,不能在Foo()本身的定义中创建静态方法bar()。您可以在构造函数中创建静态方法,但只能使用相同的语法: function Foo(){...} Foo.bar = function (){...}; 但这只会在调用构造函数后添加静态方法。此外,每次调用构造函数时,它都会重新添加它,这似乎是浪费,但我想可能是有用的,例如: function Foo(){ Foo.bar = function (){...}; } 在这种情况下,bar

这是向构造函数添加静态方法的唯一模式吗?特别是,不能在Foo()本身的定义中创建静态方法bar()。

您可以在构造函数中创建静态方法,但只能使用相同的语法:

function Foo(){...}
Foo.bar = function (){...};
但这只会在调用构造函数后添加静态方法。此外,每次调用构造函数时,它都会重新添加它,这似乎是浪费,但我想可能是有用的,例如:

function Foo(){
    Foo.bar = function (){...};
}
在这种情况下,
bar
被更新,以返回调用
Foo
的次数-这里可能有一个合理的变体,可以以有用的方式跟踪所有实例

如果出于某种原因,您真的不想参考
Foo
,那么您可以聪明地做如下操作:

function Foo() {
    var counter = (Foo.bar && Foo.bar() || 0) + 1;
    Foo.bar = function (){
        return counter;
    };
}

f = new Foo();
Foo.bar(); // 1
f2 = new Foo();
Foo.bar(); // 2
function Foo() {
    this.constructor.bar = function (){
        console.log("test");
    };
}
同样,这只在至少调用了一次
Foo
之后才有效。另外,虽然这确实演示了另一种语法,但我真的很难想象你什么时候会想使用它

这里还有另一种可能同样无用的变体:

var Foo = (function Private(){
    Private.bar = function (){...};
});
当你说“在里面”时,听起来你需要一种干净的方式把所有东西都放在一个地方。您可能会使用支持静态声明的类继承库。或者简单地使用一个并自己扩展它以添加该功能

要想以一种简单(但不是那么紧凑)的方式将所有内容保持在一起,您可以采用以下方式:

function Foo() {
    var counter = (Foo.bar && Foo.bar() || 0) + 1;
    Foo.bar = function (){
        return counter;
    };
}

f = new Foo();
Foo.bar(); // 1
f2 = new Foo();
Foo.bar(); // 2
function Foo() {
    this.constructor.bar = function (){
        console.log("test");
    };
}
但是!让声明是静态的这一点不言而喻到底有多重要?您可以简单地将静态方法声明为原型方法,并通过一些代码注释传达它们是静态(即不作用于实例)方法的事实。对于如何调用这些方法,不会有任何合同强制执行,但会有很少的副作用。所以我只想说:

var Foo = (function () {
    var ctor = function () {
        // the constructor
    };

    ctor.staticMethod = function () {
        // something static
    };

    return ctor;
})();
用法:

function Foo() {
    // the constructor
    // optionally define instance methods here
}

Foo.prototype = {
    instanceMethod: function () {
        // some instance method
        // this.bar(); ...
    },
    staticMethod: function () {
        // some static method
        // return 2 + 3;
    }
};
我发现上面的方法非常有用,尤其是在使用factory设计模式时。您的类可以在其原型中有一些静态工厂方法,并且您可以调用这些工厂方法,即使您只有一个不知道其原始类的实例

// Using "prototype" explicitly can be your contract for saying "this is static"
var sum = Foo.prototype.staticMethod();

var inst = new Foo();

var sum2 = inst.staticMethod(); // You have the added benefit of being able to call your static methods on instances

换句话说,您将创建一个匿名函数来填充Foo的原型。

获取“TypeError:Foo.bar不是一个函数”。@osoviejo-是的,请参阅我的更新-这只在您至少调用一次构造函数后才有效。无法在构造函数内部执行在函数运行之前生效的操作。要求初始实例并不是“静态的”:(@AtesGoral-这不是经典意义上的。但它是一个直接附加到构造函数的独立方法,与Javascript的“静态”非常接近不管怎样。@nrabinowitz True True…但是在任何情况下,将其附加到构造函数之外都更为自然,就像OP在他们的示例中所做的那样。或许OP的问题的答案是简单的“不,这是唯一的方法”。为什么
inst
在您的用例中会有一个方法
sum
?您不需要类似
sum.call(inst)
的东西吗?另外,关于“为什么不?”的问题-因为它会使您的代码难以阅读并减少代码压缩。
sum
是“静态的”本质上,它并不真正关心
这个
。在这种情况下绝对没有必要使用
调用
。对,但我的观点是,除非我遗漏了什么,
inst
没有名为
sum
的属性-它只有名为
staticMethod
的属性。这就是你的意思吗?@nrabinowitz“难以阅读”是主观的。这完全取决于您定义的约定和契约。记住,这些经典继承、privates/publics/statics等都是非JavaScript本机的。