65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript 中的命名空间

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.72/5 (23投票s)

2007年6月1日

6分钟阅读

viewsIcon

159912

downloadIcon

838

扩展 JavaScript 以处理命名空间、类、静态方法和全局命名空间变量。

引言

我决定写这篇教程是因为我发现了一种创建 JavaScript 命名空间的好方法。在创建命名空间的过程中,我发现了一些扩展 JavaScript 以处理构造类、类对象、静态方法和全局命名空间对象的方法。

JavaScript 实际上能够做到 C# 能做的几乎所有事情,但你必须跳出思维定势才能实现。你可能在想,“你真的能用一个函数方法做到所有这些吗?”… 是的!函数既是方法也是对象。在 JavaScript 中创建对象非常简单。

var obj = new Object();

或使用 JSON 格式

var obj = {} 

对象是我们创建面向对象命名空间所需的一切。下面是创建命名空间的主要代码。它非常小巧且简单,但具有很强的结构化能力。现在你可能会问自己“我为什么要让我的客户端代码变长?”原因是在越来越多的人转向使用 AJAX 的交互式网站,这些网站有大量需要结构化的复杂客户端 JavaScript。

下面是实现命名空间的优缺点列表。

优点

  1. 结构
  2. 面向对象的名称
  3. 易于记忆
  4. 唯一的变量和方法
  5. 自定义品牌
  6. 与未来的 Web 2.0 网站集成

缺点

  1. 代码较长
  2. 加载时间
  3. 过于复杂

虽然优点大于缺点,而且大多数缺点也可以解决。例如,较长的代码可以使用别名来缩短,我将在本教程后面介绍。加载时间也可以通过缩短代码来解决;此外,越来越多的人转向高速宽带,摆脱了拨号连接。另一种方法是使用 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 以供使用,并创建命名空间 SystemSystem.Data,因为它是点表示法层级结构。Register 方法会检查最终的点名称是否已定义。如果已定义,它将抛出错误;如果未定义,它将注册它。Namespace.Create() 方法使用 eval 方法在当前窗口中创建一个具有该点名称的全局对象。

实现

现在让我们看看这段代码如何在“Hello World”示例中发挥作用。在我的示例中,我有 4 个文件。

  1. namespace.js
  2. using.js
  3. helloworld.js
  4. example.html

Namespace.js 包含我们已描述过的源代码,所以让我们继续。Using.js 是我们的声明文件,用于声明我们的命名空间。代码如下所示。

Namespace.Register("System.Classes.HelloWorld"); 

我将它放在一个单独的 js 文件中,因为你通常会有多个定义。我们注册命名空间 System.Classes.HelloWorld,它会注册 SystemSystem.ClassesSystem.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 个变量 MessageMessage2Message3 和 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>

我们在顶部插入脚本以包含 namespaceusinghelloworld。由于执行和创建顺序,这需要保持不变。接下来,我们构造一个非构造类对象并调用它的一个方法。

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 中的面向对象,简直太棒了!我希望您和我一样喜欢创建这个教程。再见……

使用、复制、分发和修改的条款和条件

本代码由版权所有者和贡献者“按原样”提供,不作任何明示或暗示的保证,包括但不限于对适销性和特定用途适用性的暗示保证。在任何情况下,版权所有者或贡献者均不对因使用本代码而引起的任何直接、间接、附带、特殊、示范性或后果性损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)承担任何责任,无论其如何造成,也无论其是基于合同、严格责任或侵权行为(包括疏忽或其他行为)理论,即使已被告知可能发生此类损害。

© . All rights reserved.