2010-10-13 37 views
1

我看了四周,發現沒有什麼可以幫助我。爲什麼地球上不能克隆一個JavaScript對象與私人成員沒有讓他們糾纏在一起?複製javascript對象與私人會員

看看這個代碼...這是一個普通的私有財產與getter和setter。 不知何故,如果我在一個實例中調用公共setter,克隆的也會發生變化。爲什麼?它可以解決嗎?

obj = function(){ 
    var changed = 0; 
    this.getChanged = function(){ 
     return changed; 
    } 
    this.setChanged = function(){ 
     changed = 1; 
    } 
    this.setUnchanged = function(){ 
     changed = 0; 
    } 
}; 

myObj = new obj(); 
copiedObj = $.extend(true, {}, myObj); // Or any other deep copy function you'd have around 

myObj.setChanged(); 
myObj.getChanged(); // returns 1 
copiedObj.getChanged(); // returns 1! 
copiedObj.setUnchanged(); 
copiedObj.getChanged(); // returns 0 
myObj.getChanged(); // returns 0 

感謝您的任何想法。

編輯:到目前爲止,沒有什麼新的。我知道JavaScript並沒有像Java或C++這樣的OO,但是我們談論的是編程語言,總是有一條出路。有時它很醜,但有一個。

我明白了。 溶液A:只是使它this.changed代替VAR改變
解決方案B:使,重建整個對象重新

我只是希望會有一些C液那會我自己的克隆功能把javascript轉化爲標準的面向對象的模式。

有人,我真的堅持A或B嗎?

回答

1

用作構造函數的函數中的局部變量被稱爲「私有成員」,因此Java羣衆可以理解該用法的意圖。它不像一個財產。它是一個詞彙範圍內的局部變量。它對實例是「私人」的,而不是類。 JavaScript中沒有任何類。

最好的辦法是添加一個將深度複製實例的克隆方法。

1

即使深層複製也不能複製除參考以外的任何功能。由於你的職能是關閉,他們都共享相同的私人成員。爲什麼不寫一個clone()方法?

3

問題是,已更改不是私有變量 - JavaScript沒有私有變量。這是您分配給變量obj變量的函數的局部變量。當你創建一個會被分配到功能getChanged/setChanged/setUnchanged屬性,您要創建closures已關閉在可變改變

當你克隆myObj,你只是爲這些函數創建額外的別名。因此,無論您是通過myObj還是copiedObj訪問它們,並且由於它們是關閉,您在兩種情況下都訪問完全相同的變更變量,您仍然調用相同的功能。既然你不能複製函數,你最好不要試圖使變爲私有,只是在做this.changed = 0;在第二行。

0

得到了答案。

gilly3的提示幫助。

我使用的克隆/深度複製功能實際上不是jQuery的,而是一個A. Levy posted on a similar question

不得不按照兩種方式調整它,以達到我的預期。實際上,原作者已經在他的解釋中指出了方法,但是在我第一次閱讀它時沒有看到它。
首先我使用原始對象的構造函數實例化副本,並從for循環中篩選出函數。

結果如下。希望能幫助別人。

function clone(obj) { 
    // Handle the 3 simple types, and null or undefined 
    if (null == obj || "object" != typeof obj) return obj; 

    // Handle Date 
    if (obj instanceof Date) { 
     var copy = new Date(); 
     copy.setTime(obj.getTime()); 
     return copy; 
    } 

    // Handle Array 
    if (obj instanceof Array) { 
     var copy = []; 
     for (var i = 0, len = obj.length; i < len; ++i) { 
      copy[i] = clone(obj[i]); 
     } 
     return copy; 
    } 

    // Handle Object (functions are skipped) 
    if (obj instanceof Object) { 
     var copy = new obj.constructor(); 
     for (var attr in obj) { 
      if (obj.hasOwnProperty(attr) && !(obj[attr] instanceof Function)) copy[attr] = clone(obj[attr]); 
     } 
     return copy; 
    } 

    throw new Error("Unable to copy obj! Its type isn't supported."); 
} 
+0

請記住,您實際上並沒有使用此方法克隆** changed **變量的值。如果這是一項要求,則需要一個特定於您的obj「類」的克隆方法,該方法使用** getChanged **/** setChanged **傳輸該值。 – 2010-10-14 17:22:51

+1

是的。在我的情況下,更改的變量是特定於實例,並在構造函數中有一個默認值。我不希望被複制,所以沒關係。謝謝。 – 2010-10-14 17:41:37