5月27日 01:16

module.exports 和 exports 的区别是什么?export 和 export default 的区别是什么?

两对概念,一个在 CommonJS,一个在 ESModule。

module.exports vs exports(CommonJS)

  • module.exports 是真正的导出对象。exports 只是 module.exports 的引用(const exports = module.exports
  • exports 赋新值会断开引用,导出失败;module.exports 赋新值可以
  • 安全做法:只添加属性用 exports.foo = bar,需要替换整个导出用 module.exports = foo
javascript
// 正确 module.exports = { a: 1 }; exports.b = 2; // 错误 — exports 被重新赋值,断开引用 exports = { a: 1 }; // module.exports 还是 {}

export vs export default(ESModule)

  • export 是命名导出,可以有多个。导入时用 { name } 且名字必须匹配
  • export default 是默认导出,每个模块只有一个。导入时可以取任意名字
  • 一个模块可以同时有命名导出和默认导出
javascript
// 导入区别 import { foo } from './a'; // 命名导出 import foo from './a'; // 默认导出 import foo, { bar } from './a'; // 两者都有

追问

为什么 export default 导入可以随意命名?

因为默认导出本质上导出的是 { default: value } 这个特殊 key。import x from 就是取 default key 的值。因此也叫 default import。

项目中应该优先用命名导出还是默认导出?

命名导出更好——IDE 自动补全、refactor 改名时更安全、Tree-Shaking 友好。默认导出适合"这个模块只有一个主要导出"(如一个组件、一个工具函数)。但争议是社区级的,没有绝对的优劣。

标签:前端ES6