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