希望可以搞懂它。
三巨頭標準
Asynchronous Module Definition(AMD)
非同步模組定義。可以想成是從 CommonJS 延伸出來的另一個標準,目的是提升瀏覽器在載入模組的效能。
CommonJS(CMJ)
就是等下要介紹的東西,特別注意這種模組是用 同步 來載入模組的。
ES6(ESM)的
import
與export
之後出來的一個新標準,可以在 Node.js 跟瀏覽器上跑,詳細介紹可以參考 ES6 的模組機制。
注意事項
這篇文章介紹的模組機制是「CommonJS」的標準,而採用這套標準的執行環境是「Node.js」,不是瀏覽器。也就是說 你沒辦法在瀏覽器上用這套標準。
如果你曾經看過有些瀏覽器上可以用,那也許是真的。不過正確一點的說法是「用了某些工具讓瀏覽器可以支援」才對,所以請不要誤會了。
輸出一個 module 給別人
假設我想寫一個 module 給別人用,那我可以這樣寫:
1 | // myModule.js |
module.exports
就是用來「把你想輸出的內容」給輸出。
在上面的例子裡我輸出了一個 function,但其實也可以改成 123
或 'Hello'
或是 {name: 'PeaNu'}
等等,只要是符合 JavaScript 中的資料型態都可以。
載入寫好的 module
剛剛已經寫好 module 的部分了,接著我們要來載入:
1 | // main.js |
require
就是用來「把你想輸入的內容」給輸入。
記得要指定一個變數來儲存引入的模組,接著這個變數就等同於剛剛寫好的模組。
所以把 myModule
印出來看就會得到剛剛寫好的 function: double
如果到這裡都沒問題的話,就可以使用模組了:
1 | var myModule = require('./myModule') |
另外一種輸出方式
exports
是另外一種輸出方式,跟 module.exports
不同的地方是「只能以物件格式輸出」:
1 | // myModule.js |
所以引入的時候,只會拿到一個物件:
1 | var myModule = require('./myModule') |
簡單來說,你可以把 exports
想成是這樣:
1 | { |
它不像 module.exports
那麼有彈性,想輸出什麼就輸出什麼,所以這個可能比較少用一點。
輸出多個內容
剛剛只有輸出一個 function,現在來多輸出幾個。
module.exports
1 | function double(n) { |
1 | var myModule = require('./myModule') |
exports
1 | function double(n) { |
1 | var myModule = require('./myModule') |
為什麼要有模組?
既然已經會使用了,那就要來談談為什麼要用它?
其實換個角度想就好了,如果沒有模組的話會怎麼樣?
舉個例子,假設我有兩個檔案,分別是 login.js
跟 form.js
。這兩個檔案都想用一個 function 來做「信箱驗證」的動作。在沒有模組的情況下只能這樣子做:
1 | // login.js |
1 | // form.js |
你應該能發現問題很明顯:
- 有幾個檔案要用,就要宣告幾個
validEmail
- 如果要修改
validEmail
,那每一個檔案都得開起來一個一個改
但如果是模組化,就只會有兩個動作:
- 我要用
validEmail
,就用一個變數來儲存require
引入進來的東西 - 如果要修改
validEmail
,我只要去這個模組的檔案修改就好
基於這兩點,其實就沒有不使用模組化的理由。