模塊系統 Node根據CommonJS規範實現了一套自己的模塊機制,可以使用require()導入一個模塊,使用module.exports導出一個模塊。 require使用 在Node中我們可以使用require()導入一個模塊,此時我們就會獲得一個被導入模塊的對象,我們就可以利用這個對象來完成一 ...
模塊系統
Node根據CommonJS規範實現了一套自己的模塊機制,可以使用require()導入一個模塊,使用module.exports導出一個模塊。
require使用
在Node中我們可以使用require()導入一個模塊,此時我們就會獲得一個被導入模塊的對象,我們就可以利用這個對象來完成一些操作,例如:
var fs = require("fs"); fs.readFile("content.txt",function(err,data){ if(err){ return console.log("讀取文件錯誤!"); } console.log(data.toString()); })
我們通過require()將fs模塊導入,此時我們就通過獲得的fs模塊的對象來實現對文件的操作。
在Node中模塊分為核心模塊和文件模塊,核心模塊即被被編譯成二進位代碼的模塊,是Node自帶的一些模塊。文件模塊即我們自己編寫的模塊,無論哪種模塊都可以通過require()函數來引入。
require()的參數有四種不同的形式,分別為:
核心模塊:require("fs")
相對文件路徑:require("../xxx")
絕對文件路徑:require("/xxx")
非核心模塊的文件模塊:require("xxx")
載入模塊的過程如下圖所示:
require按照路徑載入模塊
例如我們通過require("X")載入一個模塊,首先會去文件模塊緩存區中查找有沒有該模塊的緩存,如果緩存區中存在該模塊,則直接返回。如果不存在該模塊就會判斷X的類型,如果是載入一個原生模塊,就會按原生模塊緩存區,原生模塊這樣的順序去查找該模塊,如果在原生模塊緩存區中找到就會直接返回模塊對象,如果在原生模塊中找到就會在原生模塊緩存區中加入該模塊以方便下一次的使用,然後返回模塊。
如果X是一個路徑類型首先把X當做文件按照X、X.js、X.json、X.node來查找該模塊,找到之後加入到文件模塊緩存區中然後返回該模塊。如果沒有找到,則把X當做是一個目錄,在X裡面按照index.js、index.json、index.node的順序依次查找,如果目錄中存在package.json則優先載入main屬性對應的文件,在找到之後將模塊加入到文件模塊緩存區中然後返回該模塊。
我們在桌面上新建兩個文件夾,分別為first和second,在first中新建first.js文件,first.js內容如下:
var name = "zt" module.exports.show = function(){ console.log(name); }
在sencond中新建main.js文件,main.js文件內容如下:
var first = require("../first"); first.show();
在命令行中進入sencond文件node main.js執行,會報Error,不能找到first。我們按照上面的過程來排除錯誤,第一次載入文件緩存區中沒有,也不是原生模塊,此時就會按照路徑的方式來載入first模塊,首先把它當成一個文件,即在桌面中按照first、first.js、first.json、first.node的順序來查找,都不存在,然後把first看錯一個目錄,然後在first文件內去查找,首先查看有沒有package.json文件,存在就會載入main屬性對應的文件,不存在就按照index.js、index.json、index.node的順序來查找,仍然找不到最終就會報錯。
按照上面的流程我們可以通過三種方式來修改:
1:在桌面上新建一個first.js,這時當按照文件來查找時就可以找到first.js,然後載入模塊。
2:在first文件夾中將first.js改名為index.js,這樣在按照文件不能查找到,按照目錄查找時就可以找到index.js,然後載入模塊。
3:在first文件夾中初始化一個package.json文件,main屬性值為first.js,這樣在按照目錄查找時在目錄中存在package.json文件就會載入main屬性對應的文件。
require按照模塊去查找
例如在second的main.js中通過require("first")這種方式來載入first模塊,使用這種方式來載入模塊優先在當前文件夾(second文件夾)中查找node_modules文件夾,在node_modules文件夾中去查找first模塊(在node_modules文件夾中也是按照路徑的那個套路來查找),然後在sencond的父級下的node_modules文件下去查找first模塊,按照這種方式一直查找下去,我們可以通過module.paths來查看查找的路徑:
console.log(module.paths);
在sencond文件夾中新建node_modules文件夾,然後把first文件夾放入到node_modules文件夾中,這樣main.js中的require("first")就可以找到first模塊了。
module.exports導出模塊
可以在一個文件中使用module.exports導出一個模塊,這樣在require()時就可以使用導出的屬性或者方法。以上面的first.js為例我們在first.js中使用module.exports導出了show方法,這樣我們在使用require()之後獲取到的對象就可以使用show方法了。
Node對module.exports的使用做了一些簡化處理讓我們在導出時可以使用exports:
module.exports = exports = {};
module.exports和exports共用一個引用,這樣就可以通過exports來收集屬性:
var name = "zt" exports.show = function(){ console.log(name); }
通過module.exports = exports = {},這樣在使用require()函數時獲得的module.exports對象也就有了exports收集的屬性。
如果module.exports重新賦值module.exports和exports的引用關係也就斷開了,而require()函數返回的是module.exports對象,也就不能得到exports收集的屬性了,所以在使用時不要混用。