JavaScript模拟命名空间

JavaScript模拟命名空间

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

var MSDNMagNS.Pet = function(name)
{
        // code here;
};

MSDNMagNs.Pet.prototype.toString = function()
{
        // code
};

var pet = new MSDNMagNS.Pet("Yammer");

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

var MSDNMagNS = {};
// nested namespace "Examples"
MSDNMagNS.Examples = {};

MSDNMagNS.Examples.Pet = function(name)
{
        // code
};

MSDNMagNS.Examples.Pet.prototype.toString = function()
{
        // code
};

var pet = new MSDNMagNS.Examples.Pet("Yammer");

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

// MSDNMagNS.Examples and Pet definition...

// think "using Eg = MSDNMagNS.Examples;"

var Eg = MSDNMagNS.Examples;
var pet = new Eg.Pet("Yammer");
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中定义类,您需要将其构造函数赋给变量(注意,构造函数如何调用举出函数):

MyNamespace.MyClass = function()
{
        MyNamespace.MyClass.initializeBase(this);
        this._myProperty = null;
}

Then, you need to define the class members itself in its prototype:

MyNamespace.MyClass.prototype = 
{
        get_myProperty:function()
        {
                return this._myProperty;
        },
        set_myProperty:function(value)
        {
                this._myProperty = value;
        },
        doSomething: function()
        {
                MyNamespace.MyClass.callBaseMethod(this,"doSomething");
                /* do something more */
        }
}

最终注册类:
MyNamespace.MyClass.registerClass("MyNamespace.MyClass", MyNamespace.BaseClass);

此处不需要管理构造函数和原型层次结构,因为这由registerClass函数自动完成。

Bertrand Le Roy 是 ASP.NET AJAX 团队的软件设计工程师 II。 
 

下一节:应当这样编写 JavaScript 代码吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值