2012-10-26 19 views
0

這是一個理論問題而不是一個如何解決問題。我工作在一個項目中哪些對象可以「分化」成幾個不同的類型,所以我決定去探索一些JavaScript的動態特性,但有一兩件事是有我真的很困惑:原型綁定在重新評估的匿名構造函數追溯到原始實例化對象

OriginalConstructor = function() {this.value = 42;} 
originalInstance = new OriginalConstructor(); 
ModifiedConstructor = eval(originalInstance.constructor); 
ModifiedConstructor.prototype.addedFunction = function(x) {return this.value + x;} 
modifiedInstance = new ModifiedConstructor(); 
document.write("modified: " + modifiedInstance.addedFunction(10)); 
document.write("<br>original: " + originalInstance.addedFunction(20)); 

爲什麼addedFunction綁定到originalInstance,即使ModifiedConstructor通過eval()被複制?當然,這兩個構造函數不能有相同的參考,他們可以嗎?

有沒有辦法修改一個對象(或未來的實例),而不影響已經從相同的構造函數實例化的其他對象?我知道還有其他方法可以解決這個問題,但我想更深入地理解Javascript。感謝您提供的任何見解。

@Felix Kling: 感謝您的快速,清晰和完整的答案。出於某種原因,我認爲構造函數屬性是一個可以被eval()解析的字符串,所以現在我明白了爲什麼這不起作用。我仍然不完全理解原型繼承,但至少現在我知道我需要學習什麼。謝謝!編輯: 我現在明白了。如果你來自傳統OOP的背景,原型繼承看起來很奇怪,但它在概念上更簡單易懂,而且在某些方面它實際上更強大。如果您想了解更多關於JavaScript的原型繼承,我強烈建議這些文章:

http://javascript.crockford.com/prototypal.html

http://www.laktek.com/2011/02/02/understanding-prototypical-inheritance-in-javascript/

http://blog.vjeux.com/2011/javascript/how-prototypal-inheritance-really-works.html

http://howtonode.org/prototypical-inheritance

另外,如果你需要這種靈活性,您可能需要考慮使用「實體系統」,它可以提供多種優勢作爲複雜層次結構o的替代方案f繼承。大多數關於實體系統的文章都集中在遊戲開發上,但我認爲這種體系結構也可能對其他應用程序有用。對OOP程序員來說這是一個非常陌生的概念,所以把所有關於OOP的知識放在一邊,並從關係數據庫設計的角度思考更多。檢查出來:

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/

回答

4

ModifiedConstructor不是OriginalConstructor副本,它是同一個功能。

第一指令在eval's algorithm是:

如果Type(X)不是字符串,返回X

即你簡單地回來你通過什麼。OriginalConstructor === ModifiedConstructor產量true

有沒有辦法修改一個對象(或未來的實例),而不影響已經實例化從相同的構造函數的其他對象?

您可以通過原型繼承:

ModifiedConstructor = function() { 
    OriginalConstructor.apply(this, arguments); 
}; 

ModifiedConstructor.prototype = Object.create(OriginalConstructor.prototype); 
ModifiedConstructor.prototype.constructor = ModifiedConstructor; 

現在你可以添加功能ModifiedConstructor.prototype而不影響OriginalConstructor創建的實例。

如果您只想防止已經創建的實例被擴展,那麼您可以覆蓋OriginalConstructor.prototype,但這不是一個乾淨的解決方案,並且也會爲現有實例打破instanceOf

相關問題