什么是模块化?为什么要模块化?
命名冲突
:为了方便也避免重复造轮子,我们习惯于把一些通用的、底层的工具抽离出来,例如写成一个函数放在另一个文件中,我们需要的时候再去引用就可以;但是在工具中被定义的变量我不能在当前文件使用,因为会产生冲突导致工具无法正常使用。所以我们希望这个工具能是一个独立的空间,不要影响到当前页面的开发。
文件依赖
:当我们在写一个新工具的时候,有可能会需要调用其它功能更小的工具;那么在执行时因为js的同步特性,要使用这个新工具就必须要先加载小工具,也就是说小工具要先于新工具去引入;当引入文件较多或者顺序乱了之后维护起来非常困难。
原因
:使用模块化主要是为了解决两个问题:命名冲突和文件依赖。
模块化x命名冲突
:用面向对象的方式将方法、工具绑在对象上;约定用关键字exports
暴露接口返回对象。
模块化x文件依赖
:约定关键字require
来获取对象将文件依赖内置,不需要外部引入。
CMD、AMD、CommonJS 规范分别指什么?
Common JS
:它是一个规范,它通过定义丰富的能解决一些通常的应用开发需求的API来补足了js
官方关于标准库的不足。建立它的意图是希望开发者可以运用这些API去开发应用,而且所开发的应用能够在不同的js环境中运行而不仅仅是浏览器。服务器端的javascript
应用node.js
就是运用Common JS
的一个例子,服务器端的程序比浏览器端要更复杂,也需要与操作系统和其他程序互动,因此服务器端必须要模块块以便应对上述问题。node.js
参照Common JS
规范创建了模块系统,模块系统通过exports
暴露接口返回对象,通过require
获取接口返回的对象。例如
// math.js文件 的内容:
exports.method=function(){
var obj=xxx;
// doing something
return obj;
};
// main.js文件 的内容:
var newObj= require('math').method;
// 当然 main.js可以继续exports接口 以供其他文件调用
AMD
:"Asynchronous Module Definition"
即异步模块定义,实现AMD的库有RequireJS
、curl
、Dojo
等。在服务器端采用的Common JS
规范到浏览器端因为同步执行加载的问题会导致浏览器在加载获取时处于假死状态什么都不能做只能等引用加载完,AMD
在这种环境下诞生了;AMD
采用异步加载的方式去获取引用的js
,待加载完成后采取执行对应程序,从而避免了等待和浏览器假死的状况。它的语法和应用如下:
// 语法
define(id?,dependencies?,factory);
// id 即对这个模块命名
// dependencies 这个模块所依赖的其他模块 多个时用数组传递
// factory 加载完成后执行的回调函数
// math.js文件 定义模块
define(function(){
var obj=xxx;
// doing somethig
return obj
})
// main.js文件 加载模块
define(method,['math'],function(math){
//把加载的模块传递进来 doing something
})
CMD
:CMD(Common Module Definition)是Sea JS
推广过程中产生的。在 CMD
规范中,一个模块就是一个文件。其语法与comment js
类似,不过多了一个外包装;且相对与AMD
的提前设置依赖,CMD
的区别就是它将依赖内置了,需要时就使用require
去获取,从表面上看实现了comment js的浏览器端化
,但实质是通过设置外包装 define(function(require, exports, module){}
来包裹代码,提前去加载引用的模块,等加载完成后再同步执行。
// 语法 一个模块就是一个文件
define(factory);
//math.js 定义
define(function(require, exports, module){
exports.obj=xxx;
})
// main.js 加载引用
define(function(require, exports, module){
var method=require('math').obj;
//doing something
})
// 当然这个模块也可以继续exports接口 让其他模块调用