Commonjs 和 ES Module的区别

74 阅读2分钟

《用得上的前端知识》系列 - 你我都很忙,能用100字说清楚,绝不写万字长文

CommonJS

CommonJS 是服务端的模块化规范,

  • 通过 exports 导出模块;
  • 通过 require 导入模块
    • 使用同步的方式加载模块;
    • 第一次加载某个模块时,Node 会缓存该模块。以后再加载该模块,则从缓存取出该模块的 module.exports 属性。
  • 在模块内,module 变量代表当前模块,其 exports 属性是对外的接口;
  • 加载某个模块,其实是加载该模块的 module.exports 属性

ES Module

ES Module 是 ES 规范中提出的模块化方案,意在统一客户端和服务端的模块化规范。

  • 通过 export 导出模块;
    • export default 就是输出一个叫做 default 的变量或方法;
    • export default 所以它后面不能跟变量声明语句。
  • 通过 import 导入模块;
    • import 命令输入的变量都是只读的;
    • import 命令具有提升效果;
    • import 是静态执行,所以不能使用表达式和变量;
    • 多次重复执行同一句 import 语句,那么只会执行一次,而不会执行多次。

区别

  • CommonJs 模块输出的是一个值的拷贝,ES Module 模块输出的是值的引用;
  • CommonJs 是单个值导出,ES Module 可以导出多个;
  • CommonJs 模块是动态语法,是在运行时加载的,所以 require 语句可以写在判断里;而 ES Module 是静态语法,在编译时输出接口,所以 import 语句只能写在顶层;
  • CommonJs 的 this 是当前模块,ES Module的 this 是 undefined。

测试

// index.js
console.log('running index.js');
import { sum } from './sum.js';
console.log(sum(1, 2));

// sum.js
console.log('running sum.js');
export const sum = (a, b) => a + b;

// 答案:running sum.js, running index.js, 3


// 题目二 --------------------------------
// base.js
let count = 0;
setTimeout(() => {
    console.log("base.count", ++count); // 1
}, 500)

module.exports.count = count;

// commonjs.js
const { count } = require('./base');
setTimeout(() => {
     console.log("count is" + count + 'in commonjs'); // 0
}, 1000)


// base1.js
let count = 0;
setTimeout(() => {
    console.log("base.count", ++count); // 1
}, 500)
exports const count = count;

// es6.js
import { count } from './base1';
setTimeout(() => {
     console.log("count is" + count + 'in es6'); // 1
}, 1000)

参考资料