xxleyi / learning_list

聚集自己的学习笔记
10 stars 3 forks source link

Module in JS #246

Open xxleyi opened 3 years ago

xxleyi commented 3 years ago

JS 中有多种模块化方式

掌握两种就差不多了,分别是 es6 中引入的 module,Node.js 中使用的 commonJS 格式。

两种模块化方式背后的实现很不一样,在表现上的话,大部分时候都表现一致,有一个微妙的区别。由于 node14.4 之后正式引入了 es6 模块化,后缀用 .mjs。下面是我自己的小实验,新建两个文件,内容很简单,但结果上能表明一个有趣的事实:es6 import 的是变量,而非值。require 那种方式导入的是值,而非变量。这也很正常,因为 require 自身就是一个函数。反观 es6 的模块设计,即便是动态 import() 也并非函数。

这个差异在大部分时候都无需在意,也感受不到,但某些情况下,可能会显现出来。

// a.mjs
let a = 4

function log() { console.log(a) }
function change(v) { a = v }

export {a, change, log}
// b.mjs
import {a, change, log} from './a.mjs'
log()
change(333)
log()
console.log(a)
// node14.6.0
node b.mjs
// output
4
333
333

而函数传参在 JS 中始终是传值。

当动态 import 和 函数传参一起出现时,会产生一种更为微妙的情况:

// c.mjs
import('./a.mjs').then((m)=> {
  m.log()
  m.change(333)
  m.log()
  console.log(m.a)
})
// node14.6.0
node c.mjs
// output
4
333
333
// d.mjs
import('./a.mjs').then(({log, change, a})=> {
  log()
  change(333)
  log()
  console.log(a)
})
// node14.6.0
node d.mjs
// output
4
333
4