1.模块的写法javascript
a、原始写法:html
function m1() {..........} function m2() {..........}
这两个函数组成一个模块,使用时直接调用,可是这样明显污染全局环境,没法保证不与其余的模块发生变量名冲突,而且这样也看不出来各个模块之间的依赖关系。java
b、后来写成对象:jquery
var module1 = new Object({ _count : 0, m1 : function (){ //... }, m2 : function (){ //... } });
这样就写module.m1(); 可是这样暴露了全部模块成员,内部代码能够被外部改写。好比外部代码能够直接改变内部计数的值 :module1._count =5;数组
c、使用当即执行函数能够达到不暴露私有成员变量的目的。浏览器
var module1 = (function(){ var _count = 0; var m1 = function(){ //... }; var m2 = function(){ //... }; return { m1 : m1, m2 : m2 }; })();
d、后来又有了宽放大的模式服务器
var module1 = ( function (mod){ //... return mod; })(window.module1 || {});
2.出现模块化规范,目前有 :CommonJS模块、AMD模块还有CMD模块 几种规范。异步
a、CommonJS规范同步加载模块,这对服务器端不是一个问题,由于全部的模块都存放在本地硬盘,能够同步加载完成,等待时间就是硬盘的读取时间。可是,对于浏览器,这倒是一个大问题,由于模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态。所以,浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"(asynchronous)。这就是AMD规范诞生的背景。
async
var math = require('math'); math.add(2, 3)
b、主要讲AMD异步加载模块加载采用异步方式加载模块,模块的加载不影响它后面语句的运行。全部依赖这个模块的语句,都定义在一个回调函数中,等到加载完成以后,这个回调函数才会运行。
AMD也采用require加载模块 require([module], callback);第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功以后的回调函数
模块化
require(['math'], function (math) { math.add(2, 3); });
math.add()与math模块加载不是同步的,浏览器不会发生假死。因此很显然,AMD比较适合浏览器环境。require.js这个JavaScript的库实现了AMD规范
3.require.js用法
a、开始引用js文件
<script src="1.js"></script> <script src="2.js"></script> <script src="3.js"></script> <script src="4.js"></script>
这样的方式加载有两个缺点:加载的时候,浏览器会中止网页渲染,加载文件越多,网页失去响应的时间就会越长(解决方法在下边);其次,因为js文件之间存在依赖关系,所以必须严格保证加载顺序
b、require.js解决了这个问题 <script src="js/require.js" defer async="true" ></script>
async属性代表这个文件须要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,因此把defer也写上。加载require.js之后就须要 加载咱们本身的代码了,写一个main.js 这就至关于c语言的main()入口;
<script src="js/require.js" data-main="js/main"></script> data-main属性的做用是,指定网页程序的主模块
main.js ---------> require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){ // some code here });
require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是['moduleA', 'moduleB', 'moduleC'],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可使用这些模块。
require()异步加载moduleA,moduleB和moduleC,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。
c、自定义模块的加载行为 :使用require.config()方法进行定义;写在main.js的头部。
require.config({ paths: { // 或者写上baseUrl: "js/lib",下边就不用写lib "jquery": "lib/jquery.min", "underscore": "lib/underscore.min", "backbone": "lib/backbone.min" } });
若是加载多个模块,就会发出屡次HTTP请求,会影响网页的加载速度。所以,require.js提供了一个优化工具,当模块部署完毕之后,能够用这个工具将多个模块合并在一个文件中,减小HTTP请求数。
4.加载方式完了,而后就是本身写的模块 应该用AMD规范进行,写模块必须采用特定的define()函数来定义;
---------------->// math.js模块 define(function (){ var add = function (x,y){ return x+y; }; return { add: add }; });
b、若是这个模块依赖其余的模块怎么办?
---------------->// math.js模块 define(['myLib'], function(myLib){ function foo(){ myLib.doSomething(); } return { foo : foo }; });
5.不少的库的模块并不符合AMD规范那么怎么进行加载呢?那加载他们以前必需要先定义他们的特征,好比加载underscore和backbone
require.config({ shim: { 'underscore':{ exports: '_' }, 'backbone': { deps: ['underscore', 'jquery'], exports: 'Backbone' } } });
require.config()接受一个配置对象,这个对象除了有前面说过的paths属性以外,还有一个shim属性,专门用来配置不兼容的模块。具体来讲,每一个模块要定义(1)exports值(输出的变量名),代表这个模块外部调用时的名称;(2)deps数组,代表该模块的依赖性。
参照文档:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html(阮一峰) 本身理解