如何将数据/函数添加到构造函数创建的javascript对象的所有实例?

时间:2012-08-01 13:43:07

标签: javascript

如何将数据/函数添加到构造函数创建的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

2 个答案:

答案 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函数进行更改。