如何在JavaScript中创建命名空间,使我的对象和函数不被其他同名对象和函数覆盖?我使用了以下方法:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
有没有更优雅或更简洁的方式来做到这一点?
如何在JavaScript中创建命名空间,使我的对象和函数不被其他同名对象和函数覆盖?我使用了以下方法:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
有没有更优雅或更简洁的方式来做到这一点?
当前回答
我创建的命名空间是受到Erlang模块的启发。这是一种非常实用的方法,但这就是我最近编写JavaScript代码的方式。
它为闭包提供全局名称空间,并在闭包中公开已定义的集合函数。
(function(){
namespace("images", previous, next);
// ^^ This creates or finds a root object, images, and binds the two functions to it.
// It works even though those functions are not yet defined.
function previous(){ ... }
function next(){ ... }
function find(){ ... } // A private function
})();
其他回答
这是Ionuț G. Stan的回答的后续,但通过使用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
我写了另一个命名空间库,它的工作方式有点像其他语言中的包/单元。它允许你创建一个JavaScript代码包,并从其他代码中引用这个包:
文件hello.js
Package("hello", [], function() {
function greeting() {
alert("Hello World!");
}
// Expose function greeting to other packages
Export("greeting", greeting);
});
文件Example.js
Package("example", ["hello"], function(greeting) {
// Greeting is available here
greeting(); // Alerts: "Hello World!"
});
页面中只需要包含第二个文件。它的依赖项(本例中的文件hello.js)将自动加载,从这些依赖项导出的对象将用于填充回调函数的参数。
你可以在Packages JS中找到相关的项目。
我喜欢Jaco Pretorius的解决方案,但我想通过将“this”关键字指向模块/名称空间对象来使其更有用。 我的煎锅版本:
(function ($, undefined) {
console.log(this);
}).call(window.myNamespace = window.myNamespace || {}, jQuery);
有没有更优雅或更简洁的方式来做到这一点?
是的。例如:
var your_namespace = your_namespace || {};
然后你就可以
var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:'test'};
your_namespace.Bar = function(arg)
{
alert(arg);
};
with(your_namespace)
{
Bar(Foo.toAlert);
}
我使用在企业jQuery网站上找到的方法:
下面是他们的例子,展示了如何声明私有和公共属性和函数。一切都是作为一个自动执行的匿名函数完成的。
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.ingredient = "Bacon Strips";
//Public Method
skillet.fry = function() {
var oliveOil;
addItem( "\t\n Butter \n\t" );
addItem( oliveOil );
console.log( "Frying " + skillet.ingredient );
};
//Private Method
function addItem( item ) {
if ( item !== undefined ) {
console.log( "Adding " + $.trim(item) );
}
}
}( window.skillet = window.skillet || {}, jQuery ));
如果你想访问某个公共成员你只需输入skillet。fry()或skillet。配料。
真正酷的是,现在可以使用完全相同的语法扩展名称空间。
//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
//Private Property
var amountOfGrease = "1 Cup";
//Public Method
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
console.log( isHot ? "Hot" : "Cold" );
};
}( window.skillet = window.skillet || {}, jQuery ));
第三个未定义的参数
The third, undefined argument is the source of the variable of value undefined. I'm not sure if it's still relevant today, but while working with older browsers / JavaScript standards (ecmascript 5, javascript < 1.8.5 ~ firefox 4), the global-scope variable undefined is writable, so anyone could rewrite its value. The third argument (when not passed a value) creates a variable named undefined which is scoped to the namespace/function. Because no value was passed when you created the name space, it defaults to the value undefined.