1

我的理解是每个 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 运行时错误:无法设置未定义或空引用的属性“重绘”

这里发生了什么?

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

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

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

4

2 回答 2

4

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

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

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

对象的原型不能从其上称为 的属性中获得prototype。该prototype属性与功能有关。它是被指定为使用表达式通过该函数创建的对象的原型的对象new(例如,new Foo()指定Foo.prototype为新创建对象的原型)。

你可以在 ES5 中通过Object.getPrototypeOf. 在一些 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"

实时复制| 来源

于 2013-05-06T08:41:01.727 回答
1

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

var foo = participants[0];
foo.redraw = function(map) {
   ... //code that redraws
};
于 2013-05-06T08:40:55.830 回答