深度保持探索全栈开发的无限可能
记录技术成长的每一步
exports、module.exports、export、export default 的区别?

exports、module.exports

这俩是 nodejs 中的,nodejs 里面的模块系统遵循的是 CommonJS 规范。

CommonJS定义的模块分为:

1、模块标识(module)

2、模块定义(exports)

3、模块引用(require)

node 执行一个 js 文件时,会给这个文件内自动生成一个 exports 和 module 对象。

- -
------------ 
- -
    -
        -
        - -
        -
    -
-

-------------
- -
    -
-

而 module 又有一个 exports 属性。他和 exports 都指向一块 {} 内存区域。

- -
-------------- - -
------------- - -
----------- - ---------- - -
----------- - ---------- - -

当修改 exports 指向,和 module.exports 内容后,如果整体导入使用,都是 module.exports 的指向的内存块内容,而不是 exports 的内容

- -
-------- - -
    -- -
-
------- - -

- -
- - - -
---------- - -
- ------ - -----
----------- - -

exports 只是 module.exports 的引用,exports 是辅助 module.exports 操作内存中的数据用的,结果到最后真正被import、require出去的内容还是module.exports的。使用时,尽量都用 module.exports 导出,然后用 require 导入

 

export、export default

这俩是 ES 中的

区别如下

1、export 与 export default 均可用于导出常量、函数、文件、模块等

2、在一个文件或模块中,export、import 一个文件可以有多个,export default 一个文件仅有一个

-
 - - -
 -

- - - 
- - - - --
- - - - --

- - - 
- - -- - - - -
------ -- - - -
-
 - - - -
 -

- - - 
- - - --
- - -
- - - --
- - - - -

3、通过 export 方式导出,在导入时要加{ },export default 则不需要

-
 - - -
 -

- - - 
- - - - --


- - - 
- - -
- - - - - -
------ - -

- - - -
- - - -
---------- - -
-
 - - - -
 -

- - - 
- - - --
- - -


- - - 
- - - -
- - - - - -
------ - -

- -
- - - -
---------- - -

4、export 能直接导出变量表达式,export default 不行。

-- --
------ ----- - - --
-- --
------ ------- ----- - - --

 

ES 模块和 CommonJS 的差异点

1、CommonJS 可以在运行时使用变量进行 require, 例如 require(path.join('xxxx', 'xxx.js')),CommonJS 模块是运行时加载,而静态 import 语法(还有动态 import,返回 Promise)不行,因为 ES 模块是编译时输出接口, 模块会先解析所有模块再执行代码。

2、require 会将完整的 exports 对象引入,CommonJS 输出的是一个值的拷贝,import 可以只 import 部分必要的内容,ES 模块输出的是值的引用,这也是为什么使用 Tree Shaking 时必须使用 ES 模块 的写法。

3、import 另一个模块没有 export 的变量,在代码执行前就会报错,而 CommonJS 是在模块运行时才报错。

4、因为 CommonJS 的 require 语法是同步的,所以就导致了 CommonJS 模块规范只适合用在服务端,而 ES 模块无论是在浏览器端还是服务端都是可以使用的,但是在服务端中,还需要遵循一些特殊的规则才能使用;

5、因为两个模块加载机制的不同,所以在对待循环加载的时候,它们会有不同的表现。CommonJS 遇到循环依赖的时候,只会输出已经执行的部分,后续的输出或者变化,是不会影响已经输出的变量。而ES6模块相反,使用 import 加载一个变量,变量不会被缓存,真正取值的时候就能取到最终的值;

6、关于模块顶层的 this 指向问题,在 CommonJS 顶层,this 指向当前模块;而在 ES 模块中,this 指向 undefined;

7、关于两个模块互相引用的问题,在 ES 模块当中,是支持加载 CommonJS 模块的。但是反过来,CommonJS 并不能 requireES6 模块,在 NodeJS 中,两种模块方案是分开处理的。

 

为什么平时开发可以混写?

ES 模块和 CommonJS 模块有很大差异,不能直接混着写。这和开发中表现是不一样的,原因是开发中写的 ES 模块最终都会被打包工具处理成 CommonJS 模块,以便兼容更多环境,同时也能和当前社区普通的 CommonJS 模块融合。