CommonJS規範的提出主要是彌補JavaScript沒有標準的缺陷,以達到開發大型應用的基礎能力。
昨天說到了nodejs,簡單的談了談nodejs是個啥,今天就來看一看node中的模組化機制,從js這門語言誕生以來,一直給人的感覺就是簡單也就是做做特效、表單驗證啥的。其實我在學校也經常聽到這樣的言論,為此還和室友幹了一架(題外話,這就不談了)。現在的js已經不是侷限在當初的那個時代了,現在js負責的也越來越多,我們急切的需要一種規範,來讓js大展拳腳。
一、CommonJS出現解決了什麼問題
樸靈老師在書中也是提到了幾點js規範上的缺陷。
1.沒有模組系統
不知道大家以前接觸過Java或者Python沒有,我們可以在檔案與檔案之間,十分方便的去引用匯出我們需要的東西。然後很悽慘的回過頭看看我們的js,以前是沒有模組這個概念的,以前js只是做表單驗證啥的沒覺得什麼,當我們的專案越來越大,專案越來越難以維護,這時候我們就急需要一種模組機制。
2.標準庫很少
ECMAScript(有沒有人不知道這是啥,我覺得應該大家都知道)定義的核心庫是非常少的,沒有像java那樣對檔案系統、網路、I/O流的標準庫,這些在我們開發大型應用時是很常見的需求,但是js中是沒有的。
3.沒有標準介面
我們在js中沒有見到過如資料庫、web伺服器等等的標準統一介面,這也是十分的不方便的。
4.缺乏包管理系統
好吧,其實我以前就一直想吐槽這一點,我以前有問題去問同學的時候,他們統一的回答是,你去導個包啊,這時候我就很想去懟他一句。沒有包管理的系統,我們就不能去很方便的自動載入,安裝依賴,去使用別人寫好的包檔案。
CommonJS為js開發指明瞭一條大道,規範裡面涵蓋了模組、二進位制、I/O流、包管理、程式環境等等。Node借鑑CommonJS的Modules規範實現了一套很容易的模組系統,而另一個偉大的創造NPM對包管理規範的實現也使得我們在開發的時候事半功倍。
二、CommonJS的模組規範
1. 模組定義
在模組中,提供了exports物件用來匯出當前模組的變數或者是方法。同時在模組中還存在一個module物件,它代表的是當前模組自身,exports呢是module的一個屬性,在Node中一個檔案就是一個模組,都有自己的作用域,關於exports和module.exports的關係與區別下面再談。
// a.js
exports.a = 1;複製程式碼
2. 模組標識
模組標識就是傳給require方法的引數,必須是符合小駝峰命名的字串,或者絕對相對路徑。
3. 模組引入
模組的匯入也非常簡單,在模組中存在一個require()方法,這個方法接收模組標識,就可以引入一個模組了。
// b.js
const { a } = require('./a'); // 1複製程式碼
三、Node中的模組
我們先來看一段程式碼。
然後我們把他跑起來,我們到瀏覽器裡去看。
在瀏覽器裡我們看到了這樣的一幕,很奇怪是不是,我們明明沒有寫這麼多程式碼。原來Nodejs悄悄地幫我們做了這項工作,在我們程式碼的頭和尾加上了這些程式碼。我們再來看一看,函式裡面傳入的幾個引數是什麼?裡面的require就不用多說了,這是用來引入的,而 __filename 和 __ dirname顧名思義就是指這個模組的檔案路徑和資料夾路徑,下面我們就來看一看exports和module.exports。
exports和module.exports
可以看到當我們執行完程式碼後,exports和module.exports上都掛載了一個log方法,也就是我們匯出去的方法。敲重點了,exports是module.exports的引用,好了這麼說大家應該就明白了,整個模組唯一的出口就是module.exports,而exports是給我們提供的一個簡便的寫法,但是呢如果我們改變了exports的指向,也就是重新給他賦值了,那麼他就不會再有匯出的功能了。
四、require規則
其實對於require的規則,也是有幾點要提的。
- /代表絕對路徑,./代表相對路徑
- 預設的副檔名是js,如果你不寫的話會按照.js、.json、.node去嘗試。
- 如果你引入的時候沒有寫路徑的話,會先去內建模組去找,比如說http等,然後就回去node_modules裡去找,層層的往上一級的node_modules找,直到根路徑。
- 還有node對於模組是有快取的,你載入了第一次之後,第二次開始就會在快取中找到,快取的優先順序是大於內建模組的,是優先順序最高的。
感覺內容有點多,今天看的比較草,望多多包涵,多提寶貴意見,謝謝。