一、爲何要模塊化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)