JavaScript名称空间污染问题 [英] Javascript namespace pollution issue

查看:86
本文介绍了JavaScript名称空间污染问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是接触Javascript,所以我对命名空间的第一次尝试最终看起来像这样:

I'm just getting in to Javascript, so my first attempt at namespaces ended up looking like this:

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对象实例,因此原型不会保存任何内容.

I gather I can safely skip the prototype step and simply have myNameSpace.SomeFunc = function..., because there's only ever one myNameSpace object instance so the prototype doesn't save anything.

问题1:这是正确的吗?我想从几个单独的.js文件添加到名称空间,所以这种方式似乎很方便.

Question 1: Is this correct? I want to add to the namespace from several separate .js files, so this way seems convenient.

问题2:通过上面的代码片段,我发现了名称空间污染的怪异副作用,如以下SomeObject正文所示:

Question 2: With the above code snippet I found a weird side-effect of namespace pollution, which is shown by the following SomeObject body:

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的成员.在我对原型的有限了解中,这似乎是一个漏洞.有人可以解释吗?

This was tested on Chrome 8 and I can't figure out how SomeObject has come to have SomeFunc as a member. This seems to be a hole in my limited knowledge of prototypes. Can someone explain?

推荐答案

让我们从基础开始.

请勿触摸__proto__.这是潘多拉的盒子.你不想惹那个.不仅不支持跨浏览器,而且您可以编写一些丑陋的代码,而无需使用它.

Don't touch __proto__. It's a pandora's box. You do not want to mess with that. Not only is it not supported cross-browser but you can write some hideous code and there's no need to use it.

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");
}    

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

You need to distinquish between a namespace and a constructor. Is there any real reason why the methods of the namespace needs to be written to the prototype rather then as properties of the object?

因此,要回答一个问题,您可以跳过原型.

So for answer one yes you can skip the prototype.

关于第二个问题,因为您最初实际编写原型时要执行的操作是直接在对象上编辑方法.

As for question two since your writing to the prototype originally what you actaully are doing is editing the methods on the object directly.

.prototype视为Class定义.如果编辑obj.__proto__,则在运行时编辑ObjectClass.您破坏了从该Class派生的所有其他对象.动态类很好.但是从对象内部编辑类是创建晦涩的bug的好方法.

Consider .prototype to be the Class definition. If your editing obj.__proto__ your editing the Class of the Object at run-time. Your corrupting all the other Objects derived from that Class. Dynamic classes are fine. But editing classes from within objects is a really good way to create obscure bugs.

问题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

您看到闹钟了吗?您一直在动态编辑Object类.您周围的所有代码都崩溃了.

Do you see the alarm bells yet? You've been editing the Object class on the fly. All your code around you is falling apart.

函数是对象吗?

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

我们找到了全部原因.我们一直在将这些方法写入Object.prototype.因此,每个对象都在其上定义了该方法.包括.__proto__也是因为它也是一个对象.

We found the entire cause. We've been writing those methods to Object.prototype. So EVERY object has that method defined on it. Including .__proto__ because that's an object too.

我看到与.__proto__打交道是一个坏主意吗?我想我应该再说一遍.

Did I saw that dealing with .__proto__ was a bad idea? I think I should say it again.

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

In case your wondering this was instance, this.__proto__ was Object.prototype.SomeObject.prototype and this.__proto__.__proto__ is Object.prototype

这里是花园的链接.

这篇关于JavaScript名称空间污染问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆