CommonJS、ES6 的 require 和 import 不同的傳遞方法

Jason Tseng
4 min readOct 13, 2020

--

開始之前建議先了解兩套方法的背景,以下來自別人文章的模組化開發的歷史發展:
https://blog.niclin.tw/2019/10/03/nodejs-require-vs-es6-import-export/
https://zhuanlan.zhihu.com/p/121770261

import 是編譯中執行,CommonJS 的 require 是同步加載

以下為我做出詳細的 8 種比較 import, export, module.exports, require 兩種輸入、兩種輸出,並在中間穿插延遲賦值,交叉結果如下:

// import.js
let imp = 'imp1';
export { imp };
imp = 'imp2';
window.setTimeout(() => {
imp = 'imp3';
}, 1000);
// require.js
let req = 'req1';
module.exports = { req }; // req 1
req = 'req2';
// module.exports = { req }; // req 2

window.setTimeout(() => {
req = 'req3';
module.exports = { req };
}, 1000);
// compare.js
import
{ imp as impImp } from './import';
import { req as reqImp } from './require';

const { imp: impReq } = require('./import');
const { req: reqReq } = require('./require');

console.log('result', impImp, reqImp, impReq, reqReq);

window.setTimeout(async () => {
const { imp: delayImpImp } = await import('./import');
const { req: delayReqImp } = await import('./require');
const { imp: delayImpReq } = require('./import');
const { req: delayReqReq } = require('./require');

console.log('result after running new assign', impImp, reqImp, impReq, reqReq, delayImpImp, delayReqImp, delayImpReq, delayReqReq);
}, 1100);

兩次印出的結果分別是

result imp2 req1 imp2 req1
result after running new assign imp3 req1 imp2 req1 imp3 req3 imp3 req3

如果將 require.js 的 module.exports = { req }; 給註解掉,第二行會是

result after running new assign imp3 req1 imp3 req1 imp3 req1 imp3 req1

可以得到:只要是 CommonJS 的 exports/require 系列,均是立即在當下給予值,實現同步加載,當下的值是什麼就是什麼不會因為後面改變不同的 value 而有所變化;而 import/export 是取址(reference)處理,所以馬上就得到 imp 是 imp2 的結果而不是imp1;所以在操作 import/export 要特別留意他是傳址,後續改變變數的行為可能會導致認知之外的結果。

而 dynamic import 結果同 require,會當作同步加載,當下取值(value)是什麼就是什麼。

import 取址(reference),require、dynamic import 取值(value)

那麼最後考考你,如果 import.js 和 require.js 都是包物件的話,輸出會是什麼?

// import.js
const imp = { foo: 'imp1' };
export { imp };
imp.foo = 'imp2';
window.setTimeout(() => {
imp.foo = 'imp3';
}, 1000);
// require.js
const req = { foo: 'req1' };
module.exports = { req }; // req 1
req.foo = 'req2';

window.setTimeout(() => {
req.foo = 'req3';
}, 1000);

--

--