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

How can I set the prototype when I don't know the name of the constructor?

本文关键字:设置 原型 何设置 构造函数 我不知道      更新时间:2023-09-26

这是我的理解,每个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());
            });

您可能会注意到有嵌套调用,并且我为每个参与者对象添加了path属性,在对象模型中表示它是特定参与者的路径数据。

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

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

令我非常惊讶的是,我得到了一个异常,声称原型是空的:

JavaScript运行时错误:无法设置未定义的属性'redraw'或空引用

这是怎么回事?

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

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

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

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

但是要回答你的问题"当我不知道构造函数的名字时,我如何设置原型?":

您不能设置现有对象的原型(不是以标准方式)。原型是在构建时指定的,不能(以标准方式)更改。你可以改变对象原型的属性,但不能改变原型的对象。

对象的原型不能从它的属性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

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

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