Javascript中的命名空间

来源:互联网 发布:linux下安装wine 编辑:程序博客网 时间:2024/04/27 11:21

在OO编程思想中会经常提到namespace一词,即“命名空间”,也称“名称空间”;在各种语言中是一种代码组织的形式,我们最容易理解的namespace的作用在于可以将命名的变量名或函数名产生重名冲突的风险性降到最小。

在现今随着各种动态语言的大行其道,其中也将namespace这一优良方式引入进来发挥作用;前端开发过程中,我们用的最多的是Javascript这种解释型的语言,那目前所流行的namespacing方式都有哪些呢?今天在这里简单罗列下,方便大家学习:

(下面内容译自于csdn上的一篇博文,由于本人水平有限,肯定会有很多纰漏,还望大家多多指正;只是根据自己的理解进行了简单翻译,有不当之处请大家不吝拍砖!原文地址在文章底部)

从宽泛的方面我们可以归纳为:静态式命名空间和动态式命名空间;

一、静态式命名空间

1.直接赋值

这种直接赋值方式应该说是最基本的方式,代码看起来略显冗余,不利于需要经常重命名命名空间的情况,然而这种方式还是比较安全和清晰的:

  1. var myApp = {}
  2.  
  3. myApp.id = 0;
  4.  
  5. myApp.next = function() {
  6.     return myApp.id++;
  7. }
  8.  
  9. myApp.reset = function() {
  10.     myApp.id = 0;
  11. }
  12.  
  13. window.console && console.log(
  14.     myApp.next(),
  15.     myApp.next(),
  16.     myApp.reset(),
  17.     myApp.next()
  18. ); //0, 1, undefined, 0

上面我们讲到这种赋值方式略显代码冗余,比如太多次的使用myApp这个对象名;基于方便于后期的维护,我们可以使用this关键字进行一点点修改,如下:

  1. var myApp = {}
  2.  
  3. myApp.id = 0;
  4.  
  5. myApp.next = function() {
  6.     return this.id++;
  7. }
  8.  
  9. myApp.reset = function() {
  10.     this.id = 0;
  11. }
  12.  
  13. myApp.next(); //0
  14. myApp.next(); //1

但是,这样会存在一些问题,比如当我再赋值的时候就会容易出错了,如下所示:

  1. var getNextId = myApp.next;
  2. getNextId(); //NaN whoops!出错了

2.使用对象字面量表示法

这种方式只需要命名一次namespace名称,代码显得优雅了些,也便于修改维护了;

  1. var myApp = {
  2.  
  3.     id: 0,
  4.  
  5.     next: function() {
  6.         return this.id++;
  7.     },
  8.  
  9.     reset: function() {
  10.         this.id = 0;
  11.     }
  12. }
  13. window.console && console.log(
  14.     myApp.next(),
  15.     myApp.next(),
  16.     myApp.reset(),
  17.     myApp.next()
  18. ) //0, 1, undefined, 0

3.模块模式

这种方式个人觉得安全性上有所加强,整个逻辑出在一个自动运行的匿名函数中,通过返回一个对象来输出公共接口。当函数执行的时候会将结果赋值于namespace,在函数中处在return之外的对象均是私有的,只有通过return中的特有方法才能访问的到。

  1. var myApp = (function() {
  2.  
  3.     var id= 0;
  4.  
  5.     return {
  6.         next: function() {
  7.             return id++;
  8.         },
  9.  
  10.         reset: function() {
  11.             id = 0;
  12.         }
  13.     };
  14. })();
  15.  
  16. window.console && console.log(
  17.     myApp.next(),
  18.     myApp.next(),
  19.     myApp.reset(),
  20.     myApp.next()
  21. ) //0, 1, undefined, 0

二、动态式命名空间

或者也可以理解为注入式命名空间,这种方式不再需要将返回的值赋予指定的命名空间;这样可以使命名空间的定义更灵活,更独立个性。动态式命名空间不仅囊括了上面提到的模块模式的所有特点,而且还增加了直观性及可读性。

1.命名空间作为参数

将命名空间作为参数传入到一个自动运行的匿名函数中:

  1. var myApp = {};
  2. (function(context) {
  3.     var id = 0;//私有
  4.  
  5.     context.next = function() {//全局
  6.         return id++;
  7.     };
  8.  
  9.     context.reset = function() {//全局
  10.         id = 0;
  11.     }
  12. })(myApp);
  13.  
  14. window.console && console.log(
  15.     myApp.next(),
  16.     myApp.next(),
  17.     myApp.reset(),
  18.     myApp.next()
  19. ) //0, 1, undefined, 0

上面代码片段中注意到变量id是私有的,因为它并没有分配到命名空间myApp中。这里大家也许已经预见到了,上面的代码只需要改动一个单词就可以将上下文环境转换成全局的,这个淫荡的概念出自于JQuery框架的开发者John Resig。

  1. var myApp = {};
  2. (function(context) {
  3.     var id = 0;
  4.  
  5.     context.next = function() {
  6.         return id++;
  7.     };
  8.  
  9.     context.reset = function() {
  10.         id = 0;
  11.     }
  12. })(this);

2.应用this关键字作为命名空间代理

这种方式其实也蛮常见的,简单理解即为利用this关键字代理当前的执行环境,防止被任意篡改。

  1. var myApp = {};
  2. (function() {
  3.     var id = 0;
  4.  
  5.     this.next = function() {
  6.         return id++;
  7.     };
  8.  
  9.     this.reset = function() {
  10.         id = 0;
  11.     }
  12. }).apply(myApp)

基于apply(call)方法的APIs,可以进行如下类似扩展:

  1. var subsys1 = {}, subsys2 = {};
  2. var nextIdMod = function(startId) {
  3.     var id = startId || 0;
  4.  
  5.     this.next = function() {
  6.         return id++;
  7.     };
  8.  
  9.     this.reset = function() {
  10.         id = 0;
  11.     }
  12. };
  13.  
  14. nextIdMod.call(subsys1);
  15. nextIdMod.call(subsys2,1000);
  16.  
  17. window.console && console.log(
  18.     subsys1.next(),
  19.     subsys1.next(),
  20.     subsys2.next(),
  21.     subsys1.reset(),
  22.     subsys2.next(),
  23.     subsys1.next()
  24. ) //0, 1, 1000, undefined, 1001, 0

以上就是目前经常会用到的一些namespacing的方式,也许不是太全面,如果有其它方式了解到再进行补充。


原创粉丝点击