JavaScript 中是否有一种“简洁”的命名空间方法?
-
08-06-2019 - |
题
我经常遇到将所有 JavaScript 放在一个 namespace
结构大致如下:
namespaces = { com : { example: { example.com's data} }
然而,相对于其他命名空间框架安全地设置它似乎需要相对大量的代码(定义为 > 2 行)。我想知道是否有人知道一个简洁的方法来做到这一点?此外,是否有一个相对标准/一致的方式来构建它?例如,是 com
命名空间直接附加到全局对象,还是通过命名空间对象附加?
[编辑:哎呀,显然 {com = { ... } }
不会完成任何接近我预期的事情,感谢 Shog9 指出了这一点。]
解决方案
Javascript 没有独立的命名空间。它具有函数(可以提供解析名称的范围)和对象(可以有助于在给定范围内访问命名数据)。
这是您的示例,已更正:
var namespaces = { com: { example: { /* example.com's data */ } } }
这是一个变量 namespaces
被分配一个对象文字。该对象包含一个属性: com
, ,具有一个属性的对象: example
, ,一个可能包含一些有趣的东西的对象。
所以,你可以输入类似的内容 命名空间.com.example。示例中的某些属性或函数 一切都会成功的。当然,这也是可笑的。您没有分层命名空间,您有一个对象,其中包含一个对象,其中包含一个包含您真正关心的内容的对象。
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 命名空间. 。他讨论了 3 种不同类型的 Javascript 命名空间:
- 前缀命名空间
- 单个对象命名空间
- 嵌套对象命名空间
我不会抄袭他在这里所说的内容,但我认为他的文章内容非常丰富。
Peter 甚至指出其中一些存在性能方面的考虑。考虑到新的 ECMAScript Harmony 计划已经放弃了命名空间和打包的 4.0 计划,我认为谈论这个话题会很有趣。
我尝试遵循雅虎约定,在全局范围内创建一个父对象来包含所有内容;
var FP = {};
FP.module = {};
FP.module.property = 'foo';
为了确保不会覆盖现有对象,您应该这样做:
if(!window.NameSpace) {
NameSpace = {};
}
或者
var NameSpace = window.NameSpace || {};
这样您就可以将其放在应用程序/网站中每个文件的顶部,而不必担心覆盖名称空间对象。此外,这将使您能够单独为每个文件编写单元测试。
这 YUI库 库中有一些代码可以使用您可能更喜欢的函数来处理命名空间。其他图书馆也可能这样做。
作为点或下划线的替代,您可以使用美元符号字符:
var namespaces$com$example = "data";
我也喜欢这个(来源):
(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 元素接口定义:
- HTML标题元素
- SVG标题元素
- SVG脚本元素
- HTML脚本元素
JavaScript 核心使用原型来命名 toString
方法作为多态性的简单形式。
参考