今天的內容涉及Node的原理、運行機制和CommonJS的內容,會有點沉悶,也會有點困難,建議像我同樣作一些筆記。
在開發大型應用的時候,咱們經常會用到全局變量,例如:var s="Hello"
。可是,當咱們的應用愈來愈大時,咱們可能會不當心重複用了幾個相同的變量或者函數名,這就會給咱們的應用形成麻煩。爲了解決這個困難,因而提出了模塊的概念。模塊是一種代碼的組織形式,就是把實現不一樣功能的JS代碼分開來寫,把相同名字的函數或變量存在不一樣的模塊中,這樣就能夠避免相同名的函數或變量發生衝突了。編程
同時,模塊還能夠提升代碼的可維護性。由於你只要關心寫好當前的模塊,而沒必要擔憂會污染或影響到別的模塊,模塊之間都是隔離的。數組
在上一節的例子中,咱們編寫了一個hello.js的代碼。在這裏,咱們把它修改一下:閉包
'use strict'; var s="Hello"; function greet(name){ console.log(s + "," + name + "!"); } module.exports=greet;
這裏,咱們用module.exports
向外輸出了一個變量。這個變量就是這個模塊與外界的一個出口。這個變量能夠是函數、對象、數組。編程語言
既然有輸出,就要有接口。咱們再建立一個main.js:函數式編程
'use strict'; //引入hello模塊: var heat=require('./hello'); var s='Michael'; heat(s); //Hello,Michael!
這裏,咱們用require函數引入了hello模塊。main.js中,變量heat就是在hello.js中暴露的greet函數。接下來heat(s)
`就是直接使用它了。函數
這種模塊加載的方式被稱爲Commonjs規範,除了這種規範以外,還有ES六、AMD、CMD,這裏不細談,我也還沒學到,這裏只談談Commonjs和之前學的閉包知識。網站
在上文中,咱們提到了全局變量的衝突。正如咱們在上面的例子中,兩個js文件都聲明瞭變量s,可是並無發生衝突,仍然是按照咱們的意願來執行的,這就是Node實行了模塊的隔離。ui
Node可以實現模塊和變量的隔離,是由於閉包。
JS是一種函數式編程語言,它支持閉包,若是咱們用函數把某個變量包起來,這個變量就變成了函數內部的局部變量了。而咱們知道,閉包中只要這個函數的生命週期沒有結束,這個變量也就能夠一直存在,而不會受到其餘函數外的其餘變量的影響。code
咱們以上面的例子來解釋,在hello模塊中,s="hello"
被保存了起來,只對外開了一個口:module.exports=greet
,在函數greet中,包含有變量s,因此」s=hello」
能一直被保存起來,直到greet在main模塊中被引用。對象
這裏有一個問題,咱們說須要一個函數才能造成閉包,可是咱們的代碼並無這個函數呀?這就是Node作的工做了,Node幫咱們在內部包裝了hello模塊:
(function(){ var s="Hello"; function greet(name){ console.log(s + "," + name + "!"); } })()
所以,s就變成了匿名函數的內部局部變量,後來加載的其餘模塊中即便也有s變量,也不會影響到這個s變量。
在Node中有一個module對象,讓咱們來看看模塊的輸出過程:
var module={ id:'hello', exports:{} }; var load=function(module){ //讀取的hello.js代碼 function greet(name){ console.log( "Hello," + name + "!"); } module.exports=greet; //hello.js代碼結束 return module.exports; }; var exported=load(module); //保存module save(module,exported);
在咱們的hello模塊中,咱們經過module.exports=greet
把一個變量傳給了Node,而module其實是Node準備階段的一個變量,並且也是做爲load函數的一個參數被保存了下來。每當咱們使用module.exports
時,Node就把一條module按模塊分類存了起來,這些module都被保存在了一塊兒。
當咱們在main模塊中想要用到hello模塊時,咱們又使用require()
來讓Node幫咱們在找到id爲hello的module傳遞給咱們。這樣,咱們就拿到了hello的模塊輸出。
Node的運行參考了 模塊—廖雪峯的官方網站,實在看的我也有點繞,不過Node處理模塊的運行原理咱們如今看個大概暫時就夠了,等學完主體內容再來細細分析。
咱們能夠經過兩種方式輸出模塊:
module.exports={ hello:hello, greet:greet }
exports.hello=hello; exports.greet=greet;
可是你不能直接對exports賦值:
exports={ hello:hello, greet:greet }
實踐證實,使用
module.exports=xxx
的方式賦值更好。具體緣由一樣涉及到Node的內部處理。有興趣的同窗能夠參考上面的那篇文章。