3.Node 加载
Node 对 ES6 模块的处理比较麻烦,因为它有自己的 CommonJS 模块格式,与 ES6 模块格式是不兼容的。目前的解决方案是,将两者分开,ES6 模块和 CommonJS 采用各自的加载方案
3.1在静态分析阶段,一个模块脚本只要有一行import或export语句,Node 就会认为该脚本为 ES6 模块,否则就为 CommonJS 模块。如果不输出任何接口,但是希望被 Node 认为是 ES6 模块,可以在脚本中加一行语句
上面的命令并不是输出一个空对象,而是不输出任何接口的 ES6 标准写法
3.2import 命令加载 CommonJS 模块
Node 采用 CommonJS 模块格式,模块的输出都定义在module.exports这个属性上面。在 Node 环境中,使用import命令加载 CommonJS 模块,Node 会自动将module.exports属性,当作模块的默认输出,即等同于export default
import命令加载上面的模块,module.exports会被视为默认输出
如果采用整体输入的写法(import * as xxx from someModule),default会取代module.exports,作为输入的接口直接赋予在对象上成为属性**
上面代码中需要注意的是,整体的输出,Node 会自动为baz添加default属性,通过baz.default才能拿到module.exports
bar本身是一个对象,不能当作函数调用,只能通过bar.default调用
CommonJS 模块的输出缓存机制,在 ES6 加载方式下依然有效
即,CommonJS输出缓存的机制导致即使通过import加载了foo.js文件,得到的结果依然是缓存里的123
由于 ES6 模块是编译时通过export确定输出接口,而CommonJS 模块是运行时确定输出接口,所以采用import命令加载 CommonJS 模块时,不允许采用下面的写法(不要添加大括号,因为等价于输出的是export default)
上面的写法不正确,因为fs的书写是 CommonJS 格式的,只有在运行时才能确定readfile接口,而import命令要求编译时就确定这个接口。解决方法就是改为整体输入
这里的’express’就没有出现大括号的形式
3.3require 命令加载 ES6 模块
采用require命令加载 ES6 模块时,ES6 模块的所有输出接口,会成为输入对象的属性
上面代码中,ES6模块的default接口变成了通过require产生的es_namespace.default对象的属性。另外,由于CommonJS的输出缓存机制,所以es.js在已经输出foo后再对foo的重新赋值没有在模块外部反映出来