JavaScript 在ES6之前没有给出官方模块的定义,因此社区自己搞了两个模块加载方案:
- CommonJS (node)
- AMD (browser) 本文略
CommonJS规范
module定义:
每个文件就是一个模块,文件有自己的私有内部作用域。module
对象代表当前模块,module.exports
是对外暴露的接口。加载模块,实际上是加载 module.exports
.
exports
是 module.exports
的引用,其实质是 node 提供的语法糖, 本质类似于每个模块开头都include了下面的代码。
如修改exports
对象的属性,等价于修改了module.exports
。虽然这样提供了方便,但是直接改变exports
对象的指向是个不好的实践。
引入的时候,require
导入的是 module.exports
指向的一个对象。
ES6 规范
export命令
export
命令定义了模块的输出、其值可以是 value,variable、function、class,
import命令
import
大括号内的变量名必须与export
一致。(在webstrom等IDE中会帮你静态检查的)
module命令
module 是个语法糖。有时候,需要import所有的接口
可以写成
export default 命令
export default命令定义了模块导出的默认值,引入默认值时不用加大括号。这个命令其实也是语法糖:
把导出值封装到了一个default
对象,再在引入时解构这个default
对象。因为有一个对象来承接中间的值,所以在import
时可以用任意key
指定被引入的值
Babel
在ES6出来之前社区上已经有许多CommonJS的module,托Babel的福,可以直接使用ES6的新语法来引入这些只支持CommonJS标准的库。
Babel 做了一层翻译,把ES6的import、export语法变成了兼容CommonJS规范的require、exports。
1. export babel翻译:
上面可以看到export default 和普通的export foo一样,都是给exports对象添加属性。
2. import babel翻译:
==========>
export default 和 import 的使用要结合一起看:
上面的export default翻译为了exports.default
;
import命令则要先判断:对经过了 babel 翻译后export的module直接返回对象,否则先用对象包装一层,并把export值赋值给default
属性;最终在代码中使用时,统一使用moduleName.default
引用。
普通的非default import语法就简单了,和require一模一样,导入时需要添加{}
===========>
参考