requireimportDynamicevaluationStaticevaluationRerunandreportanerrorReparseandreporterror不是关键字而是关键字SyntaxCommonJsmodule.exports={foo:function(){},bar:'a'}app.jsvardep=require('dep')console.log(dep.bar)dep.foo()ESMdep.jsexportfoofunction(){}exportconstbar='a'app.jsimport{foo,bar}from'dep'console.log(bar)foo()不同的加载方式当使用require时,模块的代码实际上会被打包成如下代码:function(exports,require,module,__filename,__dirname){constm=1;module.exports.m=m;}那么在执行这个方法的时候,我们可以传入:constmodule={exports:{}}constrequire=function(){/*...一些模块加载代码在这里*/}//__filename,__dirname是require提供的路径解析。fun(module.exports,require,module,__filename,__dirname)执行完后,可以通过module变量抛出方法。所以我们可以看出,module、require、exports并不是全局变量,而是专门用于本模块的局部变量。require时真正要做的事情如下:Resolution/ParsingPathLoading/LoadingCodeWrapping/PackagingEvaluation/EvaluationExecutionCaching/Caching只是简单的根据调用require时传入的路径。首先要获取到真正的绝对路径(是Relative目录,或者node_modules下等),然后读入代码,如上所示打包,然后传递给vm求值执行,得到结果,以及最后缓存它。因此,在执行模块代码之前,node并不知道模块输出了什么。这也是与ESM最大的区别,因为ESM是基于关键字进行模块化的,在解析过程中就可以知道导出。什么。在解析ESM模块时,在将代码传递给VM执行之前,可以得到一个名为ModuleRecord的内部结构,它保存了模块内容的列表。当你import{f}fromf时,他其实是在你引用的地方和f被倒出的地方建立了联系,也就是指向了同一个内存。即使是原始数据类型,如果在模块中修改了指针,也会引起引用处的变化。你是什??么意思?//dep.jsexportleta=1setTimeout(()=>a+=1,500)//app.jsimport{a}from'dep'setTimeout(function(){console.log(a)},1000)输出会是2,但是如果你用require,CommonJs模块,就会是1,因为CommonJs是普通的值传递或者引用传递。这是require和import最大的区别
