2011-01-28 137 views
0

我剛開始在爲Javascript,所以我在命名空間中的第一次嘗試最終看上去像這樣:的Javascript命名空間污染問題

var myNameSpace = {}; 
var myNameSpaceProto = myNameSpace.__proto__; 

myNameSpaceProto.SomeFunc = function() 
{ 
    alert("SomeFunc()"); 
}; 

myNameSpaceProto.SomeObject = function() 
{ 
    alert("SomeObject constructor"); 
}; 

var instance = new myNameSpace.SomeObject(); 

我收集我可以跳過原型步驟,只需有myNameSpace.SomeFunc = function...,因爲只有一個myNameSpace對象實例,所以原型不保存任何東西。

問題1:這是正確的嗎?我想從幾個獨立的.js文件添加到命名空間,所以這種方式看起來很方便。

問題2:與上面的代碼段,我發現的命名空間的污染,這是由以下SomeObject體所示的奇怪的副作用:

myNameSpaceProto.SomeObject = function() 
{ 
    // As expected NonexistantFunc is not a member of this and returns "undefined" 
    alert("typeof this.NonexistantFunc = " + typeof this.NonexistantFunc); 

    // Returns 'function'. How has SomeFunc made it to this.SomeFunc? It's supposed to be under myNameSpace.SomeFunc 
    alert("typeof this.SomeFunc = " + typeof this.SomeFunc); 

    // Turns out it's in the prototype's prototype. Why? 
    alert("this.__proto__.__proto__.SomeFunc = " + this.__proto__.__proto__.SomeFunc); 
}; 

這是在Chrome 8和I可以測試不知道如何SomeObject已成爲SomeFunc成員。這似乎是我對原型有限知識的一個漏洞。有人可以解釋嗎?

回答

10

讓我們從基礎開始。

請勿觸摸__proto__。這是潘多拉的盒子。你不想搞砸這個。它不僅不支持跨瀏覽器,而且可以編寫一些可怕的代碼,因此不需要使用它。

var Constructor = new Function; 
Constructor.fn = Constructor.prototype; 

Constructor.fn.someFunc = function() { 
    alert("someFunc"); 
} 

var obj = new Constructor; 

var namespace = {}; 
namespace.someStaticFunc = function() { 
    alert("someStaticFunc"); 
}  

您需要區分名稱空間和構造函數。是否有真正的原因,爲什麼名稱空間的方法需要寫入原型而不是作爲對象的屬性?

所以爲了回答一個是的,你可以跳過原型。

至於第二個問題,因爲你最初寫的原型是你實際做的是直接編輯對象的方法。

考慮將.prototype定義爲Class的定義。如果您在運行時編輯obj.__proto__您編輯ObjectClass。你的腐敗所有其他對象派生自那個Class。動態類很好。但是,從對象中編輯類是創建晦澀難懂的錯誤的好方法。

問題2:很奇怪。

這裏發生的事情:

var o = {}; // Ok o is an object 
var o.__proto__.property = 5; // Ok I changed o's class and it now has a property = 5. 

var o.__proto__.construct = function() { }; // Ok I changed the class again it now has a constructor 

var p = new o.construct(); // we create an object from my constructor. 

(p.__proto__ === o.construct.prototype) // true! the proto object is o.c.prototype. Because 
// p is created from o.c so the prototype is that of o.c 

(o.construct.__proto__ === Object.prototype) // true! Oh-uh. Now look what we've been doing! 
// When you created `var o = {}` and edited o.__proto__ you've been editing Object.prototype 

你看到的警鐘嗎?您一直在編輯對象類。你周圍的所有代碼都崩潰了。

函數是一個對象嗎?

Function.property === 5 // oh dear! 

我們找到了全部原因。我們一直在寫這些方法到Object.prototype。所以每一個對象都有它定義的方法。包括.__proto__,因爲那也是一個對象。

我看到與.__proto__打交道是不是一個好主意?我想我應該再說一遍。

如果你想知道thisinstancethis.__proto__Object.prototype.SomeObject.prototypethis.__proto__.__proto__Object.prototype

這裏給garden去閱讀它的鏈接。

+1

謝謝,很好的答案:)我來自C++背景,人們說* *語言有陷阱... – AshleysBrain 2011-01-28 17:29:15