Javascript命名空间污染问题

Ash*_*ain 0 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();
Run Code Online (Sandbox Code Playgroud)

我收集我可以安全地跳过原型步骤并且简单地拥有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);
};
Run Code Online (Sandbox Code Playgroud)

这是在Chrome 8测试,我无法弄清楚如何SomeObject已经到了必须SomeFunc为成员.这似乎是我对原型知识有限的漏洞.谁能解释一下?

Ray*_*nos 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");
}    
Run Code Online (Sandbox Code Playgroud)

您需要区分命名空间和构造函数.有没有任何真正的理由为什么命名空间的方法需要写入原型而不是作为对象的属性?

所以对于答案是肯定的,你可以跳过原型.

至于问题二,因为你最初写的原型正在做的是直接在对象上编辑方法.

考虑.prototype成为Class定义.如果您编辑obj.__proto__您编辑ClassObject在运行时.你破坏了所有其他对象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
Run Code Online (Sandbox Code Playgroud)

你看到了警钟吗?你一直在编辑Object类.你身边的所有代码都在崩溃.

功能是对象吗?

Function.property === 5 // oh dear!
Run Code Online (Sandbox Code Playgroud)

我们找到了整个事业.我们一直在将这些方法写入Object.prototype.所以每个对象都有定义的方法.包括.__proto__因为那也是一个对象.

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

万一你想知道thisinstance,this.__proto__Object.prototype.SomeObject.prototypethis.__proto__.__proto__Object.prototype

这里是花园的链接去读它.