CommonJS 规范中关于module.exports导出语法的四大类常用总结

CommonJS 全部导出语法汇总

CommonJS 本质只有唯一出口:module.exportsexports 只是它的初始引用别名,所有导出写法都是对这两个变量的操作变形,总共分为4 大类常用写法,附带原理、示例、优缺点,帮你彻底区分。

前置核心原理(必记)

每个 Node 模块初始化时默认执行:
var module = { exports: {} };
var exports = module.exports; // 引用赋值,指向同一个空对象
 
模块最终向外暴露的永远是 module.exports 的值,require() 获取的就是它;一旦重新赋值 module.exports = xxx,会切断和 exports 的引用关系

一、写法 1:挂载属性导出(命名批量导出,最常用)

1. exports.xxx = 值(简写版)

// utils.js
exports.add = (a, b) => a + b;
exports.del = (a, b) => a - b;
exports.str = '测试字符串';
 

2. module.exports.xxx = 值(完整版,你上一轮提问的写法)

module.exports.add = (a, b) => a + b;
module.exports.del = (a, b) => a - b;
 
  • 本质:给默认空导出对象追加属性,最终导出一个包含所有挂载属性的对象
  • 导入:支持解构 const {add} = require('./utils')
  • 适用:导出多个函数、变量、常量
  • 注意:不能后续重写 module.exports = 其他值,会覆盖所有挂载的属性

二、写法 2:直接重写 module.exports 整体导出(单值导出)

直接替换整个导出对象,抛弃默认的空对象,导出单个任意类型数据(函数、类、实例、数组、数字都可以)

导出单个函数

// calc.js
module.exports = function(a, b) { return a + b }
 

导出类 / 实例 / 数组 / 基本类型

// 导出类
module.exports = Person;
// 导出提前创建好的实例
module.exports = new Person('张三');
// 导出数组/字符串
module.exports = [1,2,3];
module.exports = 'hello';
 
  • 导入:const add = require('./calc') 直接拿到这个值,无法解构
  • 适用:模块只对外暴露一个核心功能(工具函数、单例实例、主类)

三、写法 3:一次性字面量对象批量导出(合并写法)

一次性给 module.exports 赋值一个对象字面量,批量定义多个导出成员
module.exports = {
  add: (a,b)=>a+b,
  del: (a,b)=>a-b,
  flag: true
}
 
  • 等价于写法 1 逐行挂载的最终效果,只是写法集中化
  • 导入:可解构 const {add, del} = require('./xxx')
  • 适用:提前规划好所有导出成员,统一编写

四、写法 4:混合组合导出(进阶混用,不推荐新手使用)

先通过 exports.xxx 挂载一部分属性,再整体重写 module.exports(会覆盖前面挂载内容)
// 先挂载(会失效)
exports.add = () => 1+1;
// 整体重写出口,上面的add直接丢失
module.exports = {
  del: () => 2-1
}
 
  • 坑点:重写 module.exports 后,exports 还指向原来的空对象,再写 exports.xxx 不会生效
  • 建议:项目中不要混用,要么全用挂载属性,要么直接整体导出

精简归类(总共 4 种语法,归类为 2 大逻辑)

  1. 追加属性模式(导出多个成员)
    • exports.xxx = xxx
    • module.exports.xxx = xxx
    • module.exports = { 键值对 }
  2. 整体替换模式(导出单个成员)
    • module.exports = 任意值(函数/类/实例/基础类型)

补充关键对比表

写法 导出结构 能否解构导入 最佳使用场景
exports.fn = xxx 对象包含多个方法 可以 工具类多个小函数
module.exports.fn = xxx 对象包含多个方法 可以 同上面,语义更完整
module.exports = {fn1,fn2} 自定义对象 可以 统一批量定义导出
module.exports = 单独函数/类/实例 单个值 不可以 模块只有一个核心功能

总结

语法书写形式有 4 种,但底层只有两种导出逻辑
  1. 不替换原始导出对象,往上面挂属性(多成员导出);
  2. 直接替换 module.exports 整个出口(单成员导出)。
     
    日常开发优先选:多方法用 exports.xxx,单核心功能用 module.exports = xxx,尽量不混用。
posted @ 2026-07-03 20:39  chenlight  阅读(2)  评论(0)    收藏  举报