面试官:请说说ES Module和CommonJS除了语法上的区别?

32 阅读2分钟

作为前端工程师,模块化开发已经成为必备技能。今天我们就来深入探讨ES Module和CommonJS这两种主流模块系统的核心差异,助你在技术面试中从容应对这个经典问题。

1. 语法差异

ES6 Module

// 导出
export const name = 'ES6 Module';
export function sayHello() {
    console.log('Hello from ES6 Module');
}

// 默认导出
export default function() {
    console.log('Default export');
}

// 导入
import { name, sayHello } from './module.js';
import defaultFunction from './module.js';

CommonJS

两种常见的CommonJS导出方式

// 方式1:直接使用exports对象
exports.name = 'CommonJS';
exports.sayHello = function() { /*...*/ };

// 方式2:使用module.exports整体导出
let name = 'CommonJS';
function sayHello () { /*...*/ }
module.exports = {
    name,
    sayHello,
};

// 导入
const { name, sayHello } = require('./module.js');

2. 主要区别

2.1 加载时机

  • ES6 Module: 静态加载,编译时就确定模块的依赖关系
  • CommonJS: 动态加载,运行时才能确定模块的依赖关系

2.2 导入导出差异

  • ES6 Module:
    • 支持静态分析
    • 可以只导入需要的部分(tree-shaking)
    • 导出的是值的引用
  • CommonJS:
    • 无法进行静态分析
    • 整体加载模块
    • 导出值的拷贝

3. 值拷贝vs引用的区别

让我们通过一个例子来理解理解:

ES6 Module(引用)

// counter.js
export let count = 0;
export function increment() {
    count++;
}
export function getCount() {
    return count;
}

// main.js
import { count, increment, getCount } from './counter.js';

console.log(count);     // 输出: 0
increment();
console.log(count);     // 输出: 1
console.log(getCount()); // 输出: 1

// 注意:ES6 Module导出的是值的引用
// 当模块内部的值发生变化时,外部能够实时反映这个变化

CommonJS(值拷贝)

// counter.js
exports.count = 0;
exports.increment = function() {
    exports.count++;
}
exports.getCount = function() {
    return exports.count;
}

// main.js
const { count, increment, getCount } = require('./counter');

console.log(count);     // 输出: 0
increment();
console.log(count);     // 输出: 0 (注意:这里还是0!因为count是一个拷贝)
console.log(getCount()); // 输出: 1 (通过函数调用可以获取到最新值)

// 注意:CommonJS导出的是值的拷贝
// count变量在导出时就已经被拷贝,之后模块内部的变化不会影响到这个拷贝
// 但是getCount()函数每次调用都会返回最新的值

总结

通过上述对比,ES Module和CommonJS的核心差异可以总结为:语法层面 - ES Module使用import/export,CommonJS使用require/exports;加载机制上 - ES Module是静态分析,编译时加载,而CommonJS是动态加载;数据处理上 - ES Module输出值的引用,CommonJS输出值的拷贝;使用场景上 - ES Module更适合现代前端项目,CommonJS主要用于Node.js环境。

如果您觉得这篇文章有帮助,欢迎点赞转发!如有疑问,也欢迎在评论区交流讨论。