JS中ESModule和commonjs介紹及使用區(qū)別
ES Module
導(dǎo)出
僅導(dǎo)出
- named exports: 命名導(dǎo)出,每次可以導(dǎo)出一個(gè)或者多個(gè)。
- default exports: 默認(rèn)導(dǎo)出,每次只能存在一個(gè)。
以上兩者可以混合導(dǎo)出:
// 命名導(dǎo)出 export const b = 'b' // 默認(rèn)導(dǎo)出 export default { a: 1 }; const c = 'c' export { c } // 以上內(nèi)容會(huì)合并導(dǎo)出,即導(dǎo)出為: {b:'b', c:'c', default: {a:1}}
更多示例可以直接去看mdn
重導(dǎo)出(re-exporting / aggregating)
算是一個(gè)導(dǎo)入再導(dǎo)出的一個(gè)語(yǔ)法糖吧。
export { default as function1, function2, } from 'bar.js'; // 等價(jià)于 import { default as function1, function2 } from 'bar.js'; export { function1, function2 };
然而這種語(yǔ)法是會(huì)報(bào)錯(cuò)的:
export DefaultExport from 'bar.js'; // Invalid
正確的語(yǔ)法應(yīng)該是:
export { default as DefaultExport } from 'bar.js'; // valid
我猜是因?yàn)閑xport 本身支持的export xxx這種語(yǔ)法必須是要導(dǎo)出一個(gè)對(duì)象,然而import xxx可能是任意類型,兩者沖突了,所以從編譯層面就不讓這種語(yǔ)法生效會(huì)更好。
嵌入式腳本
嵌入式腳本不可以使用export。
引入
語(yǔ)法
- import all exports:
import * as allVar
,所有導(dǎo)出內(nèi)容,包含命名導(dǎo)出及默認(rèn)導(dǎo)出。allVar會(huì)是一個(gè)對(duì)象,默認(rèn)導(dǎo)出會(huì)作為allVar的key名為default對(duì)應(yīng)的值。 - import named exports:
import {var1, var2}
,引入命名導(dǎo)出的部分。沒找到,對(duì)應(yīng)的值就為undefined。個(gè)人覺得可以看做是"import all exports"的解構(gòu)語(yǔ)法。 - import default exports:
import defaultVar
,引入默認(rèn)導(dǎo)出的部分。 - import side effects:
import "xxx./js"
,僅運(yùn)行這個(gè)js,可能是為了獲取其副作用。
// test.js export const b = 'b' // 命名導(dǎo)出 export default { // 默認(rèn)導(dǎo)出 a: 1 }; // index.js import { b, default as _defaultModule } from './test.js' import defaultModule from './test.js' import * as allModule from './test.js' console.log('name export', b) // 'b' console.log('default export', defaultModule) // {a:1} console.log(_defaultModule === defaultModule) // true console.log('all export', allModule) // {b:'b', default: {a:1}}
一個(gè)之前老記錯(cuò)的case
// test.js export default { // 默認(rèn)導(dǎo)出 a: 1 }; // index.js import { a } from './test.js' console.log('name export', a) // undefined // index.js import defaultModule from './test.js' import * as allModule from './test.js' console.log('default export', defaultModule) // {a:1} console.log('all export', allModule) // {default: {a:1}}
嵌入式腳本
嵌入式腳本引入modules時(shí),需要在script上增加 type="module"。
特點(diǎn)
live bindings:
- 通過(guò)export在mdn上的解釋,export導(dǎo)出的是live bindings,再根據(jù)其他文章綜合判斷,應(yīng)該是引用的意思。即export導(dǎo)出的是引用。
- 模塊內(nèi)的值更新了之后,所有使用export導(dǎo)出值的地方都能使用最新值。
read-only:通過(guò)import在mdn上的解釋,import使用的是通過(guò)export導(dǎo)出的不可修改的引用。
strict-mode:被引入的模塊都會(huì)以嚴(yán)格模式運(yùn)行。
靜態(tài)引入、動(dòng)態(tài)引入
import x from
這種語(yǔ)法有syntactic rigid,需要編譯時(shí)置于頂部且無(wú)法做到動(dòng)態(tài)引入加載。如果需要?jiǎng)討B(tài)引入,則需要import ()
語(yǔ)法。有趣的是,在mdn上,前者分類到了 Statements & declarations, 后者分類到了 Expressions & operators。這倆是根據(jù)什么分類的呢?
true && import test from "./a.js"; // SyntaxError: import can only be used in import() or import.meta // 這里應(yīng)該是把import當(dāng)成了動(dòng)態(tài)引入而報(bào)錯(cuò)
示例:
// a.js const test = { a: 1 }; export default test; // 改動(dòng)模塊內(nèi)部的值 setTimeout(() => { test.a = 2; }, 1000); // index.js import test from './index.js' /* live bindings */ console.log(test) // {a:1} setTimeout(()=>{ console.log(test) // {a:2} }, 2000) /* read-only */ test= { a: 3 } // 報(bào)錯(cuò), Error: "test" is read-only. /* syntactically rigid */ if(true){ import test from './index.js' // 報(bào)錯(cuò), SyntaxError: 'import' and 'export' may only appear at the top level }
commonJS
導(dǎo)出
在 Node.js 模塊系統(tǒng)中,每個(gè)文件都被視為獨(dú)立的模塊。模塊導(dǎo)入導(dǎo)出實(shí)際是由nodejs的模塊封裝器實(shí)現(xiàn),通過(guò)為module.exports
分配新的值來(lái)實(shí)現(xiàn)導(dǎo)出具體內(nèi)容。
module.exports
有個(gè)簡(jiǎn)寫變量exports
,其實(shí)就是個(gè)引用復(fù)制。exports作用域只限于模塊文件內(nèi)部。 原理類似于:
// nodejs內(nèi)部 exports = module.exports console.log(exports, module.exports) // {}, {} console.log(exports === module.exports) // true
注意:nodejs實(shí)際導(dǎo)出的是module.exports,以下幾種經(jīng)典case單獨(dú)看一下:
case1:
// ?使用exports exports.a = xxx console.log(exports === module.exports) // true // ?等價(jià)于 module.exports.a = xxx
case2:
// ?這么寫可以導(dǎo)出,最終導(dǎo)出的是{a:'1'} module.exports = {a:'1'} console.log(exports, module.exports) // {}, {a:'1'} console.log(exports === module.exports) // false // ?不會(huì)將{a:'1'}導(dǎo)出,最終導(dǎo)出的是{} exports = {a:'1'} console.log(exports, module.exports) // {a:'1'}, {} console.log(exports === module.exports) // false
引入
通過(guò)require語(yǔ)法引入:
// a是test.js里module.exports導(dǎo)出的部分 const a = require('./test.js')
原理偽代碼:
function require(/* ... */) { const module = { exports: {} }; ((module, exports) => { // Module code here. In this example, define a function. function someFunc() {} exports = someFunc; // At this point, exports is no longer a shortcut to module.exports, and // this module will still export an empty default object. module.exports = someFunc; // At this point, the module will now export someFunc, instead of the // default object. })(module, module.exports); return module.exports; }
特點(diǎn)
值拷貝
// test.js let test = {a:'1'} setTimeout(()=>{ test = {a:'2'} },1000) module.exports = test // index.js const test1 = require('./test.js') console.log(test1) // {a:1} setTimeout(()=>{ console.log(test1) // {a:1} },2000)
ES Module和 commonJS區(qū)別
語(yǔ)法:
exports
、module.exports
和require
是Node.js模塊系統(tǒng)關(guān)鍵字。
export
、export default
和import
則是ES6模塊系統(tǒng)的關(guān)鍵字:
原理:
exports
、module.exports
導(dǎo)出的模塊為值復(fù)制。
export
、export default
為引用復(fù)制。
時(shí)機(jī):
ES Module靜態(tài)加載是編譯時(shí)確定,ES Module動(dòng)態(tài)加載是運(yùn)行時(shí)確定。
CommonJS是運(yùn)行時(shí)確定。
到此這篇關(guān)于JS中ESModule和commonjs介紹及使用區(qū)別的文章就介紹到這了,更多相關(guān)JS ESModule和commonjs 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)自動(dòng)變換表格邊框顏色
用JavaScript控制表格邊框不停的變換顏色,記得以前經(jīng)??吹竭@種效果,代碼也不復(fù)雜,直接復(fù)制就可用啦! 可自定義顏色,有需要的小伙伴可以參考下。2015-05-05原生JS封裝_new函數(shù)實(shí)現(xiàn)new關(guān)鍵字的功能
這篇文章主要介紹了原生JS封裝_new函數(shù),實(shí)現(xiàn)new關(guān)鍵字的功能 ,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-08-08JS函數(shù)修改html的元素內(nèi)容,及修改屬性內(nèi)容的方法
下面小編就為大家?guī)?lái)一篇JS函數(shù)修改html的元素內(nèi)容,及修改屬性內(nèi)容的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10網(wǎng)頁(yè)自動(dòng)刷新,不產(chǎn)生嗒嗒聲的一個(gè)解決方法
網(wǎng)頁(yè)自動(dòng)刷新,不產(chǎn)生嗒嗒聲的一個(gè)解決方法...2007-03-03