Javascript模块模式分析


Posted in Javascript onMay 16, 2008

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

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

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

在匿名函数中,在返回语句前加入“私有”方法和变量。到目前为止,我们只是将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需要它们,我们的两个私有变量就不会被销毁。 

实践这个模式。让我们来看看这个模式的一个常见应用案例。假设你有一个列表,列表上的一些项可以被拖拽。应用拖拽的项上有拖拽的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方法,支持受保护或“私有”的数据和方法。 

[1]原文:《a javascript module pattern》。这是在YUI blog上的,有的地方可能打不开,可以搜一下英文的转载或者利用搜索引擎的缓存也能看。 

[2]《A JavaScript Module Pattern - JavaScript的一种模组模式》这是别人的翻译,参考了不少,不过感觉挺不方便看的,这是我翻译的这篇文章的一个原因,当然最主要的原因是这篇文章算是学习YUI的最基础的文章了,整个YUI的模块模式都基于此。 

Javascript 相关文章推荐
Javascript中拼接大量字符串的方法
Feb 05 Javascript
jQuery选择器源码解读(八):addCombinator函数
Mar 31 Javascript
谈谈JavaScript异步函数发展历程
Sep 29 Javascript
原生js封装的一些jquery方法(详解)
Sep 20 Javascript
Layui table 组件的使用之初始化加载数据、数据刷新表格、传参数
Sep 11 Javascript
Vue渲染函数详解
Sep 15 Javascript
checkbox在vue中的用法小结
Nov 13 Javascript
JS实现的合并两个有序链表算法示例
Feb 25 Javascript
iview tabs 顶部导航栏和模块切换栏的示例代码
Mar 04 Javascript
一看就会的vuex实现登录验证(附案例)
Jan 09 Javascript
js+canvas实现图片格式webp/png/jpeg在线转换
Aug 22 Javascript
介绍一下28个JS常用数组方法
May 06 Javascript
Dom加载让图片加载完再执行的脚本代码
May 15 #Javascript
直接生成打开窗口代码,不必下载
May 14 #Javascript
地震发生中逃生十大法则
May 12 #Javascript
通过修改referer下载文件的方法
May 11 #Javascript
JS启动应用程序的一个简单例子
May 11 #Javascript
一段利用WSH获取登录时间的jscript代码
May 11 #Javascript
一段利用WSH修改和查看IP配置的代码
May 11 #Javascript
You might like
php笔记之常用文件操作
2010/10/12 PHP
php 文件上传类代码
2011/08/06 PHP
深入解析PHP中的(伪)多线程与多进程
2013/07/01 PHP
PHP利用header跳转失效的解决方法
2014/10/24 PHP
Zend Framework教程之模型Model基本规则和使用方法
2016/03/04 PHP
PHP实现会员账号单唯一登录的方法分析
2019/03/07 PHP
Javascript调用C#代码
2011/01/17 Javascript
读jQuery之一(对象的组成)
2011/06/11 Javascript
在js(jquery)中获得文本框焦点和失去焦点的方法
2012/12/04 Javascript
用js实现控件的隐藏及style.visibility的使用
2013/06/14 Javascript
Js实现手机发送验证码时按钮延迟操作
2014/06/20 Javascript
jQuery移除tr无效的解决方法(tr是动态添加)
2014/09/22 Javascript
举例说明如何为JavaScript的方法参数设置默认值
2015/11/17 Javascript
JavaScript中Window对象的属性及事件
2015/12/25 Javascript
原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)
2016/06/21 Javascript
基于JS实现仿百度百家主页的轮播图效果
2017/03/06 Javascript
详解Vue.js搭建路由报错 router.map is not a function
2017/06/27 Javascript
mac上node.js环境的安装测试
2017/07/03 Javascript
说说如何在Vue.js中实现数字输入组件的方法
2019/01/08 Javascript
vue.js实现二级菜单效果
2019/10/19 Javascript
[01:01:13]2018DOTA2亚洲邀请赛 4.5 淘汰赛 Mineski vs VG 第三场
2018/04/06 DOTA
[59:42]Secret vs Alliacne 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
利用Python-iGraph如何绘制贴吧/微博的好友关系图详解
2017/11/02 Python
matplotlib设置legend图例代码示例
2017/12/19 Python
Python使用base64模块进行二进制数据编码详解
2018/01/11 Python
Django中url的反向查询的方法
2018/03/14 Python
python清除字符串前后空格函数的方法
2018/10/21 Python
PyQt5 QListWidget选择多项并返回的实例
2019/06/17 Python
django 捕获异常和日志系统过程详解
2019/07/18 Python
python通过nmap扫描在线设备并尝试AAA登录(实例代码)
2019/12/30 Python
教师求职推荐信范文
2013/11/20 职场文书
会计助理的岗位职责
2013/11/29 职场文书
高级工程师岗位职责
2013/12/15 职场文书
小学爱国卫生月活动总结
2014/06/30 职场文书
python实现过滤敏感词
2021/05/08 Python
MySQL详细讲解变量variables的用法
2022/06/21 MySQL