esmodule 和 commonjs到底有什么区别
我要说的,就算不知道两者之间的区别,你在写node和浏览器里面的编程时,也不会导致多大的问题,网络上吹毛求疵的说法太过夸张了。
在网上搜了一圈,很多文章抄袭于阮老师的总结:https://es6.ruanyifeng.com/#docs/module-loader, 没有提出自己的见解。
阮老师的科普文章写的很好,这篇基本也提炼出表象,但是对于总结出的三点区别,我个人理解起来还是容易混淆不够透彻,所以我基于这部分又作了深入的挖掘,花了点时间读取规范才终于彻底搞明白了:
https://tc39.es/ecma262/#sec-ecmascript-language-scripts-and-modules
最根本的区别
来自于两点:
一是esm
是为浏览器的加载环境设计的,考虑到网络的延迟,不可以等到模块彻底解析完成(同步)再去加载索引加载其他的模块,所以会以最快的速度建立出树形的map,再去解析装载具体的内容,这用异步去解释也能解释的通,但是它实际的过程就是这个过程,跟异步什么的关联不大。
二是esm
的import
的实际就是export
出的值,它们使用的是同一个空间(内存)。而common js
require的是module.exports
的值, 返回的实际就是这个module.exports,只是因为获取的语法是var xx = require('...')
,这只是导出的方式有细微的区别。本质是可以理解的。这是语法上的差异。
下图可以说明这种语法的本质:
所以可以说,commonsjs
中require("...")
返回的也是值的本身,只不过我们使用一个变量声明赋值的语法来获取这个值而已。
所以当你直接修改require
返回的值,也可以起到一样的效果:
//counter.js
var num = 0;
function increment() {
num += 1;
}
module.exports = {
num,
increment
}
// index.js
require('./counter').num +=2
var counter = require('./counter');
console.log(counter.num);
输出:
2