2011-01-28 136 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