【发布时间】:2012-02-21 18:32:11
【问题描述】:
function Foo(){...}
Foo.bar = function (){...};
这是向构造函数添加静态方法的唯一模式吗?特别是在Foo()本身的定义中是不是不能创建静态方法bar()?
【问题讨论】:
标签: javascript methods static design-patterns
function Foo(){...}
Foo.bar = function (){...};
这是向构造函数添加静态方法的唯一模式吗?特别是在Foo()本身的定义中是不是不能创建静态方法bar()?
【问题讨论】:
标签: javascript methods static design-patterns
( function (fn) {
fn.bar = function (...) { ... } ;
...
} ) ( Foo.prototype ) ;
换句话说,您创建了一个匿名函数来填充 Foo 的原型。
【讨论】:
当您说“内部”时,听起来您需要一种干净的方式来将所有东西都放在一个地方。您可能会使用支持静态声明的类继承库。或者干脆拿一个并自己扩展它以添加该功能。
要以简单(但不是那么紧凑)的方式将所有内容放在一起,您可以使用以下方法:
var Foo = (function () {
var ctor = function () {
// the constructor
};
ctor.staticMethod = function () {
// something static
};
return ctor;
})();
但是!使声明不言自明,它是静态的,到底有多重要?您可以简单地将静态方法声明为原型方法,并通过一些代码 cmets 传达它们是静态(即不作用于实例)方法的事实。这些方法的调用方式不会有任何合同强制执行,但副作用很少。所以我会选择:
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;
}
};
用法:
// 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
我发现上述方法非常有用,尤其是在您使用工厂设计模式时。您的类可以在其原型中包含一些静态工厂方法,即使您只有一个您不知道其原始类的实例,您也可以调用这些工厂方法。
【讨论】:
inst 在你的用例中有一个方法sum?你不需要像sum.call(inst)这样的东西吗?
sum本质上是“静态的”——它并不真正关心this。在这种情况下绝对不需要使用call。
inst 没有名为sum 的属性——它只有一个名为staticMethod 的属性。你是这个意思吗?
您可以在构造函数中创建静态方法,但只能使用相同的语法:
function Foo(){
Foo.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
在这种情况下,bar 被更新以返回 Foo 被调用的次数 - 这里可能有一个合理的变体可以以有用的方式跟踪所有实例。
如果你出于某种原因真的不想引用Foo,你可以聪明地做这样的事情:
var Foo = (function Private(){
Private.bar = function (){...};
});
同样,这只在Foo 至少被调用一次后才有效。此外,虽然这确实演示了另一种语法,但我很难想象您何时可能想要使用它。
这里还有另一个变体,可能同样没用:
function Foo() {
this.constructor.bar = function (){
console.log("test");
};
}
【讨论】: