如何在JavaScript中创建命名空间,使我的对象和函数不被其他同名对象和函数覆盖?我使用了以下方法:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
有没有更优雅或更简洁的方式来做到这一点?
如何在JavaScript中创建命名空间,使我的对象和函数不被其他同名对象和函数覆盖?我使用了以下方法:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
有没有更优雅或更简洁的方式来做到这一点?
当前回答
我的习惯是使用函数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();其他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:使用Object.create()创建对象
其他回答
虽然我已经晚了7年,但是在8年前我已经为此做了很多工作:
http://blogger.ziesemer.com/2008/05/javascript-namespace-function.html http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html
能够轻松有效地创建多个嵌套的名称空间,以保持复杂的web应用程序的组织和管理,同时尊重JavaScript全局名称空间(防止名称空间污染),并且在这样做的时候不破坏名称空间路径中的任何现有对象,这是很重要的。
以上是我在2008年前后的解决方案:
var namespace = function(name, separator, container){
var ns = name.split(separator || '.'),
o = container || window,
i,
len;
for(i = 0, len = ns.length; i < len; i++){
o = o[ns[i]] = o[ns[i]] || {};
}
return o;
};
这不是创建名称空间,而是提供了创建名称空间的函数。
这可以浓缩成一个简化的一行代码:
var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g};
使用示例:
namespace("com.example.namespace");
com.example.namespace.test = function(){
alert("In namespaced function.");
};
或者,作为一种说法:
namespace("com.example.namespace").test = function(){
alert("In namespaced function.");
};
然后执行如下:
com.example.namespace.test();
如果你不需要支持旧浏览器,更新版本:
const namespace = function(name, separator, container){
var o = container || window;
name.split(separator || '.').forEach(function(x){
o = o[x] = o[x] || {};
});
return o;
};
现在,我对将命名空间暴露给全局命名空间本身持谨慎态度。(可惜基础语言没有为我们提供这个!)所以我通常会在闭包中使用这个,比如:
(函数(){ Const namespace = function(名称,分隔符,容器){ Var o =容器||窗口; 的名字。split(separator || '.'). foreach(函数(x){ O = O [x] = O [x] || {}; }); 返回啊; }; const ns = namespace("com.ziesemer.myApp"); / /可选: ns.namespace = ns; //进一步扩展,使用ns从这里… } ()); console.log (\ com \”:“com);
在较大的应用程序中,这只需要在页面加载开始时定义一次(对于基于客户端的web应用程序)。如果保留的话,其他文件可以重用命名空间函数(在上面包含为“可选”)。在最坏的情况下,如果这个函数被重新声明了几次——它只需要几行代码,如果简化了,就会更少。
我使用在企业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.
这是user106826到Namespace.js的链接的后续。该项目似乎转移到了GitHub上。现在是smith/namespacedotjs。
我一直在我的小项目中使用这个简单的JavaScript助手,到目前为止,它似乎很轻,但足够通用,可以处理命名空间和加载模块/类。如果它允许我将包导入到我选择的名称空间中,而不仅仅是全局名称空间,那就太好了……唉,但这不是重点。
它允许你声明命名空间,然后在该命名空间中定义对象/模块:
Namespace('my.awesome.package');
my.awesome.package.WildClass = {};
另一种选择是立即声明名称空间及其内容:
Namespace('my.awesome.package', {
SuperDuperClass: {
saveTheDay: function() {
alert('You are welcome.');
}
}
});
要了解更多用法示例,请查看源代码中的example.js文件。
我喜欢这个:
var yourNamespace = {
foo: function() {
},
bar: function() {
}
};
...
yourNamespace.foo();
下面是Stoyan Stefanov在他的JavaScript Patterns一书中是如何做到这一点的,我发现这本书非常好(它还展示了他如何做注释,允许自动生成API文档,以及如何向自定义对象的原型添加一个方法):
/**
* My JavaScript application
*
* @module myapp
*/
/** @namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};
/**
* A maths utility
* @namespace MYAPP
* @class math_stuff
*/
MYAPP.math_stuff = {
/**
* Sums two numbers
*
* @method sum
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} Sum of the inputs
*/
sum: function (a, b) {
return a + b;
},
/**
* Multiplies two numbers
*
* @method multi
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} The inputs multiplied
*/
multi: function (a, b) {
return a * b;
}
};
/**
* Constructs Person objects
* @class Person
* @constructor
* @namespace MYAPP
* @param {String} First name
* @param {String} Last name
*/
MYAPP.Person = function (first, last) {
/**
* First name of the Person
* @property first_name
* @type String
*/
this.first_name = first;
/**
* Last name of the Person
* @property last_name
* @type String
*/
this.last_name = last;
};
/**
* Return Person's full name
*
* @method getName
* @return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
return this.first_name + ' ' + this.last_name;
};