如何创建JavaScript中的命名空间,以便我的对象和函数不会被其他同名的对象和函数覆盖?我已经使用了以下代码:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
有没有更优雅或更简洁的方法来做这件事?
如何创建JavaScript中的命名空间,以便我的对象和函数不会被其他同名的对象和函数覆盖?我已经使用了以下代码:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
有没有更优雅或更简洁的方法来做这件事?
我喜欢Jaco Pretorius的解决方案,但我想通过将"this"关键字指向模块/命名空间对象使其更有用。
我的版本:
(function ($, undefined) {
console.log(this);
}).call(window.myNamespace = window.myNamespace || {}, jQuery);
我写了另一个命名空间库,它的工作方式更像其他语言中的包/单元。它允许您创建一个JavaScript代码包,并从其他代码引用该包:
Package("hello", [], function() {
function greeting() {
alert("Hello World!");
}
// Expose function greeting to other packages
Export("greeting", greeting);
});
Package("example", ["hello"], function(greeting) {
// Greeting is available here
greeting(); // Alerts: "Hello World!"
});
只需要在页面中包含第二个文件。它的依赖项(例如本例中的hello.js文件)将自动加载,并且从这些依赖项导出的对象将用于填充回调函数的参数。
您可以在Packages JS中找到相关项目。
var ClassFirst = this.ClassFirst = function() {...}
展示了简洁代码的好处,利用JavaScript的闭包作用域减少了同一命名空间下类的名称冲突。var Namespace = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 123;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
var Namespace2 = new function() {
var ClassFirst = this.ClassFirst = function() {
this.abc = 666;
}
var ClassSecond = this.ClassSecond = function() {
console.log("Cluttered way to access another class in namespace: ", new Namespace2.ClassFirst().abc);
console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
}
}
new Namespace.ClassSecond()
new Namespace2.ClassSecond()
输出:
Cluttered way to access another class in namespace: 123
Nicer way to access a class in same namespace: 123
Cluttered way to access another class in namespace: 666
Nicer way to access a class in same namespace: 666
//Register NameSpaces Function
function registerNS(args){
var nameSpaceParts = args.split(".");
var root = window;
for(var i=0; i < nameSpaceParts.length; i++)
{
if(typeof root[nameSpaceParts[i]] == "undefined")
root[nameSpaceParts[i]] = new Object();
root = root[nameSpaceParts[i]];
}
}
'.'
(点)分隔的命名空间名称即可。
例如:假设您的应用程序名称为oodles。您可以通过以下方法创建一个命名空间。registerNS("oodles.HomeUtilities");
registerNS("oodles.GlobalUtilities");
var $OHU = oodles.HomeUtilities;
var $OGU = oodles.GlobalUtilities;
var oodles = {
"HomeUtilities": {},
"GlobalUtilities": {}
};
"oodles.HomeUtilities"
和"oodles.GlobalUtilities"
的命名空间。要调用这些命名空间,我们使用变量,即var $OHU
和var $OGU
。HomeUtilities
的函数时,将像以下方式声明:$OHU.initialization = function(){
//Your Code Here
};
$OHU
中。在脚本文件的任何地方调用此函数,只需使用以下代码。$OHU.initialization();
JavaScript目前尚未拥有本地名称空间的表示方式,但TypeScript已经支持了。
例如,您可以使用以下TS代码(playground)
namespace Stack {
export const hello = () => console.log('hi')
}
Stack.hello()
如果您无法将代码更新为TS,那么您至少可以使用TS在命名空间生成JS输出时所采用的模式,其格式如下:
var Stack;
(function (Stack) {
Stack.hello = () => console.log('hi');
})(Stack || (Stack = {}));
Stack.hello();
// prelude.hjs
billy = new (
function moduleWrapper () {
const exports = this;
// postlude.hjs
return exports;
})();
// someinternalfile.js
function bob () { console.log('hi'); }
exports.bob = bob;
// clientfile.js
billy.bob();
一旦代码超过1000行,我更喜欢使用Makefile,因为我可以通过在Makefile中删除一行来有效地注释掉大量的代码。这使得调试变得容易。此外,使用这种技术,命名空间只出现在前言中一次,所以很容易更改,而且不必在库代码中重复它。
使用Makefile进行浏览器实时开发的Shell脚本:
while (true); do make; sleep 1; done
var A = A|| {};
A.B = {};
A.B = {
itemOne: null,
itemTwo: null,
};
A.B.itemOne = function () {
//..
}
A.B.itemTwo = function () {
//..
}
我的习惯是使用函数myName()作为属性存储,然后使用var myName作为"方法"的容器...
无论这是否足够合法,都打我吧!我一直依赖我的PHP逻辑,事情就这么简单。:D
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(myObj instanceof Function !== false)
? Object.create({
$props: new myObj(),
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
: console.log('Object creation failed!')
);
if (this !== that) myObj.fName1(); else myObj.fName2();
你也可以以“反之亦然”的方式进行检查,以在对象创建之前进行检查,这种方式更好:
function myObj() {
this.prop1 = 1;
this.prop2 = 2;
this.prop3 = 'string';
}
var myObj = (
(typeof(myObj) !== "function" || myObj instanceof Function === false)
? new Boolean()
: Object.create({
$props: new myObj(),
init: function () { return; },
fName1: function() { /* code.. */ },
fName2: function() { /* code ...*/ }
})
);
if (myObj instanceof Boolean) {
Object.freeze(myObj);
console.log('myObj failed!');
debugger;
}
else
myObj.init();
JavaScript默认不支持命名空间。因此,如果您创建任何元素(函数、方法、对象、变量),它将成为全局变量并污染全局命名空间。让我们举一个没有任何命名空间定义两个函数的例子:
function func1() {
console.log("This is a first definition");
}
function func1() {
console.log("This is a second definition");
}
func1(); // This is a second definition
它总是调用第二个函数定义。在这种情况下,命名空间将解决名称冲突问题。