我还没有在互联网上找到一个常见的方法来在JavaScript中创建命名空间。
创建命名空间的最佳方式是什么(并列出该特定方法可能存在的任何缺点)。
我还没有在互联网上找到一个常见的方法来在JavaScript中创建命名空间。
创建命名空间的最佳方式是什么(并列出该特定方法可能存在的任何缺点)。
(function() {
var usefulVariable;
var foo = {
bar:function(){ alert('hi') }
};
// leak into global namespace
window.foo = foo;
})();
只有foo
暴露在全局命名空间中,并且它“存在于”您的私有自执行匿名函数命名空间中。
var MyNS = {
f1: function() {...},
f2: function() {...}
};
正如其他人试图展示的那样,如果你想在你的命名空间中提供一个私有作用域(建议这样做),以下方法是最合适的:
var MyNS = (function() {
var private1 = "...",
private2 = "...";
return {
f1: function() {...},
f2: function() {...}
}
})();
var myNamespace = (function(ns) {
ns.f1 = function() { ... };
ns.f2 = function() { ... };
return ns;
})(window.myNamespace || {});
在这里,myNamespace被赋值为匿名自执行函数返回的值,该函数接收参数ns。正如大家所看到的,该参数的值要么是window.myNamespace,要么是一个空对象,具体取决于myNamespace是否已经被声明。
var MyNamespace = new function(){
this.MY_CONST_ONE = 1;
this.MY_CONST_TWO = 2;
this.MyClass = function (x) {
this.x = x;
}
this.MyOtherClass = function (y) {
this.y = y;
}
} // end of namespace
// ...
var oc = new MyNamespace.MyOtherClass(123);
有趣的是,闭包函数使用 new
而不是普通括号进行调用,因此直接在其中,this
指的是函数返回的对象,换句话说,就是“命名空间”本身。
我通常尽量保持简单,创建一个表示命名空间的全局对象。如果您正在使用多个脚本,每个脚本都声明命名空间,因为它们可能在不同的应用程序中使用,那么您可能需要检查对象是否已经存在。
//create the namespace - this will actually obliterate any pre-existing
//object with the same name in the global namespace
//(and this does happen).
//NB ommiting the var keyword automatically chucks the object
//variable into the global namespace - which ordinarily you
//don't want to do
MyNameSpace = {};
//and then create a class/object in the namespace
MyNameSpace.MyClass = {
someProperty: function(){
//do something
},
anotherProperty: function(){
//doing something else
}
};
这基本上就是其他人所说的。我只是提供了一个非常简单的方法。我看到的主要缺点是理论上“MyNameSpace”对象可能已经存在 - 因此在创建它之前可能需要检查一下。通常,如果我要做比那更复杂的事情,我会开始考虑像JQuery或ExtJS这样的框架,这些框架可以大大减轻这些问题的痛苦。
还有一点需要注意的是,你不能找到Javascript中许多事情的共同方法,比如创建命名空间,部分原因是在Javascript中总有不止一种方法来解决问题。大多数语言对于如何做事情都很规范 - 创建类,是函数式的还是面向对象的或过程化的。另一方面,Javascript缺少关键字,高度灵活。这可能是好事或坏事 - 取决于你的观点。但我很喜欢它。
window.Object
)中)。接下来,我们可以在core.js
脚本文件中创建一个模块:
(function(global) {
var coreModule = {};
var MY_CONSTANT = 42
var meaningOfLife = function() {
return MY_CONSTANT;
};
coreModule.meaningOfLife = meaningOfLife;
global.myRootNamespace = coreModule;
}(this));
utils.js
文件中:(function(root) {
var utilsModule = root.utils = {};
utilsModule.bark = function() {
console.log("WOOF!");
};
}(myRootNamespace));
myRootNamespace
对象上的utils
属性的值。但是,我们可以编写代码,使其不会这样做。(function(root) {
var utilsModule = root.utils = root.utils || {};
utilsModule.bark = function() {
console.log("WOOF!");
};
}(myRootNamespace));
如果不想使用模块模式,我们可以使用一个简单的函数以非破坏性的方式为我们定义命名空间:
var ensureNamespace = function recur(ns, root) {
var parts = typeof ns === 'string' ? ns.split('.') : ns;
var r = root || this;
if (parts[0]) {
var next = parts.shift()
r[next] = r[next] || {};
return recur(parts, r[next]);
}
return r;
};
// maybe another file:
(function(){
var baz = ensureNamespace("foo.bar.baz");
// baz === window.foo.bar.baz;
baz.qux = "Yep...";
}());
查看这篇优秀文章以获取更多见解。
你可以结合目前为止收到的答案,取得更大的成就;
var Foo; // declare in window scope.
(function(){
var privateVar = "BAR!";
// define in scope of closure where you can make a mess that
// doesn't leak into the window scope.
Foo = {
staticFunc: function(){ return privateVar; }
};
})();
我通常避免使用window.xxxx = yyyy;
,因为它不总是与Visual Studio Intellesense兼容。可能还有其他问题,但我不知道。
我相信模块模式已经证明了它是正确的选择。对象字面量命名空间将所有内容暴露给命名空间外的调用者代码,这本质上不是一个很好的想法。
如果你坚持创建对象字面量命名空间,请阅读这篇教程。我认为它简单易懂,而且非常全面:JavaScript中的对象字面量命名空间(OLN)
foo.bar
即可。如果我没有通过window.foo
公开它,那么foo
只能在该函数内部访问。 - meder omuralievthis.foo=foo
,因为window
是非标准的,在这种情况下你已经在全局范围内了?同样,为什么不使用this.foo = {...
而不是var foo = {...
呢? - Dagg Nabbit