亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

Node.js模塊加載詳解

2019-11-20 14:16:02
字體:
來源:轉載
供稿:網友

JavaScript是世界上使用頻率最高的編程語言之一,它是Web世界的通用語言,被所有瀏覽器所使用。JavaScript的誕生要追溯到Netscape那個時代,它的核心內容被倉促的開發出來,用以對抗Microsoft,參與當時白熱化的瀏覽器大戰。由于過早的發布,無可避免的造成了它的一些不太好的特性。

盡管它的開發時間很短,但是JavaScript依然具備了很多強大的特性,不過,每個腳本共享一個全局命名空間這個特性除外。

一旦Web頁面加載了JavaScript代碼,它就會被注入到全局命名空間,會和其他所有已加載的腳本公用同一個地址空間,這會導致很多安全問題,沖突,以及一些常見問題,讓bug即難以跟蹤又很難解決。

不過謝天謝地,Node為服務器端JavaScript定了一些規范,還實現了CommonJS的模塊標準,在這個標準里,每個模塊有自己的上下文,和其他模塊相區分。這意味著,模塊不會污染全局作用域,因為根本就沒有所謂的全局作用域,模塊之間也不會相互干擾。

本章,我們將了解幾種不同的模塊以及如何加載它們。

把代碼拆分成一系列定義良好的模塊可以幫你掌控你的應用程序,下面我們將學習如何創建和使用你自己的模塊。

了解Node如何加載模塊

Node里,可以通過文件路徑來引用模塊,也可以通過模塊名引用,如果用名稱引用非核心模塊,Node最終會把模塊名影射到對應的模塊文件路徑。而那些包含了核心函數的核心模塊,會在Node啟動時被預先加載。

非核心模塊包括使用NPM(Node Package Manager)安裝的第三方模塊,以及你或你的同事創建的本地模塊。

每個被當前腳本導入的模塊都會向程序員暴露一組公開API,使用模塊前,需要用require函數來導入它,像這樣:

復制代碼 代碼如下:

var module = require(‘module_name')

上面的代碼會導入一個名為module_name的模塊,它可能是個核心模塊,也可以是用NPM安裝的模塊,require函數返回一個包含模塊所有公共API的對象。隨模塊的不同,返回的對象可能是任何JavaScript值,可以是一個函數,也可以是個包含了一系列屬性(函數,數組或者任何JavaScript對象)的對象。

導出模塊

CommonJS模塊系統是Node下文件間共享對象和函數的唯一方式。對于一個很復雜的程序,你應該把一些類,對象或者函數重構成一系列良好定義的可重用模塊。對于模塊使用者來說,模塊僅對外暴露出那些你指定的代碼。

在下面的例子里你將會了解到,在Node里文件和模塊是一一對應的,我們創建了一個叫circle.js的文件,它僅對外導出了Circle構造函數。

復制代碼 代碼如下:

function Circle(x, y, r) {

       function r_squared() {

              return Math.pow(r, 2);

       }

       function area() {

              return Math.PI * r_squared();

       }

       return {area: area};

}

module.exports = Circle;

代碼里最重要的是最后一行,它定義了模塊對外導出了什么內容。module是個特殊的變量,它代表當前模塊自身,而module.exports是模塊對外導出的對象,它可以是任何對象,在這個例子里,我們把Circle的構造函數導出了,這樣模塊使用者就可以用這個模塊來創建Circle實例。

你也可以導出一些復雜的對象,module.exports被初始化成一個空對象,你把任何你想暴露給外界的內容,作為module.exports對象的屬性來導出。比如,你設計了一個模塊,它對外暴露了一組函數:

復制代碼 代碼如下:

                  function printA() {

         console.log('A');

}

function printB() {

         console.log('B');

}

function printC() {

         console.log('C');

}

module.exports.printA = printA;

module.exports.printB = printB;

module.exports.pi = Math.PI;

這個模塊導出了兩個函數(printA和printB)和一個數字(pi),調用代碼看起來像這樣:

復制代碼 代碼如下:

var myModule2 = require('./myModule2');

myModule2.printA(); // -> A

myModule2.printB(); // -> B

console.log(myModule2.pi); // -> 3.141592653589793

加載模塊

前面提到過,你可以使用require函數來加載模塊,不用擔心在代碼里調用require會影響全局命名空間,因為Node里就沒有全局命名空間這個概念。如果模塊存在且沒有任何語法或初始化錯誤,require函數就會返回這個模塊對象,你還可以這個對象賦值給任何一個局部變量。

模塊有幾種不同的類型,大概可以分為核心模塊,本地模塊和通過NPM安裝的第三方模塊,根據模塊的類型,有幾種引用模塊的方式,下面我們就來了解下這些知識。

加載核心模塊

Node有一些被編譯到二進制文件里的模塊,被稱為核心模塊,它們不能通過路徑來引用,只能用模塊名。核心模塊擁有最高的加載優先級,即使已經有了一個同名的第三方模塊,核心模塊也會被優先加載。

比如,如果你想加載和使用http核心模塊,可以這樣做:

復制代碼 代碼如下:

         var http = require('http');

這將返回一個包含了http模塊對象,它包含了Node API文檔里定義的那些htpp模塊的API。

加載文件模塊

你也可以使用絕對路徑從文件系統里加載模塊:

復制代碼 代碼如下:

var myModule = require('/home/pedro/my_modules/my_module');

也可以用一個基于當前文件的相對路徑:

復制代碼 代碼如下:

var myModule = require('../my_modules/my_module');

var myModule2 = require('./lib/my_module_2');

注意上面的代碼,你可以省略文件名的擴展名,如果Node找不到這個文件,會嘗試在文件名后加上js后綴再次查找(譯者注:其實除了js,還會查找json和node,具體可以看官網文檔),因此,如果在當前目錄下存在一個叫my_module.js的文件,會有下面兩種加載方式:

復制代碼 代碼如下:

var myModule = require('./my_module');

var myModule = require('./my_module.js');

加載目錄模塊

你還可以使用目錄的路徑來加載模塊:

復制代碼 代碼如下:

var myModule = require('./myModuleDir');

Node會假定這個目錄是個模塊包,并嘗試在這個目錄下搜索包定義文件package.json。

如果沒找到,Node會假設包的入口點是index.js文件(譯者注:除了index.js還會查找index.node,.node文件是Node的二進制擴展包,具體見官方文檔),以上面代碼為例,Node會嘗試查找./myModuleDir/index.js文件。

反之,如果找到了package.json文件,Node會嘗試解析它,并查找包定義里的main屬性,然后把main屬性的值當作入口點的相對路徑。以本例來說,如果package.json定義如下:

復制代碼 代碼如下:

                   {

                            "name" : "myModule",

                            "main" : "./lib/myModule.js"

                   }

Node就會嘗試加載./myModuleDir/lib/myModule.js文件

從node_modules目錄加載

如果require函數的參數不是相對路徑,也不是核心模塊名,Node會在當前目錄的node_modules子目錄下查找,比如下面的代碼,Node會嘗試查找文件./node_modules/myModule.js:

復制代碼 代碼如下:

var myModule = require('myModule.js');

如果沒找到,Node會繼續在上級目錄的node_modules文件夾下查找,如果還沒找到就繼續向上層目錄查找,直到找到對應的模塊或者到達根目錄。

你可以使用這個特性來管理node_modules目錄的內容或模塊,不過最好還是把模塊的管理任務交給NPM(見第一章),本地node_modules目錄是NPM安裝模塊的默認位置,這個設計把Node和NPM關聯在了一起。通常,作為開發人員不必太關心這個特性,你可以簡單的使用NPM安裝,更新和刪除包,它會幫你維護node_modules目錄

緩存模塊

模塊在第一次成功加載后會被緩存起來,就是說,如果模塊名被解析到同一個文件路徑,那么每次調用require(‘myModule')都確切地會返回同一個模塊。

比如,有一個叫my_module.js的模塊,包含下面的內容:

復制代碼 代碼如下:

console.log('module my_module initializing...');

module.exports = function() {

         console.log('Hi!');

};

console.log('my_module initialized.');

然后用下面的代碼加載這個模塊:

復制代碼 代碼如下:

var myModuleInstance1 = require('./my_module');

它會產生下面的輸出:

復制代碼 代碼如下:

module my_module initializing...

my_module initialized

如果我們兩次導入它:

復制代碼 代碼如下:

var myModuleInstance1 = require('./my_module');

var myModuleInstance2 = require('./my_module');

輸出依然是:

復制代碼 代碼如下:

module my_module initializing...

my_module initialized

也就是說,模塊的初始化代碼僅執行了一次。當你構建自己的模塊時,如果模塊的初始化代碼里含有可能產生副作用的代碼,一定要特別注意這個特性。

小結

Node取消了JavaScript的默認全局作用域,轉而采用CommonJS模塊系統,這樣你可以更好的組織你的代碼,也因此避免了很多安全問題和bug??梢允褂胷equire函數來加載核心模塊,第三方模塊,或從文件及目錄加載你自己的模塊

還可以用相對路徑或者絕對路徑來加載非核心模塊,如果把模塊放到了node_modules目錄下或者對于用NPM安裝的模塊,你還可以直接使用模塊名來加載。

 譯者注:

建議讀者把官方文檔的模塊章節閱讀一遍,個人感覺比作者講得更清晰明了,而且還附加了一個非常具有代表性的例子,對理解Node模塊加載會很有很大幫助。下面把那個例子也引用過來:

復制代碼 代碼如下:

用require(X) 加載路徑Y下的模塊

1. 如果X是核心模塊,

   a. 加載并返回核心模塊

   b. 結束

2. 如果X以 './' or '/' or '../ 開始'

   a. LOAD_AS_FILE(Y + X)

   b. LOAD_AS_DIRECTORY(Y + X)

3. LOAD_NODE_MODULES(X, dirname(Y))

4. 拋出異常:"not found"

LOAD_AS_FILE(X)

1. 如果X是個文件,把 X作為JavaScript 腳本加載,加載完畢后結束

2. 如果X.js是個文件,把X.js 作為JavaScript 腳本加載,加載完畢后結束

3. 如果X.node是個文件,把X.node 作為Node二進制插件加載,加載完畢后結束

LOAD_AS_DIRECTORY(X)

1. 如果 X/package.json文件存在,

   a. 解析X/package.json, 并查找 "main"字段.

   b. 另M = X + (main字段的值)

   c. LOAD_AS_FILE(M)

2. 如果X/index.js文件存在,把 X/index.js作為JavaScript 腳本加載,加載完畢后結束

3. 如果X/index.node文件存在,把load X/index.node作為Node二進制插件加載,加載完畢后結束

LOAD_NODE_MODULES(X, START)

1. 另DIRS=NODE_MODULES_PATHS(START)

2. 對DIRS下的每個目錄DIR做如下操作:

   a. LOAD_AS_FILE(DIR/X)

   b. LOAD_AS_DIRECTORY(DIR/X)

NODE_MODULES_PATHS(START)

1. 另PARTS = path split(START)

2. 另ROOT = index of first instance of "node_modules" in PARTS, or 0

3. 另I = count of PARTS - 1

4. 另DIRS = []

5. while I > ROOT,

   a. 如果 PARTS[I] = "node_modules" 則繼續后續操作,否則下次循環

   c. DIR = path join(PARTS[0 .. I] + "node_modules")

   b. DIRS = DIRS + DIR

   c. 另I = I - 1

6. 返回DIRS

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久97久久97精品免视看| 国产精品九九久久久久久久| 亚洲第一福利视频| 亚洲国产精品悠悠久久琪琪| 亚洲免费中文字幕| 色综合天天狠天天透天天伊人| 97在线视频免费观看| 日韩专区在线播放| 久久久久久久久电影| 亚洲激情在线观看| 午夜精品三级视频福利| 国产精品igao视频| 7777kkkk成人观看| 日韩av在线资源| 成人国产精品一区二区| 日韩暖暖在线视频| 欧美激情视频三区| 欧美大胆a视频| 国产成人综合精品| 92版电视剧仙鹤神针在线观看| 亚洲国产欧美一区二区三区同亚洲| 亚洲国产中文字幕久久网| 亚洲性av在线| 国产精品一区二区久久久久| 久久精品国产亚洲精品| 在线视频日韩精品| 中文字幕九色91在线| 亚洲视频一区二区| 国产成人福利网站| 日韩电影免费在线观看中文字幕| 九九精品视频在线| 欧美日韩在线视频首页| 少妇久久久久久| 尤物精品国产第一福利三区| 亚洲欧美国产高清va在线播| 精品福利樱桃av导航| 国产专区精品视频| 欧美一区第一页| 亚洲精品国精品久久99热| 精品亚洲永久免费精品| 成人激情在线观看| 国产精品综合久久久| 久久精品免费电影| 久久久久久这里只有精品| 日韩毛片在线观看| 欧美限制级电影在线观看| 久久久久久久影视| 亚洲精美色品网站| 亚洲精品少妇网址| 精品久久久在线观看| 久久精品99无色码中文字幕| 日韩国产欧美区| 日韩一区二区久久久| 美女扒开尿口让男人操亚洲视频网站| 亚洲欧美日韩图片| 一区二区三区视频免费| 色99之美女主播在线视频| 日韩电视剧在线观看免费网站| 欧美精品在线极品| 亚洲国产精品悠悠久久琪琪| zzijzzij亚洲日本成熟少妇| 日韩中文字幕免费视频| 最近中文字幕2019免费| 欧美大片大片在线播放| 精品无人区太爽高潮在线播放| 亚洲色图国产精品| 欧美午夜宅男影院在线观看| 成人www视频在线观看| 日韩经典中文字幕在线观看| 国产成人精品综合| 欧美视频二区36p| 欧美激情在线播放| 国产美女直播视频一区| 欧美裸体xxxx极品少妇软件| 欧美激情在线播放| 亚洲人成网站色ww在线| 91色琪琪电影亚洲精品久久| 欧美日韩亚洲视频一区| 国产在线98福利播放视频| 精品国产乱码久久久久久虫虫漫画| 久热精品视频在线观看一区| 色综合天天综合网国产成人网| 久久精品国产视频| 精品视频在线播放免| 久久久噜久噜久久综合| 亚洲国产私拍精品国模在线观看| 国产精品久久久久久久久| 少妇高潮久久77777| 日韩中文字幕国产| 最新国产精品拍自在线播放| 国产在线视频不卡| 91精品国产91久久久久久| 91精品免费看| 岛国视频午夜一区免费在线观看| 在线电影欧美日韩一区二区私密| 日本一区二区在线免费播放| 91高潮精品免费porn| 精品国产精品三级精品av网址| 日韩中文视频免费在线观看| 欧美成人精品一区二区三区| 91天堂在线观看| 欧美在线精品免播放器视频| 欧美色播在线播放| 久久免费福利视频| 久久久免费精品视频| 色一区av在线| 欧美华人在线视频| 日韩中文在线视频| 亚洲国产成人精品电影| 国内成人精品视频| 播播国产欧美激情| 亚洲成人在线网| 国产精品久久久久久久电影| 欧美在线视频观看免费网站| 91高潮精品免费porn| 这里只有视频精品| 精品人伦一区二区三区蜜桃网站| 欧美专区国产专区| 日韩69视频在线观看| 亚洲色图欧美制服丝袜另类第一页| 一本色道久久综合狠狠躁篇怎么玩| 国内精品久久久久伊人av| 国产精品午夜视频| 欧美日韩国产丝袜另类| 亚洲高清福利视频| 91久久精品国产91久久性色| 九九热精品视频| 亚洲色无码播放| 青青草原成人在线视频| 日韩av电影国产| 国产精品高潮呻吟久久av无限| 欧美丝袜第一区| 欧洲成人午夜免费大片| 伊人成人开心激情综合网| 国产999精品久久久| 91免费人成网站在线观看18| 国产精品高清在线观看| 久久精品视频在线播放| xxav国产精品美女主播| 疯狂蹂躏欧美一区二区精品| 96精品视频在线| 精品国产一区二区三区久久狼黑人| 国产精品在线看| 亚洲大尺度美女在线| 国产一区二区三区视频免费| 国产精品久久9| 精品国产一区二区三区久久狼黑人| 国产精品吴梦梦| 国产精品日韩专区| 国产视频欧美视频| 亚洲91精品在线| 日韩视频永久免费观看| 视频在线一区二区| 国内精品美女av在线播放| 欧美一区二区影院| 精品毛片网大全| 国产精品久久久久久久久男| 亚洲欧洲自拍偷拍| 亚洲精品自在久久| 国产成人在线播放| 亚洲国产精品悠悠久久琪琪| 欧美又大又硬又粗bbbbb| 成人网址在线观看| www.xxxx精品|