模塊概念
- 一個js文件就是一個模塊
- Node 中沒有全局作用域,一個模塊就是一個獨立的環境
- Node 中的模塊默認是不能相互訪問的
核心模塊
- 由Node提供的封裝了API的具名模塊
- fs : 文件處理模塊
- http : 網絡服務構建模塊
- os : 系統服務模塊
- . . . . . .
導入導出模塊(讓模塊之間可以相互訪問)
導入
通過 require()
來加載並執行指定的模塊,返回對應模塊中的exports對象
const customModuleName = require('module');
require()
加載規則
- 優先從緩存加載: 加載過的模塊再次請求加載時不會重複加載,會從緩存中找到之前加載的模塊,將模塊的導出的結果返回
- 判斷模塊的標識(
require()的參數
):- 核心模塊: 模塊標識就是核心模塊的的名稱。
- 用戶自定義模塊: 路徑形式+模塊名稱,Node會根據模塊是否包含路徑形式的字符來判斷加載的是否是用戶自定義的模塊。當前路徑也要 加
./
。 - 第三方模塊: 模塊標識是此模塊報名。Node在判斷當前此模塊非核心模塊後會在當前目錄下查找
node_modules
目錄,再在其中找到對應包名的目錄,然後找到該目錄中的package.json
文件,找到main
屬性所指定的入口文件,然後加載這個入口文件。(如果該屬性沒有值,則會將index.js
文件作爲默認備選項)。如果當前目錄下沒有node_modules
或者其之下沒有對應包名的目錄,就會到上一層去找,直到磁盤根目錄,如果還找不到就報錯。一般將一個node_modules
放在項目根目錄下,並且不會再有其他node_modules
目錄了。
導出
在Node中,每個模塊默認都有一個module
的對象,這個對象中有一個exports
對象
let module = {
exports:{
...
}
}
這個exports
對象用於我們將模塊中需要導出的東西進行導出
let foo = 'bar';
let fn = function(){...};
module.exports.foo = foo;
module.exports.fn = fn;
默認在每一個模塊最後都有一個retutn module.exports
的語句來將我們設置的東西導出
不過Node還提供了一個exports
對象,可以讓我們不用點得太深
let foo = 'bar';
let fn = function(){...};
exports.foo = foo;
exports.fn = fn;
效果和module.exports
相同,實際上這兩個東西是一樣的
module.exports === exports;//true
//in fact
let exports = module.exports;
因此二者指向的是同一個空間。
有時我們希望直接導出某個數據對象,如直接導出一個函數,對象…,而不是導出一個exports
。先來看一下錯誤的做法
let fn = function(){...};
exports = fn;
由於直接賦值改變了exports
的指向,指向了fn
但是模塊最終返回的是module.exports
,所以對exports
的操作不會影響到最終返回的結果。
正確的做法
let fn = function(){...};
module.exports = fn;
PS:如果分不清楚的話,可以選擇忘記exports
而使用module.exports
注意: Node內部採用的是UTF-編碼,不會發生中文亂碼的情況,但是返回數據到前端時則需要設置Content-Type