当我不知道构造函数的名称时,如何设置原型?

时间:2013-05-06 08:34:41

标签: javascript prototype

我的理解是每个javascript对象都有一个原型,即使它只是来自Object.prototype的

我有一个asp.net webservice代理,可以从服务器获取参与者数据。那部分工作正常。这是代码:

        atomWebServiceProxy.GetInteractionParticipants(interactionId,
            function (participantsResult) {
                var assetId, pendingPathFetches;
                participants = participantsResult;
                pendingPathFetches = participants.length;
                document.title = participants.length + " participants:";
                for (var i = 0; i < participants.length; i++) {
                    assetId = participants[i].ASSETID;
                    document.title += " " + participants[i].DISPLAYID;
                    atomWebServiceProxy.GetInteractionPath(interactionId, assetId,
                        function (pathResult, participant) {
                            participant.path = pathResult;
                            pathResult.participant = participant;
                            if (--pendingPathFetches == 0) {
                                setTimeout(afterInit, 20);
                            }
                        },
                        function (error, participant) {
                            alert(participant.DISPLAYID + " reported this error: " + error.get_message());
                        },
                        participants[i]
                    );
                }
            },
            function (error) {
                alert(error.toString());
            });

您可能会注意到存在嵌套调用,并且我已向每个参与者对象添加了路径属性,在对象模型中表示它是该特定参与者的路径数据。这也很好。

然后我尝试像这样在原型中添加一个方法:

var foo = participants[0];
foo.prototype.redraw = function(map) {
   ... //code that redraws
};

令我惊讶的是,我得到一个例外,声称原型为空:

  

JavaScript运行时错误:无法设置未定义的属性“重绘”   或空引用

这里发生了什么?

This question似乎解决了这个问题,但我看不出如何将这些信息应用于这种情况,因为我不知道如何引用我的代码中未定义的构造函数。

如果这是有用的信息,在运行时立即窗口中的participant.constructor检查似乎表明构造函数是Array()

我应该编写一个将字段复制到对象中并设置原型的构造函数吗?如果有的话,有一个等同于C#反射的javascript,所以我不必为每种类型的查询结果对象重写这个吗?注意当我更新问题时,昏迷在评论中回答了这部分问题。

2 个答案:

答案 0 :(得分:4)

在这种特殊情况下,您可能最好只将函数添加到对象本身,而不是尝试将其添加到原型中。

但要回答你的问题“当我不知道构造函数的名称时如何设置原型?”

您不能设置现有对象的原型(不是以标准方式)。原型在施工时分配,不能(以标准方式)更改。您可以更改对象原型的属性,但不能更改 其原型的对象。

对象的原型在名为prototype的属性上不可用。 prototype属性与函数相关。它是通过该函数使用new探索创建的对象原型(例如,new Foo()指定Foo.prototype作为新创建对象的原型)。

您可以通过Object.getPrototypeOf在ES5中获取对象的原型。在一些ES5之前的实现中,它可以通过非标准__proto__属性获得。 (在其中一些实现中,__proto__可以写入,这就是为什么我说你不能以标准的方式交换原型对象 - 你可以在那里支持它的实现中的标准方式。)

因此,在ES5环境中,您可以像这样扩展对象的原型:

Object.getPrototypeOf(theObject).newstuff = "foo";

但请注意,这会改变原型,其他对象可能正在使用它!例如:

// A constructor function, and a prototype to assign to objects created with it
function Foo() {
}
Foo.prototype.hi = function() {
    console.log("Hi");
};

// Create two objects
var f1 = new Foo();
var f2 = new Foo();

// Add something to the prototype of `f1`:
Object.getPrototypeOf(f1).there = function() {
    console.log("there");
};

// Since `f1` and `f2` *share* the same prototype object,
// `f2` now has it too!
f2.there(); // "there"

Live Copy | Source

答案 1 :(得分:1)

要向对象而不是构造函数添加方法,只需直接添加它而不是通过原型:

var foo = participants[0];
foo.redraw = function(map) {
   ... //code that redraws
};