Javascript命名空间污染问题

时间:2011-01-28 00:51:03

标签: javascript prototype namespaces

我刚刚进入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上测试的,我无法弄清SomeObject如何成为SomeFunc成员。这似乎是我对原型知识有限的漏洞。有人可以解释一下吗?

2 个答案:

答案 0 :(得分: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__,则需要在运行时编辑Class的{​​{1}}。您破坏了从Object派生的所有其他对象。动态类很好。但是,从对象内编辑类是创建模糊错误的一种非常好的方法。

问题2:很奇怪。

以下是发生的事情:

Class

你看到了警钟吗?你一直在编辑Object类。你周围的所有代码都在崩溃。

功能是对象吗?

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

我们找到了整个事业。我们一直在将这些方法写入Object.prototype。所以每个对象都定义了该方法。包括Function.property === 5 // oh dear! ,因为那也是一个对象。

我是否看到处理.__proto__是一个坏主意?我想我应该再说一遍。

如果您想知道.__proto__thisinstancethis.__proto__Object.prototype.SomeObject.prototypethis.__proto__.__proto__

以下是garden Go的链接。

答案 1 :(得分:-1)

答案2: SomeObject可以SomeFunc访问this,因为myNameSpaceProtoSomeObject不是 {{1}}。

<击> Quirksmode has a decent explanation of why.

Here's a much better article explaining it.

所以,正如您可能已经猜到的那样,答案1:是。