Javascript模块化编程(一):模块的写法

 

作者: 阮一峰

日期: 2012年10月26日

随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂。

网页越来越像桌面程序,需要一个团队分工协作、进度管理、单元测试等等......开发者不得不使用软件工程的方法,管理网页的业务逻辑。

Javascript模块化编程,已经成为一个迫切的需求。理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块。

但是,Javascript不是一种模块化编程语言,它不支持""(class),更遑论"模块"(module)了。(正在制定中的ECMAScript标准第六版,将正式支持"类"和"模块",但还需要很长时间才能投入实用。)

Javascript社区做了很多努力,在现有的运行环境中,实现"模块"的效果。本文总结了当前"Javascript模块化编程"的最佳实践,说明如何投入实用。虽然这不是初级教程,但是只要稍稍了解Javascript的基本语法,就能看懂。

一、原始写法

模块就是实现特定功能的一组方法。

只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块。

  function m1(){
    //...
  }

  function m2(){
    //...
  }

上面的函数m1()和m2(),组成一个模块。使用的时候,直接调用就行了。

这种做法的缺点很明显:"污染"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。

二、对象写法

为了解决上面的缺点,可以把模块写成一个对象,所有的模块成员都放到这个对象里面。

  var module1 = new Object({

    _count : 0,

    m1 : function (){
      //...
    },

    m2 : function (){
      //...
    }

  });

上面的函数m1()和m2(),都封装在module1对象里。使用的时候,就是调用这个对象的属性。

  module1.m1();

但是,这样的写法会暴露所有模块成员,内部状态可以被外部改写。比如,外部代码可以直接改变内部计数器的值。

  module1._count = 5;

三、立即执行函数写法

使用"立即执行函数"(Immediately-Invoked Function Expression,IIFE),可以达到不暴露私有成员的目的。

  var module1 = (function(){

    var _count = 0;

    var m1 = function(){
      //...
    };

    var m2 = function(){
      //...
    };

    return {
      m1 : m1,
      m2 : m2
    };

  })();

使用上面的写法,外部代码无法读取内部的_count变量。

  console.info(module1._count); //undefined

module1就是Javascript模块的基本写法。下面,再对这种写法进行加工。

四、放大模式

如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式"(augmentation)。

  var module1 = (function (mod){

    mod.m3 = function () {
      //...
    };

    return mod;

  })(module1);

上面的代码为module1模块添加了一个新方法m3(),然后返回新的module1模块。

五、宽放大模式(Loose augmentation)

在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上一节的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用"宽放大模式"。

  var module1 = ( function (mod){

    //...

    return mod;

  })(window.module1 || {});

与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象。

六、输入全局变量

独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。

为了在模块内部调用全局变量,必须显式地将其他变量输入模块。

  var module1 = (function ($, YAHOO) {

    //...

  })(jQuery, YAHOO);

上面的module1模块需要使用jQuery库和YUI库,就把这两个库(其实是两个模块)当作参数输入module1。这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显。这方面更多的讨论,参见Ben Cherry的著名文章《JavaScript Module Pattern: In-Depth》

js 模块化编程的更多相关文章

  1. 从273二手车的M站点初探js模块化编程

    前言 这几天在看273M站点时被他们的页面交互方式所吸引,他们的首页是采用三次加载+分页的方式.也就说分为大分页和小分页两种交互.大分页就是通过分页按钮来操作,小分页是通过下拉(向下滑动)时异步加载数 ...

  2. require.js实现js模块化编程(一)

    1.认识require.js: 官方文档:http://requirejs.org/RequireJS是一个非常小巧的JavaScript模块载入框架,是AMD规范最好的实现者之一.最新版本的Requ ...

  3. require.js实现js模块化编程(二):RequireJS Optimizer

    require.js实现js模块化编程(二):RequireJS Optimizer 这一节,我们主要学习一下require.js所提供的一个优化工具r.js的用法. 1.认识RequireJS Op ...

  4. 初步理解require.js模块化编程

    初步理解require.js模块化编程 一.Javascript模块化编程 目前,通行的Javascript模块规范共有两种:CommonJS和AMD. 1.commonjs 2009年,美国程序员R ...

  5. [转]js模块化编程之彻底弄懂CommonJS和AMD/CMD!

    原文: https://www.cnblogs.com/chenguangliang/p/5856701.html ------------------------------------------ ...

  6. js模块化编程总结

    大家都知道,js中的变量(variable)有其作用范围,比如:函数里用var定义的变量在函数外是看不到的,而定义在函数外面的变量(不能有没有var修饰)均是全局变量,在js程序的任何位置都可以访问. ...

  7. js模块化编程之彻底弄懂CommonJS和AMD/CMD!

    先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块.但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写 ...

  8. 好文推荐系列-------(5)js模块化编程

    本文主要来源于阮一峰的<Javascript模块化编程>系列文章整合,原文地址:http://www.ruanyifeng.com/blog/2012/10/javascript_modu ...

  9. JS模块化编程(一):CommonJS,AMD/CMD

    前言 模块化是什么? 为什么采用模块化? 场景: 一个html,因不同的业务需求开发,会不断的引入js文件.另外,a.js和b.js中的变量或函数必须是全局的,才能暴露给使用方. <script ...

  10. JS模块化编程(二)

    背景 我们常在页面引用js遇到下面情况 <script src="1.js"></script> <script src="2.js&quo ...

随机推荐

  1. 优化DP的奇淫技巧

    DP是搞OI不可不学的算法.一些丧心病狂的出题人不满足于裸的DP,一定要加上优化才能A掉. 故下面记录一些优化DP的奇淫技巧. OJ 1326 裸的状态方程很好推. f[i]=max(f[j]+sum ...

  2. Altium Designer 15 --- Design PCB Frame by Rhinoceros

    step 1: Draw a PCB shape and the main component placed in the PCB. The drawing sheet should be in th ...

  3. sql总结一

    建表: select * from fruit; create table fruit ( id varchar(10) not null, name varchar(20) default '' n ...

  4. MVC JsonResult的用法

    本文导读:当客户端调用某个Action方法并希望以JSON的格式返回请求的数据时,ASP.NET MVC需要有一种机制将CLR对象转换成JSON格式予以响应,而这可以通过JsonResult来解决.下 ...

  5. 深入JVM-垃圾收集器常用的GC参数

    1.与串行回收器相关的参数 -XX:+UseSerialGC:在新生代和老年代使用串行收集器 -XX:SurvivorRatio:设置eden区大小和survivor区大小的比例 -XX:Preten ...

  6. Jquery 基本知识(二)

    一.数据类型 5种基本数据类型:Null/Undefined/String/Boolean/Number 1种复杂数据类型:Object 二.数据类型检测 1.typeof 2.instanceof/ ...

  7. JQuery------Select标签的各种使用方法

    optioin属性(value) <option value='>Hello</option> option的点击事件 <select class="s-one ...

  8. ioctlsocket()

    ioctlsocket()是控制套接口的模式. 外文名 ioctlsocket() 含    义 控制套接口的模式 头文件 #include <winsock.h> 性    质 函数 目 ...

  9. JavaScript排序算法——快速排序

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. Apache配置--用户认证(针对目录访问)-update2015-05-02

    通过Apache配置可以限制用户对目录的访问,会弹出像phpadmin一样的登陆框. ========================================================= ...