我们闲言少叙,直接开始来了解一下他们的多种区别,希望能帮到大家!
1. 语法差异
// CommonJS
// 导出
module.exports = {
hello: function() {},
name: 'value'
};
// 或
exports.hello = function() {};
exports.name = 'value';
// 导入
const { hello, name } = require('./module');
// 或
const module = require('./module');
// ES6 Module
// 导出
export function hello() {}
export const name = 'value';
// 或
export default {
hello: function() {},
name: 'value'
};
// 导入
import { hello, name } from './module';
// 或
import * as module from './module';
import module from './module'; // 默认导入
2. 加载时机
// CommonJS - 运行时加载
const data = require('./data.js');
if (condition) {
const dynamicModule = require('./dynamic.js');
}
// ES6 Module - 静态加载(编译时)
import data from './data.js'; // 必须在顶层
// if (condition) {
// import module from './module.js'; // ❌ 错误
// }
// ES6 动态导入
if (condition) {
import('./dynamic.js').then(module => {
// 使用 module
});
}
3. 值的拷贝 vs 引用
// CommonJS - 值的拷贝
// module.js
let counter = 0;
module.exports = {
counter: counter,
increment: function() {
counter++;
}
};
// main.js
const module = require('./module');
console.log(module.counter); // 0
module.increment();
console.log(module.counter); // 0(不会改变,因为是拷贝)
// ES6 Module - 值的引用
// module.js
export let counter = 0;
export function increment() {
counter++;
}
// main.js
import { counter, increment } from './module';
console.log(counter); // 0
increment();
console.log(counter); // 1(会改变,因为是引用)
4. 循环依赖处理
// CommonJS
// a.js
console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done =', b.done);
exports.done = true;
console.log('a done');
// b.js
console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done =', a.done);
exports.done = true;
console.log('b done');
// 输出:
// a starting
// b starting
// in b, a.done = false
// b done
// in a, b.done = true
// a done
// ES6 Module
// a.mjs
console.log('a starting');
export let done = false;
import { done as bDone } from './b.mjs';
console.log('in a, b.done =', bDone);
done = true;
console.log('a done');
// b.mjs
console.log('b starting');
export let done = false;
import { done as aDone } from './a.mjs';
console.log('in b, a.done =', aDone);
done = true;
console.log('b done');
5. 异步加载
// CommonJS
// 同步加载
const fs = require('fs');
const data = fs.readFileSync('file.txt');
// ES6 Module
// 支持异步加载
const loadModule = async () => {
const module = await import('./dynamic-module.js');
module.doSomething();
};
6. 主要区别总结:
1.语法差异
// CommonJS
const module = require('./module');
module.exports = { /* ... */ };
// ES6 Module
import module from './module';
export default { /* ... */ };
2.加载机制
// CommonJS - 运行时加载
const dynamic = condition ? require('./a') : require('./b');
// ES6 Module - 静态加载
import module from './module'; // 必须在顶层
3.值的处理
// CommonJS - 值的拷贝
exports.counter = 0;
exports.increment = () => exports.counter++;
// ES6 Module - 值的引用
export let counter = 0;
export const increment = () => counter++;
4.模块对象
// CommonJS
module.exports = {
// 导出对象
};
// ES6 Module
export {
// 导出绑定
};
5.this 指向
// CommonJS
console.log(this); // {} (模块对象)
// ES6 Module
console.log(this); // undefined
6.文件扩展名
// CommonJS
require('./module'); // 可以省略 .js
// ES6 Module
import './module.js'; // 必须带扩展名
现代项目通常推荐使用 ES6 Module,因为它提供了更好的静态分析能力和树摇(tree-shaking)支持。希望大家看完这篇文章之后会对CommonJS和ES6 Module有一个新的理解,建议大家收藏且反复观看!