JavaScript的实行环境由各种各样的全局变量构成,这些全局变量先于函数实行环境而创建、这些全局变量都挂载于“全局工具”下。当名称有冲突时就会产生一些不可控的问题,比如命名冲突、代码的薄弱性、难以测试等。
在编程开拓中合理的利用命名空间可以避免相同的变量或工具名称产生的冲突,而且命名空间也有助于组织代码有更强的可掩护性和可读性。JavaScript中虽然没有供应原生的命名空间支持,但我们可以利用其他的方法(工具和闭包)实现类似的效果。
1、单一全局变量
JavaScript中一个盛行的命名空间模式是选择一个全局变量作为紧张的引用工具,由于每个可能的全局变量都成为唯一全局变量的属性,也就不用再创建多个全局变量,也就避免了和其他声明的冲突。不过单一全局变量模式已经在不少的JavaScript类库中利用,如:YUI定义了唯一的YUI全局工具,jQuery定义了$和jQuery,$由其他类库利用时利用jQuery等。示例如下:
var myApplication = (function() {
function() {
//
},
return {
//
}
})();
2、命名空间前缀
命名空间前缀模式其思路非常清晰,便是选择一个独特的命名空间,然后在其后面声明声明变量、方法和工具。示例如下:
var = myApplication_propertyA = {};
var = myApplication_propertyA = {};
function myApplication_myMethod() {
//
}
从某种程度上来说,它确实减少了命名冲突的发生概率,但其并没有减少全局变量的数目,在利用这种模式时一定要特殊把稳。
3、工具字面量表示法
工具字面量模式可以认为是包含一组键值对的工具,每一对键和值由冒号分隔,键也可以是代码新的命名空间。示例如下:
var myApplication = {
// 可以很随意马虎的为工具字面量定义功能
getInfo:function() {
//
},
// 可以进一步支撑工具命名空间
models:{},
views:{
pages:{}
},
collections:{}
};
工具字面量为我们供应了优雅的键/值语法,我们可以非常便捷的组织代码封装不同的逻辑或功能,而且可读性、可掩护性、可扩展性极强。
4、嵌套命名空间
嵌套命名空间模式可以说是工具字面量模式的升级版、它也是一种有效的避免冲突模式、由于纵然一个命名空间存在、它也不太可能拥有同样的嵌套子工具、示例如下:
var myApplication = myApplication || {};
// 定义嵌套子工具
myApplication.routers = myApplication.routers || {};
myApplication.routers.test = myApplication.routers.test || {};
当然、我们也可以选择声明新的嵌套命名空间或属性作为索引属性、如:
myApplication[´routers´] = myApplication[´routers´] || {};
利用嵌套命名空间模式可以使代码易读且有组织性,而且相对安全、不易产生冲突,其弱点是如果我们的命名空间嵌套过多会增加浏览器的查询事情量。
5、立即调用的函数表达式
立即调用函数(IIFE)实际上便是匿名函数,被定义后立即被调用。IIFE是用于封装运用程序逻辑的常用方法,以保护它免受全局名称空间的影响。示例如下:
// 命名空间和undefined作为参数通报,确保:
// 1.命名空间可以在局部修正,不重写函数外部高下文
// 2.undefined 的参数值是确保undefined,避免ES5规范里定义的undefined
(function (namespace, undefined) {
// 私有属性
var foo = \"大众foo\"大众;
bar = \"大众bar\公众;
// 公有方法和属性
namespace.foobar = \"大众foobar\"大众;
namespace.sayHello = function () {
say(\"大众Hello World!\"大众);
};
// 私有方法
function say(str) {
console.log(\公众You said:\公众 str);
};
})(window.namespace = window.namespace || {});
可扩展性是任何可伸缩命名空间模式的关键,利用IIFE可以轻松实现这一目的,我们可以再次利用IIFE给命名空间添加更多的功能。
6、命名空间注入
命名空间注入是IIFE的另一个变体,从函数包装器内部为一个特定的命名空间“注入”方法和属性,利用this作为命名空间代理,这种模式的优点是可以将功能行为运用到多个工具或命名空间。示例如下:
var myApplication = myApplication || {};
myApplication.utils = {};
(function () {
var value = 5;
this.getValue = function () {
return value;
}
// 定义新的子命名空间
this.tools = {};
}).apply(myApplication.utils);
(function () {
this.diagnose = function () {
return \"大众diagnose\"大众;
}
}).apply(myApplication.utils.tools);
// 同样的办法在普通的IIFE上扩展功能,仅仅将高下文作为参数通报并修正,而不是仅仅利用this,如果你常常被全局变量冲突困扰,一定要牢记JavaScript命名空间知识点。