Node.js模块系统详解:exports、module.exports与ES6 export机制解析

作者:夜航船

时间:2026-10-22

浏览:303

本文深入解析Node.js中CommonJS规范的exports与module.exports机制,阐明二者指向同一内存对象的关系及导出差异。同时对比ES6模块系统,详细区分export与export default在数量、语法及导入方式上的不同,通过代码示例展示如何正确导出常量、函数及默认值,帮助开发者理清模块加载逻辑。

文章目录

Node.js模块系统详解:exports、module.exports与ES6 export机制解析

前言

近期难得有空闲时间,我决定重新系统地学习Node.js编程。在研究模块引入时,我发现Node.js中常用require方式,这让人联想到ES6标准中的各种export和export default语法。

面对这些概念,确实容易让人感到困惑和头疼。

理清这些概念后,我们需要先明确它们各自适用的范围。

  • require:Node.js环境和ES6环境均支持的引入方式
  • export / import:仅ES6标准支持的导出与引入机制
  • module.exports / exports:仅Node.js环境支持的导出方式

为了不再混淆,有必要彻底厘清它们之间的关系。接下来我们将深入探讨具体实现。

Node模块机制:CommonJS规范与exports关系

Node模块机制

Node.js内部的模块系统遵循CommonJS规范。

那么,什么是CommonJS规范呢?

早期JavaScript代码缺乏统一的模块概念,导致代码混乱。CommonJS规范的出台正是为了解决这一问题,对模块进行了明确定义。

CommonJS规范将模块划分为三个核心部分:模块标识(module)、模块定义(exports)以及模块引用(require)。

首先解释exports和module.exports的关系。

当Node.js执行一个文件时,会在该文件内部生成exports和module两个对象。

其中,module对象包含一个exports属性。它们之间的关系如图所示,两者最初指向同一块内存区域。


exports = module.exports = {};

Node.js模块系统详解:exports、module.exports与ES6 export机制解析

接下来我们通过代码来验证这一机制。


//utils.js
let a = 100;

console.log(module.exports); //能打印出结果为:{}
console.log(exports); //能打印出结果为:{}

exports.a = 200; //这里辛苦劳作帮 module.exports 的内容给改成 {a : 200}

exports = '指向其他内存区'; //这里把exports的指向指走

//test.js

var a = require('/utils');
console.log(a) // 打印为 {a : 200} 

从上述分析可以看出,require导出的内容实际上是module.exports所指向的内存块内容,而非exports本身。

简而言之,exports只是module.exports的一个引用,用于辅助后者添加内容。

用通俗的话讲,exports仅辅助module.exports操作内存中的数据。尽管对exports进行了各种赋值操作,最终被require导出的内容依然取决于module.exports的指向。

只要理解内存块的概念,就能清晰掌握这一机制。

为了避免混淆,建议尽量统一使用module.exports进行导出,并使用require进行导入。

ES模块的导出与导入:export与export default区别

ES模块的导出与导入

说实话,ES6中的模块系统相对清晰,但仍有一些细节需要注意。

例如export和export default的区别,以及导入时的语法差异,如import a from ...与import {a} from ...。这些细节容易让人困惑,下面我们将逐一厘清。

export与export default的区别

首先讲解这两种导出方式,并阐述它们的具体区别。

  • export和export default均可用于导出常量、函数、文件或模块。
  • 在一个文件或模块中,export和import可以有多个,但export default仅允许有一个。
  • 通过export方式导出时,导入时必须使用大括号{}包裹;而使用export default导出时,则不需要大括号。
  • export可以直接导出变量表达式,而export default不支持直接导出变量表达式。

接下来我们通过代码来验证这些结论。

testEs6Export.js


'use strict'
//导出变量
export const a = '100'; 

 //导出方法
export const dogSay = function(){ 
 console.log('wang wang');
}

 //导出方法第二种
function catSay(){
 console.log('miao miao'); 
}
export { catSay };

//export default导出
const m = 100;
export default m; 
//export defult const m = 100;// 这里不能写这种格式。

index.js


//index.js
'use strict'
var express = require('express');
var router = express.Router();

import { dogSay, catSay } from './testEs6Export'; //导出了 export 方法 
import m from './testEs6Export'; //导出了 export default 

import * as testModule from './testEs6Export'; //as 集合成对象导出



/* GET home page. */
router.get('/', function(req, res, next) {
 dogSay();
 catSay();
 console.log(m);
 testModule.dogSay();
 console.log(testModule.m); // undefined , 因为 as 导出是 把 零散的 export 聚集在一起作为一个对象,而export default 是导出为 default属性。
 console.log(testModule.default); // 100
 res.send('恭喜你,成功验证');
});

module.exports = router;

从上述代码可以看出,ES6的模块系统确实非常灵活。

代码地址

GitHub仓库:https://github.com/XuXiaoGH/exportImportTest

本地下载:http://xiazai.jb51.net/201710/yuanma/exportImportTest(jb51.net).rar

参考文献

1.老树新芽,在ES6下使用Express

2.exports 和 module.exports 的区别 3.module.exports与exports,export与export default之间的关系

3.module.exports与exports,export与export default之间的关系

感谢这三位前辈的分享。

总结

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章