一、为何要模块化javascript
嵌入网页的javascript代码愈来愈庞大,愈来愈复杂,须要一个团队分工协做、进度管理、单元测试等,模块化编程,已经成为一个迫切的需求。此外:模块化编程解决的问题有:命名冲突问题,文件依赖问题等等。html
一言以蔽之:模块化就是分解代码。java
二、什么是模块node
模块就是实现特定功能的一组方法。只要把不一样的函数(以及记录状态的变量)简单地放在一块儿,就算是一个模块。有了模块,咱们能够更方便地使用别人的代码,想要什么功能,就加载什么模块。接着出现了模块规范:就是你们必须以一样的方式编写模块,目前,通行的Javascript模块规范主要有两种:CommonJS和AMD。jquery
三、模块之间的关系如何解决
web
define(['myLib'], function(myLib){ function foo(){ myLib.doSomething(); } return { foo : foo }; });
3.2:CMD规范中:npm
// 全部模块都经过 define 来定义 define(function(require, exports, module) { // 经过 require 引入依赖 var $ = require('jquery'); var Spinning = require('./spinning'); // 经过 exports 对外提供接口 exports.doSomething = ... // 或者经过 module.exports 提供整个接口 module.exports = ... });
四、AMD和common js有什么区别 编程
AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。全部依赖这个模块的语句,都定义在一个回调函数中,等到加载完成以后,这个回调函数才会运行。json
AMD也采用require()语句加载模块,可是不一样于CommonJS,它要求两个参数:数组
require([module], callback);
第一个参数[module],是一个数组,里面的成员是要加载的模块;
第二个参数callback,是加载成功以后的回调函数。若是将前面的代码改写成AMD形式,就是下面这样:
require(['math'], function (math) { math.add(2, 3); });
CommonJS是服务器端模块的规范,Node.js采用了这个规范。
根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象。下面就是一个简单的模块文件example.js。
console.log("evaluating example.js"); var invisible = function () { console.log("invisible"); } exports.message = "hi"; exports.say = function () { console.log(message); }
使用require方法,加载example.js。
var example = require('./example.js');
这时,变量example就对应模块中的exports对象,因而就能够经过这个变量,使用模块提供的各个方法。
{ message: "hi", say: [Function] }
require方法默认读取js文件,因此能够省略js后缀名。
var example = require('./example');
js文件名前面须要加上路径,能够是相对路径(相对于使用require方法的文件),也能够是绝对路径。若是省略路径,node.js会认为,你要加载一个核心模块,或者已经安装在本地 node_modules 目录中的模块。若是加载的是一个目录,node.js会首先寻找该目录中的 package.json 文件,加载该文件 main 属性提到的模块,不然就寻找该目录下的 index.js 文件。
下面的例子是使用一行语句,定义一个最简单的模块。
// addition.js exports.do = function(a, b){ return a + b };
上面的语句定义了一个加法模块,作法就是在exports对象上定义一个do方法,那就是供外部调用的方法。使用的时候,只要用require函数调用便可。
var add = require('./addition'); add.do(1,2) // 3
再看一个复杂一点的例子。
// foobar.js function foobar(){ this.foo = function(){ console.log('Hello foo'); } this.bar = function(){ console.log('Hello bar'); } } exports.foobar = foobar;
调用该模块的方法以下:
var foobar = require('./foobar').foobar, test = new foobar(); test.bar(); // 'Hello bar'
有时,不须要exports返回一个对象,只须要它返回一个函数。这时,就要写成module.exports。
module.exports = function () { console.log("hello world") }
总结:
1.common js是同步加载的 ,amd是异步的
2.根本不一样:common js用于服务器端同步加载模块;amd是客户端异步加载模块。cmd =浏览器端实现的蹩脚的common js (为何这样:由于http是异步的, 在浏览器端使用common js不现实,cmd=amd的思想+common js的写法 )
3.相同点:二者都有一个全局函数require(),用于加载模块;只是AMD规范中的require函数须要有2个参数。
五、包,以及npm包结构规范
5.1:概念:包就是能完成独立功能的一个特殊模块 ,例如connect,http,compression,cookie-session,body-parser
都是包,包与模块相比有多个区别:
一、包是由模块组成的
二、一般状况下由第三方提供的叫包,而本身书写的叫模块
三、一般引用包用模块的名字,而引用模块用文件路径
四、模块可能不能单独使用,而包是能够单独使用的
官网解释:package
This specification describes the CommonJS package format for distributing CommonJS programs and libraries. A CommonJS package is a cohesive wrapping of a collection of modules, code and other assets into a single form. It provides the basis for convenient delivery, installation and management of CommonJS components.
This specifies the CommonJS package descriptor file and package file format. It does not specify a package catalogue file or format; this is an exercise for future specifications. The package descriptor file is a statement of known fact at the time the package is published and may not be modified without publishing a new release.
5.2:包结构规范
CommonJS包规范是理论,NPM是其中的一种实践。NPM之于Node,至关于gem之于Ruby,pear之于PHP。对于Node而言,NPM帮助完成了第三方模块的发布、安装和依赖等。借助NPM,Node与第三方模块之间造成了很好的一个生态系统。 借助NPM,能够帮助用户快速安装和管理依赖包。
一个符合CommonJS规范的包应该是以下这种结构:
"contributors": [{ "name": "Jackson Tian", "email": "mail @gmail.com" }, { "name": "fengmk2", "email": "mail2@gmail.com" }],
"licenses": [{ "type": "GPLv2", "url": "http://www.example.com/licenses/gpl.html", }]
六、node.js的模块引用机制
6.1:简单模块定义和使用
在Node.js中,定义一个模块十分方便。咱们以计算圆形的面积和周长两个方法为例,来表现Node.js中模块的定义方式。
var PI = Math.PI; exports.area = function (r) { return PI * r * r; }; exports.circumference = function (r) { return 2 * PI * r; };
将这个文件存为circle.js,并新建一个app.js文件,并写入如下代码:
var circle = require('./circle.js'); console.log( 'The area of a circle of radius 4 is ' + circle.area(4));
能够看到模块调用也十分方便,只须要require须要调用的文件便可。
var http = require('http')
var myMod = require('/home/base/my_mod')
var myMod = require('./my_mod')
varmyMod = require('./my_mod')
varmyMod = require('./my_mod.js')
var myMod = require('./folder')
{ "name": "pack", "main": "modA.js" }
console.log('模块modA开始加载...') exports = function() { console.log('Hi') } console.log('模块modA加载完毕')
varmod1 = require('./modA') varmod2 = require('./modA') console.log(mod1 === mod2)