JavaScript模拟命名空间

news/2025/2/23 15:30:32

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 代码吗?


http://www.niftyadmin.cn/n/1040193.html

相关文章

WeHalo 简约风 的微信小程序版博客✨

简介 WeHalo [wiˈheɪloʊ],意为我们的光环,嘻嘻。 配合 Halo 轻快,简洁,功能强大的博客系统而开发出来的 简约风 微信小程序版博客 演示 最后 Github: https://github.com/aquanlerou... Gitee: https://…

应当这样编写 JavaScript 代码吗?

应当这样编写 JavaScript 代码吗? 您已经看到JavaScript可以很好地支持面向对象的编程。尽管它是一种基于原型的语言,但它的灵活性和强大功能可以满足在其它流行语言中常见的基于类的编程风格。但问题是:是否应当这样编写JavaScript代码&am…

canal修改同步位点解析

前言 在canal的数据同步使用过程中,有时会遇到需要修改同步位点的情况,这里对修改位点操作做一下记录。 分析 我们知道在canal-server的instance的配置文件中有一下配置项是与位点修改相关的, canal.instance.master.journal.name canal.…

SQLServer如何清除缓存?

--1. 将当前数据库的全部脏页写入磁盘。“脏页”是已输入缓存区高速缓存且已修改但尚未写入磁盘的数据页。 -- CHECKPOINT 可创建一个检查点,在该点保证全部脏页都已写入磁盘,从而在以后的恢复过程中节省时间。 CHECKPOINT --2. 若要从缓冲池中删除清除…

js删除数组中元素 delete 和splice的区别

例如我有一个数组: var array ["aa","dd","cc","aa"] ,我想删除这个数组的“dd”元素,那么我们应该怎么办呢? 定义一个输出数组元素的方法 //输出数组中的元素var getArray function(array){//循环…

X.509 证书

X.509 Certificates X.509标准定义了什么信息可以被写入证书,并且描述了如何写入(数据的格式)。所有的X.509证书有下面的数据,还有签名: Version 它确定了当前的证书使用的是哪个版本的X.509标准,还确定了证…

canal-adapter适配elasticsearch 2.x和5.x版本

前言 适配elasticsearch不同版本的过程,是一个了解adapter整体架构的过程,但是同样也很想吐槽elasticsearch的版本间的不兼容问题,不过既然要用,就怂怂的接受好了。 适配 注:adapter使用版本为1.1.5-alpha 在1.1.5版…

X.500 Distinguished Names

X.500 Distinguished Names被用来标识一个实体,例如那些用主题和发行者(签名者)来命名的X.509证书领域。keytool支持如下部分: commonName — 一个人的普通名字,例如:“Susan Jones”organicationUnit — …