require
: node 和 es6 都支持的引入export / import
: 只有 es6 支持的导出引入module.exports / exports
: 只有 node 支持的导出
CommonJS
Node
里面的模块系统遵循的是 CommonJS
规范。
CommonJS
定义的模块分为: 模块标识 (module
)、模块定义 (exports
) 、模块引用 (require
)。
在一个node执行一个文件时,会给这个文件内生成一个 exports
和 module
对象,而 module
又有一个exports
属性。
它们俩个的关系如下:
1 | exports = module.exports = {}; |
上面的代码等价于:
1 | module.exports = {...} |
require
导入的内容是 module.exports
指向的内存块内容,并不是 exports
的。简而言之,区分他们之间的区别就是 exports
只是 module.exports
的引用,辅助后者添加内容用的。
然后呢,为了避免糊涂,尽量都用 module.exports
导出,然后用require
导入。
放一段代码:
1 | // a.js 中的代码 |
1 | // b.js 中的代码 |
上面的代码相当于:
1 | // 变量 a 相当于 module.exports,变量 b 相当于 exports,最后导出的还是 module.exports |
ES6模块化
普通导入导出
一个 export 和 多个 export 效果相同,只是写法不同,一个 export 的方式可以看作是简化版。
导入已命名的导出内容必须使用花括号。
多个 export
hello.mjs
1 | const ninja = "a" |
index.mjs
1 | import { message, sayHiToNinja} from './hello.mjs' |
一个 export
hello.mjs
1 | const ninja = "a" |
index.mjs
1 | import { message, sayHiToNinja} from './hello.mjs' |
默认导入导出
通常,我们不需要从模块中导出一组相关的标识符,只需要一个标识符来代表整个模块的导出。
在关键字export后面增加关键字default,指定模块的默认导出。在本例中,模块默认导出类Ninja。虽然指定了模块的默认导出,但是仍然可以导出其他标识符,如导出函数compareNinjas。
hello.mjs
1 | export default class Ninja { |
导入默认导出的内容,不需要使用花括号 {},可以任意指定名称。
index.mjs
1 | import ImportedNinja from './hello.mjs' |
index.mjs 中的 import 语句可以简化成下面:
1 | import ImportedNinja, { compareNinjas } from './hello.mjs' |
使用重命名
1 | export { sayHi as sayHello } |
1 | import { sayHello } from "./hello.mjs" |
1 | import { sayHello as greet } from "./hello.mjs" |
导出后修改
一般导出后就不再进行修改,但是如果修改了,那么对于普通导入导出和默认导入导出情况是不同的。
普通
hello.mjs
1 | let awesome = 100; |
index.mjs
1 | import { awesome } from './hello.mjs' |
默认
hello.mjs
1 | let awesome = 100; |
index.mjs
1 | import awesome from './hello.mjs' |