命名空间

最新更新: 2019-08-30 14:37:29 阅读: 42次

1、前言

命名空间可以被认为是唯一标识符下代码的逻辑分组、为什么会出现命名空间这一概念呢?由于各个头文件是由不同的人设计的,有可能在不同的头文件中用了相同的名字来命名所定义的类或函数,这样在程序中就会出现名字冲突。不仅如此,有可能我们自己定义的名字会与源码库中的名字发生冲突。

命名空间可以帮助我们防止与全局命名空间下的其他对象或变量产生冲突、命名空间也有助于组织代码、有更强的可维护性和可读性。

 通俗的说,每个名字空间都是一个名字空间域,存放在名字空间域中的全局实体只在本空间域内有效。名字空间对全局实体加以域的限制,从而合理的解决命名冲突。


 JavaScript执行环境有很多独特之处、全局变量和函数的使用就是其中之一、JavaScript的执行环境由各种各样的全局变量构成、这些全局变量先于函数执行环境而创建、这些全局变量都挂载于“全局对象”下、在浏览器中、window对象就等同于全局对象

那么、在全局作用域中声明的任何变量和函数都是window对象的属性、当名称有冲突时、就会产生一些不可控的问题、全局变量会带来以下问题:

  • 命名冲突
  • 代码的脆弱性
  • 难以测试 
在编程开发中合理的使用命名空间、可以避免相同的变量或对象名称产生的冲突、而且、命名空间也有助于组织代码、有更强的可维护性和可读性、JavaScript中虽然没有提供原生的命名空间支持、但我们可以使用其他的方法(对象和闭包)实现类似的效果、下面就是一些常见的命名空间模式 


2、单一全局变量


 JavaScript中一个流行的命名空间模式是选择一个全局变量作为主要的引用对象、因为每个可能的全局变量都成为唯一全局变量的属性、也就不用再创建多个全局变量、那么也就避免了和其他声明的冲突、单一全局变量模式已经在不少的JavaScript类库中使用、如:

  • YUI定义了唯一的YUI全局对象
  • jQuery定义了$和jQuery、$由其他类库使用时使用jQuery
  • Dojo定义了一个Dojo全局变量
  • Closure类库定义了一个goog全局对象
  • Underscore类库定义了一个_ 全局对象 



 三、命名空间前缀

命名空间前缀模式其思路非常清晰、就是选择一个独特的命名空间、然后在其后面声明声明变量、方法和对象、示例如下:

var = myApplication_propertyA = {}; var = myApplication_propertyA = {}; function myApplication_myMethod() { // *** }


从某种程度上来说、它确实减少了命名冲突的发生概率、但其并没有减少全局变量的数目、当应用程序规模扩大时、就会产生很多的全局变量、在全局命名空间内、这种模式对其他人都没有使用的这个前缀有很强的依赖、而且有些时候也不好判断是否有人已经使用某个特殊前缀、在使用这种模式时一定要特别注意


四、对象字面量表示法

对象字面量模式可以认为是包含一组键值对的对象、每一对键和值由冒号分隔、键也可以是代码新的命名空


与为对象添加属性一样、我们也可以直接将属性添加到命名空间、对象字面量方法不会污染全局命名空间、并在逻辑上协助组织代码和参数、并且、这种方式可读性和可维护性非常强、当然我们在使用时应当进行同名变量的存在性测试、以此来避免冲突、下面是一些常用的检测方法: 

var myApplication = myApplication || {};
 
if(!myApplication) {
    myApplication  = {};
}
 
window.myApplication || (window.myApplication || {});
 
// 针对jQuery
var myApplication = $.fn.myApplication = function() {};
 
var myApplication = myApplication === undefined ? {} :myApplication;

 五、嵌套命名空间

嵌套命名空间模式可以说是对象字面量模式的升级版、它也是一种有效的避免冲突模式、因为即使一个命名空间存在、它也不太可能拥有同样的嵌套子对象、示例如下:

var myApplication = myApplication || {}; // 定义嵌套子对象 myApplication.routers = myApplication.routers || {}; myApplication.routers.test = myApplication.routers.test || {};


当然、我们也可以选择声明新的嵌套命名空间或属性作为索引属性、如:

myApplicationrouters´] = myApplicationrouters´] || {};


使用嵌套命名空间模式、可以使代码易读且有组织性、而且相对安全、不易产生冲突、其弱点是、如果我们的命名空间嵌套过多、会增加浏览器的查询工作量、我们可以把要多次访问的子对象进行局部缓存、以此来减少查询时间


六、立即调用的函数表达式

立即调用函数(IIFE)实际上就是匿名函数、被定义后立即被调用、在JavaScript中、由于变量和函数都是在这样一个只能在内部进行访问的上下文中被显式地定义、函数调用提供了一种实现私有变量和方法的便捷方式、IIFE是用于封装应用程序逻辑的常用方法、以保护它免受全局名称空间的影响、其在命名空间方面也可以发挥其特殊的作用

 七、命名空间注入

命名空间注入是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



转载自:

1、DD博客的javascript 命名空间