有没有一种“简洁”的方式来在JavaScript中进行命名空间?
我经常遇到的网站,把所有的JavaScript的一个“命名空间”结构内沿有没有一种“简洁”的方式来在JavaScript中进行命名空间?
namespaces = { com : { example: { example.com's data} }
但相对于其他命名空间框架的安全设置此功能似乎线路需要相对大幅金额代码(定义为> 2行)。我想知道是否有人知道一个简洁的方法来做到这一点?以及是否有相对标准/一致的方式来构建它?例如。是直接连接到全局对象的“com”名称空间还是通过名称空间对象连接?
[编辑:哎呀,明显{com = { ... } }
不会完成任何接近我的意图,感谢Shog9指出。 :D]
Javascript没有独立的命名空间。它具有可以提供解析名称范围的函数和对给定范围内可访问的指定数据有贡献的对象。
这里是你的榜样,纠正:
var namespaces = { com: { example: { /* example.com's data */ } } }
这是一个变量namespaces
被分配一个对象常量。该对象包含一个属性:com
,具有一个属性的对象:example
,这个对象大概会包含一些有趣的内容。
所以,你可以输入类似namespaces.com.example。 somePropertyOrFunctionOnExample它会一切正常。当然,这也很荒谬。您没有分层名称空间,您的对象包含一个包含您实际关心的对象的对象。
var com_example_data = { /* example.com's data */ };
那的作品一样好,没有无谓的层次结构。
现在,如果你真的想向建立一个层次,你可以尝试这样的事:
com_example = com_example || {};
com_example.flags = com_example.flags || { active: false, restricted: true};
com_example.ops = com_example.ops || (function()
{
var launchCodes = "38925491753824"; // hidden/private
return {
activate: function() { /* ... */ },
destroyTheWorld: function() { /* ... */ }
};
})();
......这是,恕我直言,相当简洁。
这是一篇由Peter Michaux撰写的关于Javascript Namespacing的有趣文章。他讨论了3种不同类型的Javascript命名空间的:
- 前缀命名空间
- 单一对象命名空间
- 嵌套对象命名空间
我不会抄袭了他在这里说,但我认为他的文章是非常翔实。
彼得甚至指出,其中一些人有性能方面的考虑。我认为这个话题很有意思,因为考虑到新的ECMAScript Harmony计划已经放弃了命名空间和包装的4.0计划。
我试图按照雅虎的惯例在全球范围内制作单个父对象来包含所有内容;
var FP = {};
FP.module = {};
FP.module.property = 'foo';
作为替代点或下划线,你可以使用美元符号:
var namespaces$com$example = "data";
为了确保不覆盖现有对象,你要那么是这样的:
if(!window.NameSpace) {
NameSpace = {};
}
或
var NameSpace = window.NameSpace || {};
通过这种方式,您可以将它放在应用程序/网站中每个文件的顶部,而不用担心覆盖命名空间对象。此外,这将使您能够为每个文件单独编写单元测试。
我想也是这个(source):
(function() {
var a = 'Invisible outside of anonymous function';
function invisibleOutside() {
}
function visibleOutside() {
}
window.visibleOutside = visibleOutside;
var html = '--INSIDE Anonymous--';
html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside;
html += '<br/> typeof visibleOutside: ' + typeof visibleOutside;
contentDiv.innerHTML = html + '<br/><br/>';
})();
var html = '--OUTSIDE Anonymous--';
html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside;
html += '<br/> typeof visibleOutside: ' + typeof visibleOutside;
contentDiv.innerHTML += html + '<br/>';
使用对象文本,要么在this
对象或明确的名称做命名空间基础上,包含了函数的局部变量的兄弟性能。例如:
var foo = { bar: function(){return this.name; }, name: "rodimus" }
var baz = { bar: function(){return this.name; }, name: "optimus" }
console.log(foo.bar());
console.log(baz.bar());
或不明确的name
属性:
var foo = { bar: function rodimus(){return this; } }
var baz = { bar: function optimus(){return this; } }
console.log(foo.bar.name);
console.log(baz.bar.name);
使用或不使用this
:
var foo = { bar: function rodimus(){return rodimus; } }
var baz = { bar: function optimus(){return optimus; } }
console.log(foo.bar.name);
console.log(baz.bar.name);
使用RegExp
或Object
构造函数添加名称的属性来对抗变量和其他共同的名字,然后用hasOwnProperty
测试做检查:
var foo = RegExp(/bar/);
/* Add property */
foo.name = "alpha";
document.body.innerHTML = String("<pre>" + ["name", "value", "namespace"] + "</pre>").replace(/,/g, "	");
/* Check type */
if (foo.hasOwnProperty("name"))
{
document.body.innerHTML += String("<pre>" + ["foo", String(foo.exec(foo)), foo.name] + "</pre>").replace(/,/g, "	");
}
/* Fallback to atomic value */
else
{
foo = "baz";
}
var counter = Object(1);
/* Add property */
counter.name = "beta";
if (counter.hasOwnProperty("name"))
{
document.body.innerHTML += String("<pre>" + ["counter", Number(counter), counter.name] + "</pre>").replace(/,/g, "	");
}
else
{
/* Fallback to atomic value */
counter = 0;
}
DOM使用以下约定来命名空间HTML和SVG元素接口定义:
- HTMLTitleElement
- SVGTitleElement
- SVGScriptElement
- HTMLScriptElement
JavaScript的核心采用原型来命名空间中的toString
方法多态性的简单形式。
参考
- Does javascript autobox?
- Getting sibling value of key in a JavaScript object literal
- MDN: JavaScript Operators - this as an object method
- Lua: technical note 7 - Modules and Packages
- HTMLTitleElement.webidl
- SVGTitleElement.webidl
- SVGScriptElement.webidl
- HTMLScriptElement.webidl
- The names of functions in ES6
- ECMAScript 2015 Language Specification - 19.2.4.2 Function Instances: name | ECMA-262 6th Edition
虽然,现在`com_example`将是全局对象的一部分。假设我们添加了更多的对象`com_something_else`,`com_etc`,那么我们仍然在污染全局对象的根级别。如果我们在全局只有一个`com`对象,那么所有其他对象都被添加了吗?另外,我们不想覆盖任何现有对象,如果使用多个库,会发生什么情况。 – Peter 2011-10-04 05:00:28
@Peter:如果多个库定义相同的符号,无论如何你都会遇到问题;这就是为什么像jQuery这样的图书馆需要这么长的时间才能将所有内容填充到单个全局对象中我的观点并不是你应该使用多个顶层对象,而只是用深层嵌套的对象伪造名称空间并不会真正为你购买任何超过疯狂对象名称的东西。查看我最后一个更实用的方法示例:使用不太可能发生碰撞的单个全局名称,然后使用允许不同位代码向其中添加对象的技术。 – Shog9 2011-10-04 15:39:14