JavaScript 中的命名空间






4.72/5 (23投票s)
2007年6月1日
6分钟阅读

159912

838
扩展 JavaScript 以处理命名空间、类、静态方法和全局命名空间变量。
引言
我决定写这篇教程是因为我发现了一种创建 JavaScript 命名空间的好方法。在创建命名空间的过程中,我发现了一些扩展 JavaScript 以处理构造类、类对象、静态方法和全局命名空间对象的方法。
JavaScript 实际上能够做到 C# 能做的几乎所有事情,但你必须跳出思维定势才能实现。你可能在想,“你真的能用一个函数方法做到所有这些吗?”… 是的!函数既是方法也是对象。在 JavaScript 中创建对象非常简单。
var obj = new Object();
或使用 JSON 格式
var obj = {}
对象是我们创建面向对象命名空间所需的一切。下面是创建命名空间的主要代码。它非常小巧且简单,但具有很强的结构化能力。现在你可能会问自己“我为什么要让我的客户端代码变长?”原因是在越来越多的人转向使用 AJAX 的交互式网站,这些网站有大量需要结构化的复杂客户端 JavaScript。
下面是实现命名空间的优缺点列表。
优点
- 结构
- 面向对象的名称
- 易于记忆
- 唯一的变量和方法
- 自定义品牌
- 与未来的 Web 2.0 网站集成
缺点
- 代码较长
- 加载时间
- 过于复杂
虽然优点大于缺点,而且大多数缺点也可以解决。例如,较长的代码可以使用别名来缩短,我将在本教程后面介绍。加载时间也可以通过缩短代码来解决;此外,越来越多的人转向高速宽带,摆脱了拨号连接。另一种方法是使用 AJAX 按需加载 JavaScript,这将减少初始加载时间。第三个问题“过于复杂!”,嗯,你有没有打开过别人的 JavaScript 代码,并试图从一开始就弄明白?代码执行起来很容易让人迷失方向。所以我想问你,哪种更容易理解?var sObj
是一个对象,还是System.Object
是一个对象。
现在让我们继续学习我的代码以及它将如何帮助你整理代码。下面是创建命名空间的实际命名空间代码。
代码
var Namespace =
{
Register : function(_Name)
{
var chk = false;
var cob = "";
var spc = _Name.split(".");
for(var i = 0; i<spc.length; i++)
{
if(cob!=""){cob+=".";}
cob+=spc[i];
chk = this.Exists(cob);
if(!chk){this.Create(cob);}
}
if(chk){ throw "Namespace: " + _Name + " is already defined."; }
},
Create : function(_Src)
{
eval("window." + _Src + " = new Object();");
},
Exists : function(_Src)
{
eval("var NE = false; try{if(" + _Src + "){NE = true;}else{NE = false;}}catch(err){NE=false;}");
return NE;
}
}
使用 JSON,我预先定义了一个对象变量,其中包含三个方法。
Namespace.Register()
Namespace.Create()
Namespace.Exists()
Namespace.Register
允许你在页面中全局注册命名空间。你传递一个点分隔的名称字符串参数给它,如下所示:
Namespace.Register("System.Data");
这会注册 System.Data
以供使用,并创建命名空间 System
和 System.Data
,因为它是点表示法层级结构。Register
方法会检查最终的点名称是否已定义。如果已定义,它将抛出错误;如果未定义,它将注册它。Namespace.Create()
方法使用 eval
方法在当前窗口中创建一个具有该点名称的全局对象。
实现
现在让我们看看这段代码如何在“Hello World”示例中发挥作用。在我的示例中,我有 4 个文件。
- namespace.js
- using.js
- helloworld.js
- example.html
Namespace.js 包含我们已描述过的源代码,所以让我们继续。Using.js 是我们的声明文件,用于声明我们的命名空间。代码如下所示。
Namespace.Register("System.Classes.HelloWorld");
我将它放在一个单独的 js 文件中,因为你通常会有多个定义。我们注册命名空间 System.Classes.HelloWorld
,它会注册 System
、System.Classes
和 System.Class.HelloWorld
。下一个文件 helloworld.js 包含我们的类、方法和变量。它看起来是这样的。
// Class Example
System.Classes.HelloWorld = function(){ return {
Message : "Hello World!",
Hello : function()
{
alert(this.Message);
}
};}
//PreConstructed class with methods
System.Classes.HelloDevelopers = {
Message : "Hello Developers",
Message2 : "Hello Developers Again",
Message3 : "Wassup!",
Hello : function()
{
alert(this.Message);
}
}
//Static Method
System.Classes.HelloMom = function()
{
var Message = "Hi";
var Message2 = "Mom!";
alert(Message + " " + Message2);
}
//Global Namespace Variable
System.Classes.Hey = "Hey";
第一个类 System.Classes.HelloWorld
包含一个变量 Message
和一个方法 Hello()
。它不是构造的,因为我们将其包装在 function()
中并让它返回 JSON 对象。这是创建非构造类对象的关键。
第二个类 System.Classes.HelloDevelopers
是一个预构造类。它包含 3 个变量 Message
、Message2
、Message3
和 1 个方法 Hello()
。注意函数被移除,也没有返回值。它实际上已准备就绪,无需构造。还有一点要指出的是,我们在这个文件中使用了两个名为 Hello()
的方法而没有发生冲突。因为它们位于不同的命名空间中,所以它们可以共存。
第三个 System.Classes.HelloMom
是一个 static
方法。因为它位于一个没有 JSON 的函数包装器中,所以它已准备就绪,可以随时使用。
第四个 System.Classes.Hey
是一个添加到其中一个命名空间中的字符串变量。它是一种在不发生全局命名冲突的情况下向页面添加 var
的方法。如你所见,通过代码,我们没有向命名空间声明任何 var
。它们被预定义为对象、变量或方法,并且已准备就绪。现在让我们继续使用代码。
我们的下一个文件 example.html 包含类和方法的调用和构造。里面的内容如下:
<html>
<head>
<script type="text/javascript" src="namespace.js"></script>
<script type="text/javascript" src="using.js"></script>
<script type="text/javascript" src="helloworld.js"></script>
</head>
<body>
<script type="text/javascript">
//Construct a class and call a method------------
var HW = new System.Classes.HelloWorld();
HW.Hello();
//-----------------------------------------------
//Use a PreConstructed class and call a method---
System.Classes.HelloDevelopers.Hello();
//or
var HW2 = System.Classes.HelloDevelopers;
HW2.Hello();
//-----------------------------------------------
//Static Method Call from class------------------
System.Classes.HelloMom();
//-----------------------------------------------
//Using variables from class---------------------
alert(System.Classes.HelloDevelopers.Message3);
//-----------------------------------------------
//Using variables from a namespace---------------
alert(System.Classes.Hey);
//-----------------------------------------------
</script>
</body>
</html>
我们在顶部插入脚本以包含 namespace、using 和 helloworld。由于执行和创建顺序,这需要保持不变。接下来,我们构造一个非构造类对象并调用它的一个方法。
var HW = new System.Classes.HelloWorld();
HW.Hello();
正如你所看到的,我们分配了一个 var
并使用 new
来构造它。然后我们调用 hello world,它将弹出一个带有消息的警报。这就引出了别名。注意我们现在有一个 var
HW
,而不是 System.Classes.HelloWorld()
。这比完整的点表示法更小巧、更易于管理,但它包含了所有类方法和变量。
我们使用的第二件事是一个预构造的类。我们可以使用完整的点表示法 System.Classes.HelloDevelopers.Hello()
或别名缩写来使用它。
var HW2 = System.Classes.HelloDevelopers;
HW2.Hello();
这两种方式都会调用该方法。注意我们不使用 new
关键字来构造,因为我们已经预定义了它。
下一段代码是一个 static
方法调用,它也已准备就绪,可以立即使用。只需按名称调用它即可执行该方法,无需构造。
System.Classes.HelloMom()
一旦一个类被预构造或构造,你就可以使用它的属性或方法。这就引出了下一行代码:
alert(System.Classes.HelloDevelopers.Message3);
这会获取 System.Classes.HelloDevelopers
类中的 message3
字符串属性,并在警报中弹出它。
最后但同样重要的是全局命名空间字符串变量 System.Classes.Hey
。
alert(System.Classes.Hey);
这是一种在命名空间范围内使用变量的方法,这样它们就不会与其他全局变量发生冲突。
结论
哇,JavaScript 中的面向对象,简直太棒了!我希望您和我一样喜欢创建这个教程。再见……
使用、复制、分发和修改的条款和条件
本代码由版权所有者和贡献者“按原样”提供,不作任何明示或暗示的保证,包括但不限于对适销性和特定用途适用性的暗示保证。在任何情况下,版权所有者或贡献者均不对因使用本代码而引起的任何直接、间接、附带、特殊、示范性或后果性损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)承担任何责任,无论其如何造成,也无论其是基于合同、严格责任或侵权行为(包括疏忽或其他行为)理论,即使已被告知可能发生此类损害。