分享

JavaScript模拟命名空间

 WindySky 2009-07-02

在C++和C#中,命名空间用于尽可能地减少名称冲突。例如,在.NET Framework中,命名空间有助于将Microsoft.Build.Task.Message类与System.Messaging.Message区分开来。JavaScript没有任何特定语言功能来支持命名空间,但很容易使用对象来模拟命名空间。如果要创建一个JavaScript库,则可以将它们包装在命名空间内,而不需要定义全局函数和类,如下所示:

Js代码 复制代码
  1. var MSDNMagNS.Pet = function(name)   
  2. {   
  3.         // code here;   
  4. };   
  5.   
  6. MSDNMagNs.Pet.prototype.toString = function()   
  7. {   
  8.         // code   
  9. };   
  10.   
  11. var pet = new MSDNMagNS.Pet("Yammer");  

 命名空间的一个级别可能不是唯一的,因此可以创建嵌套的命名空间:

Js代码 复制代码
  1. var MSDNMagNS = {};   
  2. // nested namespace "Examples"   
  3. MSDNMagNS.Examples = {};   
  4.   
  5. MSDNMagNS.Examples.Pet = function(name)   
  6. {   
  7.         // code   
  8. };   
  9.   
  10. MSDNMagNS.Examples.Pet.prototype.toString = function()   
  11. {   
  12.         // code   
  13. };   
  14.   
  15. var pet = new MSDNMagNS.Examples.Pet("Yammer");  

 可以想象,键入这些冗长的嵌套命名空间会让人很累。幸运的是,库用户可以很容易地为命名空间指定更短的别名:

Js代码 复制代码
  1. // MSDNMagNS.Examples and Pet definition...   
  2.   
  3. // think "using Eg = MSDNMagNS.Examples;"   
  4.   
  5. var Eg = MSDNMagNS.Examples;   
  6. var pet = new Eg.Pet("Yammer");   
  7. alert(pet);  

 如果看一下Microsoft Ajax库的源代码,就会发现库的作者使用了类似的技术来实现命名空间(请参阅静态方法Type.registerNamespace的实现)。

OOP 和 ASP.NET AJAX

在ASP.NET AJAX中实现的OOP与在本文中讨论的规范实现稍有不同,这主要有两个原因:ASP.NET AJAX版本提供了更多反射可能性(它是诸如 xml 脚本等声明性语法和参数验证所必需的),而且ASP.NET AJAX的目标是将使用.NET的开发人员所熟悉的某些其它构造(例如属、事件、枚举和接口)转换成JavaScript。

在JavaScript当前广泛使用的版本中,它缺少.NET开发人员所熟悉的几个OOP的关键概念,而ASP.NET AJAX可以模拟其中的大多数。

根据命名约定(要遵守的示例),类可以有属性访问器,以及多播事件(符合紧密反映由.NET提供的约定的模式)。私有变量遵守成员以下划线开头则为私有的约定。很少有机会用到真正的私有变量,此策略是为了使调试程序能够监测到这些变量。引入接口也是为了使类型检查能够避免常见的鸭子定型法(一种类型方案,它基于的概念是:如果有什么物体走路和叫声像鸭子,那么它就是鸭子,或至少可以将它视为鸭子)。

类和反射

在JavaScript中,没有办法知道函数的名称。即使这是可能的,但在大多数情况下也没有什么用,因为类构造函数通常是通过向命名空间变量分配匿名函数来构造的。实际构成类型名称的是此变量的完全限定名称,它同样不可访问,并且构造函数本身对它一无所知。为了规避此限制,并使JavaScript类有丰富的反射,ASP.NET AJAX需要将类型名称进行注册。

ASP.NET AJAX中反射的API将检查所有类型(无论是内置类型、类、接口、命名空间或者甚至是枚举),而它们包括的类似.NET Framework 的函数(例如 isInstanceOfType和inheritsFrom)可以在运行时检查类的层次结构。ASP.NET AJAX 还会在调试模式下执行某些类型检查,这对开发人员更早的捕获Bug很有帮助。

注册类层次结构和调用基础函数

若要在ASP.NET AJAX中定义类,您需要将其构造函数赋给变量(注意,构造函数如何调用举出函数):

Js代码 复制代码
  1. MyNamespace.MyClass = function()   
  2. {   
  3.         MyNamespace.MyClass.initializeBase(this);   
  4.         this._myProperty = null;   
  5. }   
  6.   
  7. Then, you need to define the class members itself in its prototype:   
  8.   
  9. MyNamespace.MyClass.prototype =    
  10. {   
  11.         get_myProperty:function()   
  12.         {   
  13.                 return this._myProperty;   
  14.         },   
  15.         set_myProperty:function(value)   
  16.         {   
  17.                 this._myProperty = value;   
  18.         },   
  19.         doSomething: function()   
  20.         {   
  21.                 MyNamespace.MyClass.callBaseMethod(this,"doSomething");   
  22.                 /* do something more */  
  23.         }   
  24. }   
  25.   
  26. 最终注册类:   
  27. MyNamespace.MyClass.registerClass("MyNamespace.MyClass", MyNamespace.BaseClass);   
  28.   
  29. 此处不需要管理构造函数和原型层次结构,因为这由registerClass函数自动完成。   
  30.   
  31. Bertrand Le Roy 是 ASP.NET AJAX 团队的软件设计工程师 II。  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多