CommonJS模塊規(guī)范
- 一個(gè)js文件就是一個(gè)模塊
- CommonJS 就是一套約定標(biāo)準(zhǔn)约炎,不是技術(shù); 用于約定我們的代碼應(yīng)該是怎樣的一種結(jié)構(gòu)蟹瘾。
- Node 采用的模塊化結(jié)構(gòu)是按照 CommonJS 規(guī)范圾浅。
- CommonJS的特點(diǎn):
- 所有代碼都運(yùn)行在模塊作用域,不會(huì)污染全局作用域憾朴。
- 模塊可以多次加載狸捕,但是只會(huì)在第一次加載時(shí)運(yùn)行一次,然后運(yùn)行結(jié)果就被緩存了众雷,以后再加載府寒,就直接讀取緩存結(jié)果。要想讓模塊再次運(yùn)行报腔,必須清除緩存株搔。
- 模塊加載的順序,按照其在代碼中出現(xiàn)的順序纯蛾。
- 模塊的分類
- 自定義模塊:即我們自己寫的功能模塊文件纤房。
- 核心模塊:即Node自帶的功能模塊,如:HTTP模塊翻诉,fs模塊等等炮姨。
- 第三方模塊:社區(qū)或第三方開發(fā)好的功能模塊,可以直接拿回來(lái)用碰煌。
- 模塊的導(dǎo)入
- 通過(guò)
require("fs")
來(lái)加載模塊
- 如果是第三方模塊舒岸,需要先使用
npm
進(jìn)行下載
- 如果是自定義模塊,需要加上相對(duì)路徑./或者../,可以省略.js后綴芦圾,如果文件名是index.js那么index.js也可以省略
- 模塊可以被多次加載蛾派,但是只會(huì)在第一次加載
module.exports與exports
- 載入一個(gè)模塊就是構(gòu)建一個(gè) Module 實(shí)例,一個(gè)新的 JS 文件就是一個(gè)模塊
-
module.exports
是用于為模塊導(dǎo)出成員的接口个少。
- 在模塊的內(nèi)部洪乍,
module
變量代表的就是當(dāng)前模塊,它的exports
屬性就是對(duì)外的接口夜焦,加載某個(gè)模塊壳澳,加載的就是module.exports
屬性,這個(gè)屬性指向一個(gè)空的對(duì)象茫经。
-
exports
是指向module.exports
的引用巷波,相當(dāng)于在模塊開始執(zhí)行的時(shí)候進(jìn)行var exports = module.exports
操作萎津。從下面的打印中可以看出,它們最初都是一個(gè)空對(duì)象{}
抹镊,而這兩個(gè)對(duì)象實(shí)際上指向同一塊內(nèi)存空間姜性,即在不改變它們指向的內(nèi)存地址的前提下,它們是等價(jià)的髓考。
console.log(exports) //{}
console.log(module) //Module {……exports: {},parent: null……}
console.log(exports === module.exports) //true
-
require
引入的對(duì)象本質(zhì)上是module.exports
部念,這也意味著module.exports
與exports
指向的不是同一塊內(nèi)存時(shí),exports
的內(nèi)容就會(huì)失效氨菇。
//try.js
exports = {name: "Join"}
module.exports = {name: "Bob"}
//main.js
let name = require('./try.js')
console.log(name) //{ name: 'Bob' }
require加載文件規(guī)則
- require('../file.js'); // 上級(jí)目錄下找 file.js 文件
require('./file.js'); // 同級(jí)目錄找 file.js 文件
require('file.js'); // 同級(jí)目錄找 file.js 文件
- 加載順序:
- 按js文件來(lái)執(zhí)行(先找對(duì)應(yīng)路徑當(dāng)中的module.js文件來(lái)加載)
- 按json文件來(lái)解析(若上面的js文件找不到時(shí)儡炼,則找對(duì)應(yīng)路徑當(dāng)中的module.json文件來(lái)加載)
- 按照預(yù)編譯好的c++模塊來(lái)執(zhí)行(尋找對(duì)應(yīng)路徑當(dāng)中的module.node文件來(lái)加載)
- 若參數(shù)字符串為一個(gè)目錄(文件夾)的路徑,則自動(dòng)先查找該文件夾下的package.json文件查蓉,然后再再加載該文件當(dāng)中main字段所指定的入口文件乌询。(若package.json文件當(dāng)中沒有main字段,或者根本沒有package.json文件豌研,則再默認(rèn)查找該文件夾下的index.js文件作為模塊來(lái)載入妹田。)
CommonJS引入與ES6的區(qū)別
- CommonJS是直接做一個(gè)值的拷貝操作,也就是一旦輸出一個(gè)值鹃共,模塊內(nèi)部的變化是影響不到這個(gè)值的
//try.js
let counter = 1
let addCounter = () => {
counter++
}
module.exports = {
counter,
addCounter
}
//main.js
let func = require('./try.js')
console.log(func.counter) //1
func.addCounter()
console.log(func.counter) //1
- ES6模塊是動(dòng)態(tài)引用鬼佣,并且不會(huì)緩存值,模塊里面的變量綁定其所在的模塊霜浴。
//try.js
export let counter = 1
export let addCounter = () => {
counter++
}
//main.js
import {counter,addCounter} from './try.js'
console.log(counter) //1
addCounter()
console.log(counter) //2
- CommonJS模塊的循環(huán)引用
- 執(zhí)行
node main.js
->第一行晶衷,require(a.js)
- 進(jìn)入
require(a)
方法:判斷緩存->無(wú)->初始化一個(gè)module
->將module
加入緩存->執(zhí)行a.js內(nèi)容
- 第一行導(dǎo)出
a=1
->第二行引入b.js
- 執(zhí)行b.js的內(nèi)容,第一行導(dǎo)出
b=11
,第二行require(a.js)
- 此時(shí)a.js是第二次調(diào)用require阴孟,判斷緩存->有->繼續(xù)執(zhí)行b.js->第三行打印
1
->第四行修改b=22
- b文件執(zhí)行完畢回到a.js中->第三行打印
b=22
->導(dǎo)出a=2
- a文件執(zhí)行完畢晌纫,回到main.js中->獲取a,第二行輸出
a=2
->執(zhí)行完畢
// a.js
module.exports.a = 1;
var b = require('./b');
console.log(b);
module.exports.a = 2;
// b.js
module.exports.b = 11;
var a = require('./a');
console.log(a);
module.exports.b = 22;
//main.js
var a = require('./a');
console.log(a);
Node加載
- Node 要求使用 ES6 模塊需要采用
.mjs
后綴文件名永丝。也就是說(shuō)锹漱,Node 遇到.mjs
文件,就認(rèn)為它是ES6 模塊慕嚷,默認(rèn)啟用嚴(yán)格模式哥牍,不必在每個(gè)模塊文件頂部指定"use strict"
。
- 如果不希望將后綴名改成
.mjs
闯冷,可以在項(xiàng)目的package.json
文件中砂心,指定type
字段為module
。一旦設(shè)置了以后蛇耀,該目錄里面的 JS 腳本,就被解釋用 ES6 Module
坎弯。如果這時(shí)還要使用 CommonJS 模塊纺涤,那么需要將 CommonJS 模塊腳本的后綴名都改成.cjs
译暂。如果沒有type
字段,或者type
字段為commonjs
撩炊,則.js腳本會(huì)被解釋成 CommonJS 模塊外永。
{
"type": "module" // 開啟 ES6 Module 模式
}
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者