js模块化思想里面,为什么要采用这样的方法扩展模块?

fishenal
  • 3.4k

先是在http://www.ruanyifeng.com/blog/2012/10/javascript_module.html 这里看到过,sf上也看到过这个问题:
http://segmentfault.com/q/1010000000457419

这里面都采用了类似这样的代码来扩展一个模块(继承一个模块?)

var Module = (function(duplication) {
    duplication.foo = function() {
       //refactor method foo here    
    }
    return duplication;
} (Module || {}));

既然是对Module本身的扩展,为何不直接写成Module.foo = function(){...},而是用这样复杂的传递返回方法?这样写的好处是什么?

回复
阅读 6.3k
2 个回答
✓ 已被采纳

我认为你贴的方法不是一个良好的实践。可能有一些好处,但这些好处和“JS模块化”这件事情关系不大。

从模块化的角度来看,你贴的代码里暗藏的问题有:

  • 假设可能会有Module这个全局变量是放某个模块的。全局变量是恶魔。
  • 认为模块就是keyvalue的一堆方法。Module凭啥不能是个function(或者说是类)?如果允许Module是个function的话|| {}的写法就是在坑爹。
  • 明明没什么关系的代码却都要叫Module这个名字,就好象一大堆jQuery插件全都闭着眼睛扔在$.fn上,这完全不是模块化
  • 代码中没有依赖关系。看了那行注释,看上去这段代码想要改造Module.foo的行为,结合上面那个问题,名字又覆盖掉了,那如果想要在这段代码里引用原有的Module.foo的话,简直里外不是人了

    • Module.foo压根可能不存在,因为有|| {}
    • 无论在函数体里是调用Module.foo还是duplication.foo,都是死循环(而非很常见的“调用父类同名方法”)

我认为所谓模块化需要解决的问题有

  • 依赖管理 这个才是核心
  • 命名空间 用以支持依赖管理
  • 模块封装规范 这个是最终的表现形式

其实谈到“JS模块化”这个话题,说了那么多还没说到CMD / AMD 两大标准是很不专业的。这里赶紧贴一下这两大标准的参考

  • CMD: CommonJS Module/1.1。 相关支持有NodeJS/SeaJS/RequireJS(兼容)。由于形式上是同步加载模块,所以浏览器端理论上无法做到100%兼容
  • AMD: Asynchronous Module Defination。由RequireJS主导的异步模块定义规范,比起CMD来说更适合浏览器环境(异步加载模块)

估计题主是浏览器环境的JS,不妨去看一下RequireJS。附题中代码可能在RequireJS里的样子

//anotherFoo.js
define(['Module'], function(Module) {
    return function () {
        //xxxx
        Module.foo();
        //yyyy
    };
});
StephenLi
  • 7k

如果是在单个 js 文件内直接扩展功能的话,写成 Module.foo = function(){...} 当然没问题,但是在一些大型项目里,将一个功能模块分离成多个文件非常常见的,如果你用过一些 javascript 的前端框架进行开发,例如 backbone+marionette ,你就会发现基本都是一个 Module 被分割为 view,controller,module等,或者更复杂的结构。
分割的好处,我认为第一有利于代码的构建,反正自从我用了 backbone 后对我开发复杂的前端的 app 帮助很大,后来再加入号称 'make backbone dance'marionette 后就更棒了。
第二的话,也比较利于多人的开发,有时候一个比较复杂的前端功能可能是需要多人开发,这个时候大家各自开发一个 Module 的不同功能模块,总比一起改同一个文件好吧,至少可以减少不必要的 conflict
贴一个项目内的截图:
请输入图片描述请输入图片描述   请输入图片描述

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏