前言
最近使用 node 和 vue 一起编程,想到 ES6 各种 export 、export
default。阿西吧,头都大了....
头大完了,那我们坐下先理理他们的使用范围。
1 2 3 4 5 require: node 支持的引入 module.exports / exports: 只有 node 支持的导出 export / import : 只有es6 支持的导出引入
这一刻起,我觉得是时候要把它们之间的关系都给捋清楚了,不然我得混乱死。话不多少,咱们开干!!
node模块
理解
Node里面的模块系统遵循的是 CommonJS 规范。
那问题又来了,什么是CommonJS规范呢?
由于js以前比较混乱,各写各的代码,没有一个模块的概念,而这个规范出来其实就是对模块的一个定义。
CommonJS定义的模块分为: 模块标识(module)、模块定义(exports)
、模块引用(require)
先解释 exports 和 module.exports
在一个 node 执行一个文件时,会给这个文件内生成一个 exports 和 module
对象, 而 module 又有一个 exports
属性。他们都指向一块{}内存区域,关系如下图。
1 exports = module .exports = {};
那下面我们来看看代码的吧。
1 2 3 4 5 6 7 8 9 10 11 let a = 100 ;console .log (module .exports ); console .log (exports ); exports .a = 200 ; exports .a = 100 ; exports = '指向其他内存区' ;
1 2 3 var a = require ('/utils' );console .log (a)
从上面可以看出,其实 require 导出的内容是 module.exports
的指向的内存块内容,并不是exports 的。
简而言之,区分他们之间的区别就是 exports 只是 module.exports
的引用,辅助后者添加内容用的。下面的摘抄nodejs官方的代码 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function require ( ) { const module = { exports : {} }; ((module , exports ) => { function someFunc ( ) {} exports = someFunc; module .exports = someFunc; })(module , module .exports ); return module .exports ; }
用白话讲就是,exports 只辅助 module.exports
操作内存中的数据,辛辛苦苦各种操作数据完,累得要死,结果到最后真正被
require 出去的内容还是 module.exports 的,真是好苦逼啊。
其实大家用内存块的概念去理解,就会很清楚了。
然后呢,为了避免糊涂,尽量都用 module.exports 导出,然后用 require
导入。
node 模块的导出方式
上面讲了 exports, module.exports 的区别
接下来总结一下使用 CommonJS 规范时,有哪些导出形式
导出函数
1 2 3 4 5 6 7 const getName = ( ) => { return 'Jim' ; }; exports .getName = getName;
1 2 3 4 const user = require ('./user' );console .log (`User: ${user.getName()} ` );
导出多个函数和值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const getName = ( ) => { return 'Jim' ; }; const getLocation = ( ) => { return 'Munich' ; }; const dateOfBirth = '12.01.1982' ;exports .getName = getName;exports .getLocation = getLocation;exports .dob = dateOfBirth;
1 2 3 4 5 6 const user = require ('./user' );console .log ( `${user.getName()} lives in ${user.getLocation()} and was born on ${user.dob} .` );
1 2 Jim lives in Munich and was born on 12.01 .1982 .
在导出的过程中,可以与原变量有不同的名字
语法变化
我们可以在文件的任何地方导出方法或者值:
1 2 3 4 5 6 7 8 9 exports .getName = () => { return 'Jim' ; }; exports .getLocation = () => { return 'Munich' ; }; exports .dob = '12.01.1982' ;
导出默认值
上面的方式是对函数和值进行分别导出,这种方式适合于帮助类。但当你只想导出一个对象的时候,可以使用
module.exports
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class User { constructor (name, age, email ) { this .name = name; this .age = age; this .email = email; } getUserStats ( ) { return ` Name: ${this .name} Age: ${this .age} Email: ${this .email} ` ; } } module .exports = User ;
ES6 中的模块导出导入
说实话,在 es
中的模块,就非常清晰了。不过也有一些细节的东西需要搞清楚。
比如 export 和 export default,还有 导入的时候,import a from ..,
import {a} from ..,总之也有点乱,那么下面我们就开始把它们捋清楚吧。
export 和 export default
首先我们讲这两个导出,下面我们讲讲它们的区别:
export 与 export default
均可用于导出常量、函数、文件、模块等
在一个文件或模块中,export、import 可以有多个,export default
仅有一个
通过 export 方式导出,在导入时要加{ name },export default
则不需要
export 导入时,只能使用定义时的名称,而 export default
导入时,可以是任意名称
export 能直接导出变量表达式,export default 不行
上面的两种方式,export 适合于一个模块中有 0 个或者多个 export
的情况;export default 则只能有一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 export let name1, name2, …, nameN; export let name1 = …, name2 = …, …, nameN; export function functionName ( ){...}export class ClassName {...}export { name1, name2, …, nameN };export { variable1 as name1, variable2 as name2, …, nameN };export const { name1, name2 : bar } = o;export default expression;export default function (… ) { … } export default function name1 (… ) { … } export { name1 as default , … };export * from …; export * as name1 from …; export { name1, name2, …, nameN } from …;export { import1 as name1, import2 as name2, …, nameN } from …;export { default } from …;
总结
在 node 中使用 module.exports exports 和 require
在 ES6 中使用 export export default 和 import
致谢
exports、module.exports
和 export、export default 到底是咋回事
Understanding
module.exports and exports in Node.js
MDN
export