CommonJS是由javascript社區(qū)提出的一套包含模塊、文件、IO、控制臺在內(nèi)的一系列標準。
1、模塊
CommonJS中規(guī)定每個文件是一個模塊,將一個js文件直接通過script標簽插入頁面中與封裝成CommonJS模塊最大的不同在于,前者的頂層作用域是全局作用域,在進行變量以及函數(shù)聲明的時候會污染全局環(huán)境。后者會形成一個屬于模塊自身的作用域,所有的變量以及函數(shù)只能自身模塊去訪問,對外是不可見的。
示例:
- getInfo.js:
export var name = 'getInfo.js中的name'
- index.js:
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
require('./src/index.js')
var name = 'index.js中的name';
console.log(name);
node在升級之后,對 require 的使用方法發(fā)生了改變。從node.js 14版及以上版本中,require作為COMMONJS的一個命令已不再直接支持使用,所以我們需要導(dǎo)入createRequire命令才可以。
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
2、導(dǎo)出
導(dǎo)出是一個模塊向外暴露自身的唯一方式,在CommonJS中,通過module.exports可以導(dǎo)出模塊的內(nèi)容。
module.exports = {
name: 'e-kr',
add: function(a,b) {
return a+b;
}
}
CommonJS模塊內(nèi)部會有一個module對象用于存放當前模塊的信息,默認是有一個主體的對象module的,不進行邏輯操作的話相當于導(dǎo)出的module空對象的。
export.name = 'e-kr';
exports默認指向了module.exports
3、導(dǎo)入
在CommonJS中使用require進行模塊導(dǎo)入時,
// getInfo.js
module.exports = {
add: function(a,b) {
return a+b;
}
}
// index.js
const info = require('./getInfo');
const sum = info.add(2,3);
console.log(sum);
在index.js中導(dǎo)入getInfo模塊,并調(diào)用它的add函數(shù)方法,當我們require一個模塊時會產(chǎn)生兩種情形:
- 1、require的模塊是第一次被加載,這時會首先執(zhí)行這個模塊,然后再導(dǎo)出內(nèi)容
- 2、require的模塊是之前被加載過的,這時該模塊的代碼不會再次執(zhí)行,而是直接導(dǎo)出之前執(zhí)行過的結(jié)果。
出現(xiàn)這種情況的原理是:
模塊中有一個module對象專門用來存放其信息,這個對象中有一個屬性loaded用于記錄該模塊是否被加載
過,它的默認值是false,當模塊第一次被加載和執(zhí)行過后會變成true,后面再次加載時檢測到module對象中的loaded屬性為true的話就不會再去執(zhí)行模塊代碼。
有時加載一個模塊,不需要獲取其導(dǎo)出的內(nèi)容,只想通過執(zhí)行它而產(chǎn)生某種作用,直接使用require即可。
此外,require函數(shù)可以接收表達式,這個特性可以動態(tài)的給我們指定模塊的加載路徑。
const moduleNames = ['foo.js', 'bar.js'];
moduleNames.forEach( name => {
require('./' + name);
})