模塊
在計算機程序的開發(fā)中,隨著代碼越寫越多,在一個文件里代碼就會越來越長,越來越不容易維護.
為了編寫可維護的代碼,我們把很多函數(shù)分組,分別放在不同的文件里,這樣,每個文件包含的代碼就相對較少,很多變成語言都采用這種方式組織代碼. 在Node環(huán)境中,一個.js文件就是一個模塊(module)
使用模塊有什么好處?
最大的好處就是大大提高了代碼的可維護性,其次,編寫代碼不必從0開始,當一個模塊編寫完畢,就可以被其他地方引用,我們在編寫程序的時候,也經(jīng)常引用其他模塊,包括Node內(nèi)置的模塊和來自第三方的模塊.
使用模塊還可以避免函數(shù)名和變量名沖突,形同名字的函數(shù)和變量完全可以分別存在不同的模塊中,因此,我們自己在編寫模塊時,不必考慮名字會與其他模塊沖突
在上一節(jié),我們編寫了一個hello.js文件,這個hello.js文件就是一個模塊,模塊的名字就是文件名不帶js后綴,所以hello.js文件就是名為hello的模塊.
我們把hello.js改造一下,創(chuàng)建一個函數(shù),這樣我們就可以在其他地方調(diào)用這個函數(shù):
'use strict'
var s = 'Hello';
function greet(name){
console.log(s + ',' + name + '!');
}
module.exports = greet;
函數(shù)greet()是在hello模塊中定義的,代碼的最后一行賦值語句是,把函數(shù)greet作為模塊的輸出暴露出去,這樣其他模塊就可以使用greet函數(shù)了
問題是其他模塊怎么使用hello模塊這個greet函數(shù)呢,我們在編寫一個mian.js文件,調(diào)用hello模塊的greet函數(shù)
'use strict'
//引用hello模塊
var greet = require('./hello');
var s = 'Michael';
greet(s);
注意到引入hello模塊用Node提供的require函數(shù):
引入的模塊最為變量保存在greet變量中,那greet變量到底是什么東西?
其實變量greet就是hello.js中我們用module.exports=greet;輸出的greet函數(shù),所以main.js就成功引用了hello模塊中定義的greet()函數(shù)了,因為main.js和hello.js位于同一個目錄,所以我們使用了當前目錄’.’
var greet = require('./hello'); // 不要忘了寫相對目錄!
如果只寫模塊名
var greet = require(‘hello’);
則Node會依次在內(nèi)置模塊,全局模塊和當前模塊下查找hello.js,你可能會得到一個錯誤:
module.js
throw err;
遇到這個錯誤,你要檢查:
- 模塊名是否寫對了;
- 模塊文件是否存在;
- 相對路徑是否寫對了。
CommonJS規(guī)范
這種模塊加載機制被稱為CommonJS規(guī)范,在這個規(guī)范下,每個.js文件都是一個模塊,他們內(nèi)部各自使用的變量名和函數(shù)名都互不沖突
一個模塊想要對外暴露變量(函數(shù)也是變量),可以用module.exports= variable,一個模塊要引用其他模塊暴露的變量,用var ref = require(“module_name_”)就拿到了模塊引用的變量;
結(jié)論
要在模塊中對外輸出變量,用:
module.exports = variable;
輸出的變量可以是任意對象、函數(shù)、數(shù)組等等。
要引入其他模塊輸出的對象,用:
var foo = require('other_module');
引入的對象具體是什么,取決于引入模塊輸出的對象。
如果要輸出一個鍵值對象’{}’,可以利用exports這個已存在的空對象{},并繼續(xù)在上面添加新的鍵值;
如果要輸出一個函數(shù)或數(shù)組,必須直接對module.exports對象賦值。
所以我們可以得出結(jié)論:直接對module.exports賦值,可以應(yīng)對任何情況:
module.exports = {
foo: function () { return 'foo'; }
};
或者:
module.exports = function () { return 'foo'; };
最終,我們強烈建議使用module.exports = xxx的方式來輸出模塊變量,這樣,你只需要記憶一種方法。