完整高频题库仓库地址:https://github.com/hzfe/awesome-interview完整高频题库阅读地址:https://hzfe.github.io/awesome-采访/相关问题JavaScript的主要模块化规范有哪些?AMD和CMD有什么异同?什么是无害环境管理?什么是模块化?,出口出口内容。AMD[2]:主要用在浏览器端。通过define定义模块和依赖,require异步加载模块,尊重前置依赖。CMD[3]:与AMD类似,主要用在浏览器端。模块通过require异步加载,内容通过exports导出。建议就近就靠。UMD[4]:UniversalModuleSpecification,融合了CommonJS和AMD规范,跨平台解决方案。ESM[5]:官方模块化规范,现代浏览器原生支持,通过导入异步加载模块,导出内容。深入知识点1.为什么需要模块化和模块化规范模块化可以解决代码之间命名变量、函数、对象等的冲突/污染问题,良好的模块化设计可以减少代码之间的耦合关系,提高代码可维护性、可扩展性和可重用性。模块化规范的作用是规范JavaScript模块的定义和加载机制,统一导出和加载模块,降低学习和使用成本,提高开发效率。2.各种模块化规范详解2.1CommonJSCommonJS主要用于Node.js。模块通过require同步加载,exports导出内容。在CommonJS规范下,每个JS文件都是一个独立的模块,每个模块都有独立的作用域,模块中的局部变量都是私有的。示例//hzfe.jsconsthzfeMember=17;constgetHZFEMember=()=>{return`HZFEMember:${hzfeMember}`;};module.exports.getHZFEMember=getHZFEMember;//index.jsconsthzfe=require("./hzfe.js");console.log(hzfe.getHZFEMember());//HZFE会员:17个使用场景CommonJS主要用在服务端(如:Node.js),也可以在浏览器端使用打包工具进行打包。加载方式CommonJS同步加载模块。第一次加载会缓存结果,后续加载会直接读取缓存的结果。优缺点优点简单易用require模块在任意位置支持循环依赖缺点同步加载方式不适合浏览器端浏览器端使用需要打包难以支持模块静态分析2.2AMD(AsynchronousModuleDefinition)AMD,that是,异步模块定义。AMD定义了一套JavaScript模块依赖的异步加载标准来解决浏览器端模块加载的问题。AMD主要用在浏览器端。通过define定义模块和依赖,require异步加载模块,尊重前置依赖。AMD模块通过define函数定义在闭包中:/***define*@paramid模块名*@paramdependencies依赖列表*@paramfactory模块具体内容/具体实现*/define(id?:string,dependencies?:字符串[],工厂:函数|对象);示例//hzfe.jsdefine("hzfe",[],function(){consthzfeMember=17;constgetHZFEMember=()=>{return`HZFEMember:${hzfeMember}`;};return{getHZFEMember,};});//index.jsrequire(["hzfe"],function(hzfe){//前端依赖console.log(hzfe.getHZFEMember());//HZFEMember:17});场景AMD主要用于浏览器,通过符合AMD规范的JavaScript库(如RequireJs)加载模块。加载方式AMD异步加载模块,每加载一个模块,实际上是加载对应的JS文件。优缺点优点依赖异步加载,启动速度较快支持循环依赖支持插件缺点语法相对复杂依赖加载器难以支持模块静态分析具体实现RequireJs2.3CMD(CommonModuleDefinition)CMD,即common模块定义。CMD定义了一套JavaScript模块依赖异步加载标准,解决浏览器端模块加载问题。CMD主要用在浏览器端。通过define定义模块和依赖,使用require异步加载模块,推荐最接近的依赖。CMD模块通过define函数定义在闭包中:/***define*@paramid模块名*@paramdependencies依赖列表*@paramfactory模块具体内容/具体实现*/define(id?:string,dependencies?:字符串[],工厂:函数|对象);示例//hzfe.jsdefine("hzfe",[],function(){consthzfeMember=17;constgetHZFEMember=()=>{return`HZFEMember:${hzfeMember}`;};exports.getHZFEMember=getHZFEMember;});//index.jsdefine(function(require,exports){consthzfe=require("hzfe");//取决于最近的console.log(hzfe.getHZFEMember());//HZFEMember:17});场景CMD主要用于浏览器,通过符合CMD标准的JavaScript库(如sea.js)加载模块。加载方式CMD异步加载模块,每加载一个模块,实际上是加载对应的JS文件。优缺点优点依赖异步加载,启动速度更快支持循环依赖就近依赖保持与CommonJS的良好兼容性缺点语法相对复杂依赖加载器难以支持模块静态分析具体实现Sea.js2.4UMD(UniversalModuleDefinition)UMD代表通用模块定义。UMD主要是为了解决CommonJS和AMD规范下的代码不通用的问题,同时也支持全局挂载模块,是一个跨平台的解决方案。示例//hzfe.js(function(root,factory){if(typeofdefine==="function"&&define.amd){//AMDdefine(["exports","hzfe"],factory);}elseif(typeofexports==="object"&&typeofexports.nodeName!=="string"){//CommonJSfactory(exports,require("hzfe"));}else{//浏览器全局变量factory((root.commonJsStrict={}),root.hzfe);}})(typeofself!=="undefined"?self:this,function(exports,b){consthzfeMember=17;constgetHZFEMember=()=>{返回`HZFE成员:${hzfeMember}`;};exports.getHZFEMember=getHZFEMember;});//index.jsconsthzfe=require("./hzfe.js");console.log(hzfe.getHZFEMember());//HZFE会员:17个使用场景UMD既可以在服务器端使用,也可以在浏览器端使用。加载方式UMD加载模块的方式取决于环境,Node.js同步加载,浏览器异步加载。优缺点优点跨平台兼容性缺点代码量稍大2.5ESM(ECMAScriptModule)ESM,即ESModule,ECMAScriptModule。现代浏览器原生支持的官方模块化规范,通过导入和导出内容加载模块。示例//hzfe.jsconsthzfeMember=17;exportconstgetHZFEMember=()=>{return`HZFEMember:${hzfeMember}`;};//index.jsimport*ashzfefrom"./hzfe.js";console.log(hzfe.getHZFEMember());//HZFE会员:17使用场景ESM可以在支持的浏览器环境中直接使用,在不支持的端需要编译/打包使用。加载方式ESM加载模块的方式也取决于环境,Node.js同步加载,浏览器端异步加载。优缺点优点支持同步/异步加载语法简单支持模块静态分析支持循环引用缺点兼容性差扩展阅读1.静态分析静态程序分析(Staticprogramanalysis)是指在不运行程序的情况下进行程序分析的方法。静态程序分析-Wiki简而言之,上面所说的静态分析是指能够在运行代码之前判断代码中哪些代码被使用,哪些代码没有被使用。2、模块化和工程化:webpackwebpack同时支持CommonJS、AMD和ESM三种模块化规范的打包。webpack会根据不同的规格,将模块加工成不同的产品。CommonJS(function(module,exports){consthzfeMember=17;constgetHZFEMember=()=>{return`HZFEMember:${hzfeMember}`;};module.exports=getHZFEMember;});AMD(函数(模块,导出,__webpack_require__){var__webpack_amd_define_array__,////依赖________________________________________ebpack_amd_define_array_aray__array___erem________________________________________________________________________________________________________________]成员:${hzfeMember}`;};return{getHZFEMember,};}.apply(exports,__WEBPACK_AMD_DEFINE_ARRAY__);__WEBPACK_AMD_DEFINE_RESULT__!==undefined&&(module.exports=__WEBPACK_AMD_DEFINE_RESULT__);});ESM(function(module,__webpack_exports__,__webpack_require__){__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,"getHZFEMember",函数(){returngetHZFEMember;});consthzfeMember=17;constgetHZFEMember=()=>{return`HZFE成员:${hzfeMember}`;};});3.模块化和工程化:TreeShaking一种死代码行为的术语,它依赖于ES2015中的import和export语句来检测代码模块是否被JavaScript文件导出、导入和使用。TreeShaking-MDN简单的说,TreeShaking是一种通过对ESM模块进行静态分析实现的功能,可以在编译时安全地移除代码中不用的部分(webpack5也支持CommonJS,这里不做详细展开)。参考模块:CommonJS模块异步模块定义通用模块定义通用模块定义模块:ECMAScript模块模块语义
