如何将数据/函数添加到构造函数创建的javascript对象的所有实例中,以便所有实例具有相同的引用而不是它的副本?
基本上在C#中实现静态方法的等价物。
例如,给定以下创建Widget类的代码。
(function() {
var Widget = function() {
};
Widget.prototype.init = function(data) {
this.data = data;
};
this.Widget = Widget;
}).call(this);
var instance1 = new Widget();
instance1.init('inst1');
var instance2 = new Widget();
instance2.init('inst2');
alert(instance1.data); // inst1
alert(instance2.data); // inst2
在上面的例子中,每个实例都有自己的data属性副本。但是,我想添加一个为所有当前和未来实例设置数据的函数。
我目前的解决方案是向构造函数对象添加一个函数,而不是它的原型。见下面的例子。这有什么陷阱,还有更好的方法吗?
(function() {
var Widget = function() {
};
Widget.prototype.init = function(data) {
this.data = data;
};
Widget.addStaticData = function(data) {
this.staticData = data;
};
Widget.prototype.getStaticData = function() {
return Widget.staticData;
};
this.Widget = Widget;
}).call(this);
var instance1 = new Widget();
instance1.init('inst1');
Widget.addStaticData('static');
var instance2 = new Widget();
instance2.init('inst2');
alert(instance1.data); // inst1
alert(instance2.data); // inst2
alert(instance1.getStaticData()); // static
alert(instance2.getStaticData()); // static
答案 0 :(得分:2)
我能想到的三个陷阱:
方法论:原型是共享,重用,继承功能/属性的地方 - 利用它本身
性能:继承比在实例上设置每次更快。 John Resig(jQuery创建者)在一篇我目前无法找到的博客文章中做了一些基准测试。
丢失继承属性和自有属性之间的分割。如果通过构造函数将所有内容应用于实例,则所有内容都是实例属性。
通过构造函数的所有内容:
function Dog() { this.legs = 4; }
var fido = new Dog();
fido.name = 'Fido';
for (var i in fido) if (fido.hasOwnProperty(i)) alert(i+' = '+fido[i]);
...警告这两个属性,因为它们被认为是实例所拥有的。
通过原型和构造函数
function Dog2() { }
Dog2.prototype.legs = 4;
var fido = new Dog2();
fido.name = 'Fido';
for (var i in fido) if (fido.hasOwnProperty(i)) alert(i+' = '+fido[i]);
...仅警告name
,因为这是唯一的实例属性。 (尽管如此,fido.legs
是可检索的 - 但它来自原型。)
[编辑 - 以回应下面的OP公司]
如果你想要一个静态方法,那么应该在声明之后将它添加到函数中。
function Dog() {}
Dog.static = function() {}
答案 1 :(得分:1)
考虑局部变量staticData
而不是Widget.staticData
属性。这样,外部命令无法直接写入数据,因此编写它的唯一方法是通过addStaticData
函数:
(function () {
var Widget = function () {};
var staticData;
Widget.addStaticData = function ( obj ) {
staticData = obj.data;
};
Widget.prototype.init = function () {
var data = staticData;
// use data
// or just use the staticData variable directly
};
this.Widget = Widget;
}).call( this );
使用您的代码,可以执行此操作:
Widget.staticData = { data: 'COMPROMISED!' };
更改静态数据。由于您具有设置静态数据的专用功能,因此您可能不希望以其他方式更改静态数据。
使用我的代码,上述语句无效,静态数据只能通过addStaticData
函数进行更改。