Javascript的一种模块模式

全局变量是魔鬼。在YUI中,我们仅用两个全局变量:YAHOO和YAHOO_config。YUI的一切都是使用YAHOO对象级的成员或这个成员作用域内的变量。我们建议在你的应用程序也使用类似的规则。

Douglas Crockford已经传授了一个有用的单例模式(singleton pattern)实现此规则,我认为他的模式有益于你基于YUI的那些应用。Douglas叫它模块模式(module pattern)。它是如下工作的:

  1. 创建一个命名空间对象:如果你使用YUI,可以用YAHOO.namespace()方法: YAHOO.namespace("myProject");这分配了一个空的myProject对象,是YAHOO的一个成员(如 果myProject已存在的话,则不会被覆盖)。现在我们可以开始添加YAHOO.myProject的成员。
  2. 对你的命名空间对象分配一个匿名函数返回值:
    YAHOO.myProject.myModule = function () {
    return  {
      myPublicProperty: "我作为YAHOO.myProject.myModule.myPublicProperty被访问。";
      myPublicMethod: function () {
        YAHOO.log("我作为YAHOO.myProject.myModule.myPublicMethod被访问。");
      }
    };
    }(); // 这个括号导致匿名函数被执行且返回
    

    注意有闭合大括号和紧接着的括号()的最后一行—这种符号导致了匿名函数的立即执行,返回包含myPublicProperty和myPublicMethod的对象。只要这个匿名函数一返回,返回对象就作为YAHOO.myProject.myModule被访问。

  3. 在匿名函数中,在返回语句前加入“私有”方法和变量。到目前为止,我们只是将myPublicProperty和myPublicMethod直接分配到YAHOO.myProject.myModule中。此外,当我们在返回语句之前放置一些代码时,这个模式还支持被增加的效用。
    YAHOO.myProject.myModule = function () {
    //“私有”变量:
    var myPrivateVar = “我仅能在YAHOO.myProject.myModule内被访问。”;
    //私有方法:
    var myPrivateMethod = function () {
        YAHOO.log(”我仅能在YAHOO.myProject.myModule内被访问。”);
    }
    
    return  {
        myPublicProperty: “我作为YAHOO.myProject.myModule.myPublicProperty能被访问。”
        myPublicMethod: function () {
        YAHOO.log(”我作为YAHOO.myProject.myModule.myPublicMethod能被访问。”);
        //在myProject,我能访问私有的变量和方法
        YAHOO.log(myPrivateVar);
        YAHOO.log(myPrivateMethod());
        //myPublicMethod的原生作用域是myProject,我们可以用“this”来访问公共成员。
        YAHOO.log(this.myPublicProperty);
        }
    };
    }();

    在上面的代码中,我们从一个匿名函数返回有两个成员的一个对象。在YAHOO.myProject.myModule内部,可以分别用this.myPublicProperty和this.myPublicMethod来访问。在YAHOO.myProject.myModule外部,公共成员可以用YAHOO.myProject.myModule.myPublicProperty和YAHOO.myProject.myModule.myPublicMethod来访问。
    私有变量myPrivateProperty和myPrivateMethod只能被匿名函数本身或返回对象的成员访问。尽管匿名函数会立即执行和终止,但它们依然是保留着,凭借闭包(closure)的力量——通过一个函数的局部变量在这个函数返回后是保留的规则。只要 YAHOO.myProject.myModule需要它们,我们的两个私有变量就不会被销毁。

  4. 实践这个模式。让我们来看看这个模式的一个常见应用案例。假设你有一个列表,列表上的一些项可以被拖拽。应用拖拽的项上有拖拽的CSS类。
    <!--这个脚本文件包含所有的YUI实用程序-->
      <script type="text/javascript"
    src="http://yui.yahooapis.com/2.2.2/build/utilities/utilities.js"></script>
    <ul id="myList">
       <li class="draggable">一项</li>
       <li>二项</li> <!--二项将不能被拖拽-->
       <li class="draggable">三项</li>
       </ul>
    <script>
      YAHOO.namespace("myProject");
      YAHOO.myProject.myModule = function () {
     //YUI实用程序的私有简写引用:
      var yue = YAHOO.util.Event,
      yud = YAHOO.util.Dom;
     //私有方法
      var getListItems = function () {
     // 注意这个地方使用其他的私有变量,包括"yud"YAHOO.util.Dom的简写:
      var elList = yud.get("myList");
      var aListItems = yud.getElementsByClassName(
      "draggable", //得到仅有CSS类"draggable"的项
      "li", //仅返回列表项
      elList //限定搜索改元素的子
      );
      return aListItems;
      };
     //这个放回的对象将变成YAHOO.myProject.myModule:
      return  {
     aDragObjects: [], //可对外访问的,存储DD对象
     init: function () {
      //直到DOM完全加载好,才实现列表项可拖拽:
      yue.onDOMReady(this.makeLIsDraggable, this, true);
      },
     makeLIsDraggable: function () {
      var aListItems = getListItems(); //我们可以拖拽的那些元素
      for (var i=0, j=aListItems.length; i<j; i++) {
      this.aDragObjects.push(new YAHOO.util.DD(aListItems[i]));
      }
      }
     };
      }();
    //上面的代码已经执行,所以我们能立即访问init方法:
      YAHOO.myProject.myModule.init();
      </script>

    这是一个简单的例子,特意写的详细一些——如果按照这种方式做,我们无疑能把它写的更紧凑。当项目变得更加复杂和它的API增加,这个模式缩放的很好。通过这种方式,它避免了全局命名空间,提供了对外的可以访问的API方法,支持受保护或“私有”的数据和方法。

标签:, , ,

作者:秦歌,时间:2007-12-04 0:49,归纳于:Javascript & DOM & AJAX,订阅:RSS 2.0,引用:Trackback

有评论 7 条,发表一条评论 »

海天说:2007-12-04 12:38 #1

呼呼~沙发

老鼠说:2007-12-04 20:15 #2

板凳。
btw,lz的英语素越来越好了哇

海天说:2007-12-05 10:45 #3

lz

柠檬园主说:2007-12-06 14:05 #4

果然YAHOOBLOG訪問不了。。。靠。。。。該S的GFW

怿飞说:2007-12-07 13:00 #5

写得不错,在联盟上看过,不过这篇更详细!

火re说:2007-12-09 16:21 #6

素是什么意思?

Javascript的匿名函数 @ 随网之舞说:2008-05-07 1:15 #7

[...] 《Javascript的一种模块模式》中的第一句话就是“全局变量是魔鬼”。配合var关键字,匿名函数可以有效的保证在页面上写入Javascript,而不会造成全局变量的污染。在这给一个不是很熟悉的页面增加Javascript时非常有效,也很优美。实际上,YUI以及其响应的范例中大量使用匿名函数,其他的Javascript库中也不乏大量使用。 [...]

发表一条评论

您可以在下面评论内容中使用下列XHTML标签:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

您或许也喜欢看:

  1. 第二届D2见闻和随想
  2. 扩展YUI Loader
  3. Javascript的匿名函数
  4. Firefox的默认样式表
  5. Javascript风格要素(2)
  6. Javascript风格要素(1)
  7. 从中国雅虎的改版看如何向Yahoo!主页学习
  8. 向Yahoo Mail的主页学习
  9. dwnTree:可记忆的无限级树型菜单 1.1
  10. 检测大写锁定键(Caps Lock)是否被激活
回到页眉