2009-07-22 43 views
1

我知道再次閱讀這個話題真的很煩人,在開始編寫代碼之前,有一種解決方案可能是我沒有在JavaScript中獲得原型和對象,但是現在我認爲, 。克隆JavaScript對象。再次說明:(

的問題是:
如何克隆JavaScript類(與原型創建),以便擴展和事後執行時,「克隆」類保持不變

function clone(obj){ 
    if(obj == null || typeof(obj) != 'object') 
     return obj; 

    var temp = new obj.constructor(); 
    for(var key in obj) 
     temp[key] = clone(obj[key]); 

    return temp; 
} 

var FOO = function() { 
    var myBAR = clone(BAR); 
    myBAR.prototype = jQuery.extend(true, myBAR.prototype, this); // deep cloning twice and extending with this 
    console.log("FOO:", this.name); 
    new myBAR(); 
}; 

FOO.prototype = { 
    name: "FOO" 
}; 

var BAR = function() { 
    console.log("BAR:", this.name); 
}; 

BAR.prototype = { 
    name: "BAR" 
}; 

new FOO(); // returns FOO: FOO and BAR: FOO 
new BAR(); // returns BAR: FOO should return BAR: BAR 

如果我」?我知道它是正確的,第二個電話new BAR()(在new FOO()之後)應該返回目前爲而不是BAR: FOO。對於這個問題

一個可能的解決方案是clone功能的一個東西完全重寫這樣的:

function clone(obj) { 
    return eval("("+obj.toString()+")"); // the same as eval(uneval(obj)); 
} 

但這種方法有一個很大的弊端,不能傳遞任何動態創建的對象。

任何想法?

+1

你是什麼意思的「動態創建的對象」? – 2009-07-23 07:19:59

+0

想象一下,您在FOO內部創建了一個CAT實例,並將其保存爲屬性,如this.cat = new CAT();CAT類已創建並保存對DOM元素的引用。像this.myBody = $("body")。 – 2009-07-23 07:33:31

+0

在你的克隆過程中,你想要複製什麼時候以及何時需要複製一個參考? – Rojo 2009-07-23 08:02:43

回答

0

我只是想向任何人展示我對上述問題的解決方案。

function cloneClass (func) { 

    if(typeof func == 'function') { 

    var prototype = {}; 
    for (var prop in func.prototype) { 
     prototype[prop] = func.prototype[prop]; 
    }; 

    var Class = function() { 
     var _this = this; 
     var constructor = function() { 
     func.apply(_this, arguments); 
     }; 
     constructor.prototype = _this; 

     for (var property in func) { 
     if(property != "prototype") { 
      constructor[property] = func[property]; 
     } 
     }; 

     return constructor; 
    }; 

    Class.prototype = prototype; 
    return new Class(); 
    } 

    return func; 

}; 

試着深入瞭解它是如何工作的。有沒有人可以看到這個實現的任何問題,內存泄漏等?

0

克隆javascript對象的問題是你決定走多深?

考慮我有以下對象:

var obj = { 
    prop : { 
     n1prop : { 
      hello : 'world'; 
     } 
    } 
}; 

這意味着我將不得不遍歷的類型是「對象」可能得到相當昂貴的,如果你有一個深度嵌套的所有屬性。

如果你有一個簡單的1級別的對象,你可以使用一個簡單的反射循環,並創建一個新的對象文字。 注意:這不會複製原始對象的方法。

function clone(obj) { 
    var cloned; 

    if (obj && typeof obj === 'object') { 
     cloned = {}; 
     for (var p in obj) { 
      if (obj.hasOwnProperty(p) && typeof obj[p] !== 'function') { 
       cloned[p] = obj[p] 
      } 
     } 
     return cloned; 
    } 
    else { 
     return null; 
    } 
} 
+0

對不起亞歷克斯,但這並沒有解決我動態創建的對象的問題。你的方法和我的克隆功能非常相似。 – 2009-07-23 07:10:32

1

的問題是你如何克隆「原型」

下面一行

myBAR.prototype = jQuery.extend(true, myBAR.prototype, this); // deep cloning 

您不僅克隆了「原型」,你也克隆了「名」屬性。

如果您要更換以上符合

myBAR.prototype = jQuery.extend(true, myBAR.prototype, this.prototype); // deep cloning 

現在您的代碼將返回

new FOO(); // returns FOO:FOO and BAR:BAR 
new BAR(); // returns BAR:BAR 
0

有一個需要進行,除了通過SolutionYogi提到的另一個變化。在FOO中,你傳遞的是要克隆的BAR,但BAR是構造函數(typeof BAR ==「function」),所以它將首先測試克隆函數,並且返回值將是對未更改的BAR的引用。這意味着myBAR.prototype不是BAR.prototype的克隆,而是對它的引用。

爲了真正創建一個新的構造,不只是一個參考,我認爲你必須使用eval - 添加類似:

if (typeof obj == "function) { 
    eval("var temp = " + obj + ";"); 
    return temp; 
} 

還有其他因素(如亞歷克斯指出) ,但添加上面的內容,應該會導致您的測試用例成功。

0
function clone(obj) { 
    if(typeof obj !== 'undefined') { 
     clone.prototype = Object(obj); 
     return new clone; 
    } 
} 

function Foo() {} // base class 

function Bar() {} // derived class 
Bar.prototype = clone(Foo.prototype); // inherit from `Foo.prototype`