[英]Javascript module Pattern with Namespacing
我一直在使用具有适当名称间隔的JavaScript模块模式进行练习。 所以基本上我声明了名称空间,每个名称空间都封装了某些模块。 这是我到目前为止所写的。 该代码已正确注释。
// namespace has been defined somewhere not to worry that it will be undefined
if (NAMESPACE == null || typeof (NAMESPACE) == 'undefined') {
NAMESPACE = {};
var id = function (id) {
var _all_ids = {};
var persona = {};
var _id = id; // _id is a local variable that stores the argument
var getId = function () { //this function returns the local private variable
return _id;
}
persona.getId = getId;
var _closed = false;
var close = function () {
delete _all_ids[getId()];
this._closed = true;
}
persona.close = close;
return persona; // persona is an object that has two properties `getId` and `close`. Both these are functiona
}
NAMESPACE['id'] = id; // so basically this will become NAMESPACE.id.getId or NAMESPACE.id.close
}
我已经完全注释了该代码,任何人都可以理解。 它声明一个简单的名称空间,然后在其中添加一个模块。 当然,该模块正在使用封装。
我的一位讲师建议此代码具有基本的缺陷标准或其他缺陷标准。 尽管代码运行正常,但我无法弄清楚。
标准明智吗? 还是我做错了?
我对示例进行了扩展以展示原理。
// NAMESPACE with install/define method, like when using require.js
var NAMESPACE = (function ( doc, win ) {
var _modules = {};
return {
'install' : function ( name, definition ) {
if (!_modules.hasOwnProperty(name)) {
_modules[name] = definition;
this[name] = _modules[name];
}
else throw new Error('Module ' + name + ' is already installed.');
}
};
}( document, window ));
// Your actual module to use in the NAMESPACE
NAMESPACE.install('id', (function ( id ) {
var _all_ids = {},
_id = id,
_closed = false;
return {
'getID' : function () {
return _id;
},
'close' : function () {
delete _all_ids[_id];
_closed = true;
}
};
}( 'someDefaultID' )));
// NAMESPACE as an object we pass around
var NAMESPACE = {};
(function ( NAMESPACE ) {
var id,
NAMESPACE = NAMESPACE;
if (NAMESPACE == null || typeof (NAMESPACE) == 'undefined') {
NAMESPACE = {};
window.NAMESPACE = NAMESPACE;
}
id = (function ( id ) {
var _all_ids = {},
_id = id,
_closed = false;
return {
'getID' : function () {
return _id;
},
'close' : function () {
delete _all_ids[_id];
_closed = true;
}
};
}( 'someDefaultID' ));
NAMESPACE['id'] = id;
}( window.NAMESPACE ))
为什么不将函数放在名称空间中?
NAMESPACE = {
id: function (id) {
// The id function in here
}
}
命名空间的目的是避免污染全局范围。 在您的代码中
if (NAMESPACE == null || typeof (NAMESPACE) == 'undefined') {
NAMESPACE = {};
var id = function (id) {
// ...
}
NAMESPACE['id'] = id; // so basically this will become NAMESPACE.id.getId or NAMESPACE.id.close
}
现在在全局范围以及您的命名空间中定义了id
。 这违反了使用名称空间的目的。
重新实现目标名称空间而不污染全局范围的简单JS方法是重新安排
if (NAMESPACE == null || typeof (NAMESPACE) == 'undefined') {
NAMESPACE = {};
NAMESPACE['id'] = function (id) {
// ...
}
}
要么
if (NAMESPACE == null || typeof (NAMESPACE) == 'undefined') {
NAMESPACE = {
id: function (id) {
// ...
}
}
正如@Lekoaf建议的那样。
但是,避免全球污染的现代方法是将所有代码都封装在IIFE中。 虽然有多种方法可以将代码封装在IIFE中,但最简单的方法是直接将其放入
(function(){ // Beginning of IIFE
if (NAMESPACE == null || typeof (NAMESPACE) == 'undefined') {
NAMESPACE = {};
var id = function (id) {
var _all_ids = {};
var persona = {};
var _id = id; // _id is a local variable that stores the argument
var getId = function () { //this function returns the local private variable
return _id;
}
persona.getId = getId;
var _closed = false;
var close = function () {
delete _all_ids[getId()];
this._closed = true;
}
persona.close = close;
return persona; // persona is an object that has two properties `getId` and `close`. Both these are functiona
}
NAMESPACE['id'] = id; // so basically this will become NAMESPACE.id.getId or NAMESPACE.id.close
}
})(); // End of IIFE
您可以使用扩充模块模式,以避免覆盖全局模块及其方法。
//fooModule does not exist, so it is defined as an empty object
var fooModule = (function(app, name, definition) {
if (!app[name]) app[name] = definition;
else throw new Error("this method has already been defined");
return app;
})(fooModule || {}, "foobar", function() {
console.log("foobar");
});
//fooModule now exists, so we use the pre-existing object instead of an empty one
var fooModule = (function(app, name, defintion) {
if (!app[name]) app[namepace] = definition;
else throw new Error("this method has already been defined");
return app;
})(fooModule || {}, "barfoo", function() {
console.log("barfoo");
});
//throws an error because barfoo has already been set to fooModule
var fooModule = (function(app, name, defintion) {
if (!app[name]) app[namepace] = definition;
else throw new Error("this method has already been defined");
return app;
})(fooModule || {}, "barfoo", function() {
console.log("should throw error");
});
fooModule.foobar(); //"foobar"
fooModule.barfoo(); //"barfoo"
重要的部分是myModule || {}
myModule || {}
。 如果模块存在,请使用它,如果不存在,请创建该模块。
这仅解决全局对象上的方法。 你读过这篇文章吗? 可能是我读过的关于模块模式的最佳内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.