2013-05-06 60 views
1

這是我的理解,每個JavaScript對象都有一個原型,即使它只是一個Object.prototype當我不知道構造函數的名稱時,如何設置原型?

我有一個asp.net web服務代理,從服務器獲取參與者數據。這部分工作正常。下面的代碼:

 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 runtime error: Unable to set property 'redraw' of undefined or null reference

這是怎麼回事這裏?

This question似乎解決了這個問題,但我不明白如何將這些信息應用於這種情況,因爲我不知道如何引用未在我的代碼中定義的構造函數。

在這種情況下是有用的信息,在運行時立即窗口participants.constructor的檢查似乎表明構造爲陣列()

我應該寫一個構造函數,複製等領域爲對象並設置一個原型?如果是的話,是否存在與C#反射相當的JavaScript,所以我不必爲每種類型的查詢結果對象都重寫該函數?注意當我更新問題時,昏迷在評論中回答了這部分問題。

+0

你試過'foo.constructor.prototype.redraw ='? – thebreiflabb 2013-05-06 08:39:52

+0

它是JSON嗎?看看http://stackoverflow.com/questions/5873624/parse-json-string-into-a-particular-object-prototype-in​​-javascript – coma 2013-05-06 08:41:34

+0

使用foo.constructor.prototype.redraw會導致jQuery-1.9.1在第2816行的barf說,處理程序是不確定的,我確實嘗試過。 – 2013-05-06 08:42:28

回答

4

在這種特殊情況下,你可能會更好過只是增加了功能的對象本身,而不是試圖將其添加到原型。

但要回答您的問題「我不知道構造函數的名稱時如何設置原型?」

您不能設置現有對象的原型(不是以標準方式)。原型在施工時分配,不能(以標準方式)更改。您可以更改對象原型的屬性,但不能更改的原型

對象的原型不能從其上的屬性獲得,稱爲prototypeprototype財產涉及功能。這是通過使用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

+0

這是一個傑出的迴應。你比我桌上的三本教科書解釋得更好,而且更簡潔。 – 2013-05-06 08:58:34

+0

@PeterWone:哇,謝謝!如果是這樣,你可能會喜歡我的博客:http://blog.niftysnippets.org/和/或我的['天堂傳承助手](http://code.google.com/p/lineagejs/) 。 – 2013-05-06 10:03:57

+0

寫書。你有它的訣竅。我認爲你不會有太多戲劇性的與奧雷利一起演出,或者你可以自行發佈,付費是一個可打印的PDF的好處(我個人更喜歡XPS,因爲你不需要安裝觀衆,但這是一場神聖的戰爭)。 – 2013-05-06 12:52:24

1

要通過原型方法添加到一個對象,而不是一個構造只需添加它,而不是直接的:

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

而在這個函數的主體中,我可以引用「this」並期望它解析到它被調用的對象? – 2013-05-06 08:57:19

+0

是的。更具體地說,「this」將引用由最後一個點之前的單詞命名的對象。例如,如果你做了像'r = foo.redraw'之類的東西,然後調用'r()',那麼這個調用中的'this'不會引用'foo',而是會引用全局對象(窗口)。 – slebetman 2013-05-06 12:30:01

+0

請參閱以下有關'this'如何在js中工作的更長解釋:http://stackoverflow.com/questions/13441307/how-does-the-this-keyword-in-javascript-act-within-an-object-文字/ 13441628#13441628 – slebetman 2013-05-06 12:32:00

相關問題