论坛首页 Web前端技术论坛

【原创翻译】A JavaScript Module Pattern - JavaScript的一种模组模式

浏览 9607 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-24  

A JavaScript Module Pattern - JavaScript的一种组件模式
原文出处:http://yuiblog.com/blog/2007/06/12/module-pattern/
翻译:Frank
全局变量是一种祸害。在YUI中,我们只使用两个全局变量YAHOO和YAHOO_config。所有YUI的对象都从YAHOO这个对象层次上访问成员或属于这个成员的变量。我们建议你在您的程序中亦效仿此实践。
Douglas Crockford已经对我们传授了使用单例的模式(singletion pattern)来实现此模式,而且我认为应用到该模式来构建基于YUI,不乏一些有意思的地方。Douglas称这个为“”,看看他怎么做的?

1、创建命名空间对象:如果你使用的YUI,你可以采用的YAHOO.namespace()的方法:

js 代码
 
  1. YAHOO.namespace("myProject");


这分配了一个空的myProject对象,是YAHOO的一个成员(但不会覆盖myProject如果已存在的话)。现在我们可以开始加入YAHOO.myProject成员。

2、从一个匿名函数返回值,分配到命名空间对象上

js 代码
 
  1. YAHOO.myProject.myModule = function () {
  2. return {
  3. myPublicProperty: "I'm accessible as YAHOO.myProject.myModule.myPublicProperty.";
  4. myPublicMethod: function () {
  5. YAHOO.log("I'm accessible as YAHOO.myProject.myModule.myPublicMethod.");
  6. }
  7. };
  8. }(); //这里括号的作用的是 执行该匿名函数并返回


注意花括号结尾的最底行,后面紧跟着一对括号() --这符号的含意是立即执行该匿名函数,返回一个包含myPublicProperty和myPublicMethod的对象。只要匿名函数能够返回,返 回的那个对象便可 以YAHOO.myProject.myModule访问。
3、在匿名函数中优先加入”私有“的方法和变量(在return之前)。
到现在,我们做的只是将myPubilcProperty和myPublicMethod直接分配到YAHOO.myProject.myModule。除此之外,该模式还允许我们在return语之前执行一些代码:

 


私有变量如myPrivateProperty和myPrivateMethod的,只能被匿名函数本身,或是返回对象的成员访问。尽管匿名函数会立即执行和终结,但它们依然是保留着,凭借闭包(closure)的力量,只要 YAHOO.myProject.myModule需要它们,我们的两个所以变量就不会被销毁。

4、实践该模式我们来看看module pattern的实际应用。假设你有一段列表,列表的上的某些item是可被拖动的。拖动的item有一个draggable的CSS Class。

 
  1. <!--This script file includes all of the YUI utilities:-->
  2. <script type="text/javascript" src="http://yui.yahooapis.com/2.2.2/build/utilities/utilities.js"><!--</span-->script>
  3. <ul id="myList">
  4. <li class="draggable">Item one.<!--</span-->li>
  5. <li>Item two.<!--</span-->li> <!--item two won't be draggable-->
  6. <li class="draggable">Item three.<!--</span-->li>
  7. <!--</span-->ul>
  8. <script>
  9. YAHOO.namespace("myProject");
  10. YAHOO.myProject.myModule = function () {
  11. //引用YUI utilities的简写:
  12. var yue = YAHOO.util.Event,
  13. yud = YAHOO.util.Dom;
  14. //私有方法
  15. var getListItems = function () {
  16. //注意我们使用其它的私有变量,包括 "yud"的简写
  17. var elList = yud.get("myList");
  18. var aListItems = yud.getElementsByClassName(
  19. "draggable", //获取只带有”draggable“CSS类的item
  20. "li", //只返回列表item
  21. elList //限制搜索该元素的children
  22. );
  23. return aListItems;
  24. };
  25. //返回的对象变为YAHOO.myProject.myModule:
  26. return {
  27. aDragObjects: [], //保存 DD objects,可对外访问
  28. init: function () {
  29. //等到DOM完全加载好,才开始创建列表item:
  30. yue.onDOMReady(this.makeLIsDraggable, this, true);
  31. },
  32. makeLIsDraggable: function () {
  33. var aListItems = getListItems(); //这些元素我们让它可拖动
  34. for (var i=0, j=aListItems.length; i<j; i++) {
  35. this.aDragObjects.push(new YAHOO.util.DD(aListItems[i]));
  36. }
  37. }
  38. };
  39. }(); //这里括号的作用的是 执行该匿名函数并返回
  40. //上面的代码执行完毕,所以我们即可访问init
  41. YAHOO.myProject.myModule.init();
  42. <!--</span-->script>
xml 代码

这个一个简单的例子,特意写得繁琐一些。如果我们按这种方式做,我们有相信能够写出更紧凑的代码。不过,该模式的伸缩 会随着项目的复杂度同步增长,API也变得越来越大。使用该方法,避免的了全局的命名空间,而又能对API的方法公共的访问,支持保护(protected)或”私有“的数据。

 

js 代码
 
  1. YAHOO.myProject.myModule = function () {
  2. //“私有变量”:
  3. var myPrivateVar = "I can be accessed only from within YAHOO.myProject.myModule.";
  4. //“私有方法”:
  5. var myPrivateMethod = function () {
  6. YAHOO.log("I can be accessed only from within YAHOO.myProject.myModule");
  7. }
  8. return {
  9. myPublicProperty: "I'm accessible as YAHOO.myProject.myModule.myPublicProperty."
  10. myPublicMethod: function () {
  11. YAHOO.log("I'm accessible as YAHOO.myProject.myModule.myPublicMethod.");
  12. //Within myProject, I can access "private" vars and methods:
  13. YAHOO.log(myPrivateVar);
  14. YAHOO.log(myPrivateMethod());
  15. //The native scope of myPublicMethod is myProject; we can
  16. //access public members using "this":
  17. YAHOO.log(this.myPublicProperty);
  18. }
  19. };
  20. }(); //这里括号的作用的是 执行该匿名函数并返回

上面的代码中,我们从一匿名函数返回一个包含两个成员的对象。在YAHOO.myProject.myModule内可分别用 this.myPublicProperty和this.myPublivMethod来访问。在YAHOO.myProject.myModule外 部,这些公告成员可用YAHOO.myProject.myModule.myPublicProperty 和 YAHOO.myProject.myModule.myPublicMethod访问。
   发表时间:2007-06-24  
另一版本在 http://jstang.5d6d.com/thread-315-1-1.html
Module Pattern翻译成为组件模式不太贴切,只是一时又找不到更好的翻译
0 请登录后投票
   发表时间:2007-06-24  
在我有JSI的想法之前,这种方式我确实挺喜欢的,后来就不这么认为了。

一长串的路径还是挺烦人的。而且想重构一下包名,那就更是麻烦。
0 请登录后投票
   发表时间:2007-06-24  
这种写法优点其实是明显的。
避免全局变量,我实在找不出其它更好的办法(这也算是闭包的一种变相写法吧?)
不过,如果能有JSI的协助,当然是另一个精彩的故事:)
0 请登录后投票
   发表时间:2007-06-24  
sp42 写道
这种写法优点其实是明显的。
避免全局变量,我实在找不出其它更好的办法(这也算是闭包的一种变相写法吧?)
不过,如果能有JSI的协助,当然是另一个精彩的故事:)


恩,确实,这是避免过多的全局变量最简单的办法:)

这个翻译成模块模式是不是好点呢?
0 请登录后投票
   发表时间:2007-06-25  
应该翻译成模块模式,或者意译为命名空间模式。


当然这里所演示的方式,没有什么好处——除了简单之外。jsi和pies是王道。:)
0 请登录后投票
   发表时间:2007-06-25  
hax 写道
应该翻译成模块模式,或者意译为命名空间模式。


当然这里所演示的方式,没有什么好处——除了简单之外。jsi和pies是王道。:)


"模块模式" 是我第一时间想到称谓,但是出现了两个“模”字,不太顺,总觉得不是太“优美”吧?
0 请登录后投票
   发表时间:2007-06-25  
虽然不太优美,但是比不太准确要好。


组件多是指component。module虽然在别的场合也有翻译成“组件”的,但是在指程序代码组织单位时,基本上都用“模块”。台湾似翻译成“模组”。

0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics