为什么ES模块比CommonJS更好?

2022-10-28 11:23:54 浏览数 (1)

ES6 模块与 CommonJS 模块的差异

1.CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。2.CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。请看下面这个模块文件lib.js的例子。

代码语言:javascript复制
// lib.js	
var counter = 3;	
function incCounter() {	
counter  ;	
}	
module.exports = {	
counter: counter,	
incCounter: incCounter,	
};

上面代码输出内部变量counter和改写这个变量的内部方法incCounter。然后,在main.js里面加载这个模块。

代码语言:javascript复制
// main.js	
var mod = require('./lib');	
	
console.log(mod.counter);  // 3	
mod.incCounter();	
console.log(mod.counter); // 3

上面代码说明,lib.js模块加载以后,它的内部变化就影响不到输出的mod.counter了。这是因为mod.counter是一个原始类型的值,会被缓存。除非写成一个函数,才能得到内部变动后的值。

ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。

换句话说,ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块(动态绑定)。

第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

代码语言:javascript复制
// 不能这样写	
const flag = true	
if (flag) {	
import $ from 'jquery'	
}	
// 但是可以这样写	
if (flag) {	
const $ = require('jquery')	
}

为什么ES模块比CommonJS更好?

ES模块是官方标准,也是JavaScript语言明确的发展方向,而CommonJS模块是一种特殊的传统格式,在ES模块被提出之前做为暂时的解决方案。ES模块允许进行静态分析,从而实现像 tree-shaking 的优化,并提供诸如循环引用和动态绑定等高级功能。

什么是 ‘tree-shaking’?

Tree-shaking, 也被称为 "live code inclusion," 它是清除实际上并没有在给定项目中使用的代码的过程,但是它可以更加高效。

0 人点赞