提问人:olliej 提问时间:8/16/2008 最后编辑:Stephen Kingolliej 更新时间:4/20/2018 访问量:3511
有没有一种“简洁”的方法来在 JavaScript 中进行命名空间?
Is there a "concise" way to do namespacing in JavaScript?
问:
我经常遇到一些网站,他们把所有的JavaScript都放在一个结构中,如下所示:namespace
namespaces = { com : { example: { example.com's data} }
但是,相对于其他命名空间框架安全地设置它似乎需要相对较多的代码(定义为 > 2 行)。我想知道是否有人知道一种简洁的方法可以做到这一点?此外,是否有一种相对标准/一致的方法来构建它?例如,命名空间是直接附加到全局对象,还是通过命名空间对象附加?com
[编辑:哎呀,显然不会完成任何接近我预期的事情,感谢 Shog9 指出这一点。{com = { ... } }
答:
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() { /* ... */ }
};
})();
...恕我直言,这是相当简洁的。
评论
com_example
com_something_else
com_etc
com
YUI 库库的代码使用您可能认为更可取的函数来处理命名空间。其他库也可以这样做。
这是 Peter Michaux 关于 Javascript 命名空间的一篇有趣的文章。他讨论了 3 种不同类型的 Javascript 命名空间:
- 前缀命名空间
- 单个对象命名空间
- 嵌套对象命名空间
我不会剽窃他在这里说的话,但我认为他的文章信息量很大。
彼得甚至指出,其中一些存在性能方面的考虑。考虑到新的 ECMAScript Harmony 计划已经放弃了名称空间和打包的 4.0 计划,我认为这个话题会很有趣。
我尝试遵循 Yahoo 的惯例,即在全局范围内制作一个父对象来包含所有内容;
var FP = {};
FP.module = {};
FP.module.property = 'foo';
作为点或下划线的替代方法,您可以使用美元符号字符:
var namespaces$com$example = "data";
评论
为了确保你不会覆盖现有对象,你应该这样做:
if(!window.NameSpace) {
NameSpace = {};
}
或
var NameSpace = window.NameSpace || {};
这样,您可以将其放在应用程序/网站中每个文件的顶部,而不必担心覆盖命名空间对象。此外,这将使您能够为每个文件单独编写单元测试。
我也喜欢这个(来源):
(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());
或者不带 explicit 属性: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);
使用 or 构造函数将名称属性添加到计数器变量和其他公用名称,然后使用测试进行检查: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 元素接口定义:
- HTMLTitle元素
- SVGTitle元素
- SVGScript元素
- HTMLScript元素
JavaScript 核心使用原型将方法命名为多态的简单形式。toString
引用
评论