Nodejs模塊化開發

前言

對nodejs入門之後,我們經常會發現,代碼中經常會出現require(’’)這樣的代碼,nodejs菜鳥教程的創建的第一個應用就使用到了require指令來載入http模塊,並將實例化的http賦值給變量http。那麼所謂的模塊又是什麼?今天將從require開始,進入模塊的世界

require(’’)方法

require()是接收模塊標識符參數,然後node根據一定的規則引入該模塊之後,就可以使用模塊中定義的方法和屬性了。node引入模塊是有規則的。
nodejs模塊包含三種:
內置模塊:也就是nodejs提供的模塊,例如http,fs等。這些模塊在node源碼編譯的過程中就編譯進了二進制執行文件,在node進程啓動的時候,部門核心模塊就直接加載進內存中,只需要經歷路徑分析步驟,而且路徑分析中是有限判斷的,所以加載速度較快。
第三方模塊:
自定義模塊(一個js一個模塊):文件模塊使用的時候需要按需加載,需要經歷路徑分析、文件定位、編譯執行三個步驟。

優先從緩存中加載

node對引入過的模塊會進行緩存,node是緩存編譯執行之後的對象而不是靜態文件,是因爲 我們對一個對象引入兩次,得到的對象是相等的。跟Java不同,如果你對Java的一個對象new兩次,那麼你得到的是兩個不同的對象。
驗證代碼如下:
module.js

let sayHello=function(){
    console.log('hello');
}

let sayBye=function(){
    console.log('Bye~');
}

module.exports={
    sayHello:sayHello,
    sayBye:sayBye
}

testmodule.js

var moduleTest1=require('./module1');
var moduleTest2=require('./module1');

console.log(moduleTest2);
console.log(moduleTest1===moduleTest2);

運行結果如下:
在這裏插入圖片描述
解析:雖然我們兩個引入了module1的模塊,但是模塊中的代碼其實只執行了一遍。那麼moduleTest1和moduleTest2指向的是同一個對象,結果纔會是TRUE。–可以查看Module._load的源碼進行分析

路徑分析

nodejs會根據require是相對路徑還是非相對路徑做出不同的行爲。
require(Y+X)
1、如果X是核心模塊,例如(require(“http”))
* 返回該模塊 * 不在繼續執行
2、如果Y是以’./’,’/‘或者’…/‘開頭
(1)優先從緩存中加載
(2)X當做文件,從制定路徑開始,依次查找下面文件:X、X.js、X.json、X.node,只要其中一個存在,就返回該文件,不在繼續執行
(3)把X當成目錄,從執行路徑開始,一次查找下面文件:X/package.json(main字段)、X/index.js、X/index.json、X/index.node,只要其中一個存在,就返回該文件,不在繼續執行
3、如果X不是核心模塊,也沒有’./’,’/‘或者’…/'開頭,則nodejs會從當前模塊的父目錄開始,嘗試從它的/node_module目錄里加載模塊,如果還沒有找到,則移動到再上一層父目錄,直到文件系統的根目錄。
4、拋出Error: Cannot find module

清除緩存

require第一步是將模塊加載到內存的,用於提升第二次加載的性能。但是,如果修改了被引入模塊的代碼之後,再次引入,就發現還是之前的代碼。

module模塊

每個文件就是一個模塊,每個模塊中都有一個module對象。module對象的屬性以下圖片是打印出來的module對象值:
在這裏插入圖片描述
由圖可知,module對象有以下屬性
(1)id:當前模塊的bi
(2)path:文件所在位置
(3)exports:暴露給外部的值,由代碼值,此暴露了2個函數
(4)parent:一個對象,表示調用當前模塊的模塊
(5)filename:模塊的絕對路徑
(6)loaded:布爾值,表示當前模塊是否已經被完全加載
(7)paths:從當前文件目錄開始查找node_modules目錄;然後依次進入父模塊,查找父目錄下的node_modules目錄,直到根目錄下的node_modules目錄。

module.exports

經過上面的解析,發現nodule對象有一個exports屬性,該屬性就是用來對外暴露變量、方法或這個模塊的。當使用require調用的時候,其實就是調用的exports屬性

exports對象

module.exports和exports對象的聯繫和區別:
1、module.exports和exports對象的都是引用類型的變量,兩個對象指向同一塊內存地址。並且兩者一開始都是指向一個空對象
2、exports只能使用,語法類向外暴露內部變量 export.xxx=xxx,而module.exports可以使用語法或者對象的形式輸出

module.exports.xxx=xxx;
module.exports={xxx:yyy}

如果以對象輸出的的話只能module.exports

3、module對象中包含了exports對象,所以exports不能直接賦予對象類型的值,因爲這樣會改變exports的指向,從而找不到module.exports和exports不是一個對象,也就是說給exports賦值會切斷與module.exports之間的聯繫
在這裏插入圖片描述
tips:exports=module.exports=xxx //code
這種方式的實現其實就是賦值module.exports後不忘把exports也同時指向這塊新內存了,即module.exports指向新對象以後,exports斷開了對module.exports的引用,後面的做法主要是讓exports重新指向module.exports

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章