0

如何向构造函数创建的 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
4

2 回答 2

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() {}
于 2012-08-01T13:50:28.333 回答
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函数来​​改变静态数据。

于 2012-08-01T14:04:24.013 回答