当前位置: 首页 > Web前端 > JavaScript

JS模块化——CJS&AMD&CMD&ES6-前端面试知识点查漏补缺_3

时间:2023-03-26 21:57:47 JavaScript

本文以时间为轴,从以下几个方面总结了JS模块化。从nomodularity=>IIFE=>CJS=>AMD=>CMD=>ES6=>webpack阶段分析。初期历史:没有模块化的方法需要在页面加载不同的js,用于动画、组件、格式化。各种js文件分为不同的文件。同一个模板引用不同的文件。在这里,文件拆分是最基本的模块化(第一步)*面试中问到script标签的参数:async&defer总结三种加载普通加载:解析到立即阻塞,下载并立即执行当前scriptdefer加载:解析到标签后开始异步加载,后台下载并加载js,解析完成后加载并执行js中的内容,不阻塞渲染asyncloading:(立即执行)开始异步加载解析为标签后,下载后开始执行并阻塞渲染,执行完成后继续渲染转换前夕)-IIFE(语法优化)作用域控制letcount=0;常量增加=()=>++计数;constreset=()=>{count=0;}usetheblocklevelofthefunctionScope(()=>{letcount=0;...})//最基本的部分实现了最简单的模块constiifeModule=(()=>{letcount=0;constincrease=()=>++count;constreset=()=>{count=0;}console.log(count);increase();})();问题:如何优化独立模块自身的额外依赖优化一:依赖其他模块参数传递类型constiifeModule=((dependencyModule1,dependencyModule2)=>{letcount=0;constincrease=()=>++count;constreset=()=>{count=0;}console.log(count);increase();...//可以处理依赖中的方法})(dependencyModule1,dependencyModule2)面试一:了解jquery或者其他很多开源框架的模块加载方案,暴露自己的方法constiifeModule=((dependencyModule1,dependencyModule2)=>{letcount=0;constincrease=()=>++count;constreset=()=>{count=0;}console.log(count);increase();...//可以处理依赖了methodreturnincrease,reset}})(dependencyModule1,dependencyModule2)iifeModule.increase()=>揭示模式revealing=>上层不需要了解底层实现,只关注抽象=>框架查询:继续横向模块化扩展并转向框架:jquery|vue|react模块的细节转向设计模式的成熟阶段。CJS(Commonjs)node.js指定特性:通过module+exports暴露接口,通过require引入外部模块。详细答案参考前端进阶面试题。main.jsconstdependencyModule1=require('./dependencyModule1')constdependencyModule2=require('./dependencyModule2')letcount=0;const增加=()=>++count;constreset=()=>{count=0;}console.log(count);increase();exports.increase=increase;exports.reset=reset;module.exports={increase,reset}execonst{increase,reset}=require(./main.js)compositeuse(function(this.value,exports,require,module){constdependencyModule1=require('./dependencyModule1')constdependencyModule2=require('./dependencyModule2')}).call(this.value,exports,require,module)问题:为什么有些开源项目会把全局,指针和框架本身作为参数(function(window,$,undefined){const_show=function(){$("#app").val("hizhuawa")}window.webShow=_show;})(window,jQuery)块思路1.window全局作用域转换为局部作用域,window为全局作用域,如果不转换toalocalscope会有一个向上看知道全世界的过程,提高执行效率编译期优化:编译后会变成(optimizecompressioncost,destroy)(function(c){})(window)//窗口将be优化为c//window,所有其他执行和所有更改将在执行后与c一起销毁。2、jquery独立自定义复制挂载,防止全局串扰3、undefined防止重写:这段代码在内部执行保证undefined正确,不会被重写。比如在外部定义一个undefined=1undefined,对于jquery本身来说是非常重要的。有优点也有缺点。全局变量的问题还没有出现。缺点:对于服务器服务端方案,异步拉取,依赖处理不是很友好=>异步依赖处理AMD通过异步执行+允许指定回调函数经典实现框架:require.js新定义方法://define定义模块define(id,[depends],callback)//需要加载reuqire([module],callback)模块定义define('amdModule',[dependencyModule1,dependencyModule2],(dependencyModule1,dependencyModule2)=>{//业务逻辑letcount=0;constincrease=()=>++count;module.exports={increase}})介绍require(['amdModule'],amdModule=>{amdModule.increase()})面试题:ifWhatshouldIdoifI想与AMDModule中的现有代码兼容?define('amdModule',[],require=>{constdependencyModule1=require('./dependencyModule1')constdependencyModule2=require('./dependencyModule2')//业务逻辑letcount=0;constincrease=()=>++count;module.exports={increase}})面试题:手写是否兼容CJS&AMD//判断的关键:1.对象还是函数2.导出?3.define(define('AMDModule'),[],(require,export,module)=>{constdependencyModule1=require('./dependencyModule1')const依赖Module2=require('./dependencyModule2')letcount=0;常量增加=()=>++计数;constreset=()=>{count=0;}控制台日志(计数);export.increase=increase();})(//目标:一次区分CJS或AMDtypeofmodule==='object'&&module.exports&&typeofdefine!==function?//CJSfactory=>module.exports=factory(require,exports,module)://AMDdefine)优缺点优点:适合在浏览器中加载异步模块缺点:引入成本CMD按需加载主应用框架:sea.jsdefine('module',(require,exports,module)=>{let$=require('jquery')letdependencyModule1=require('./dependencyModule1')})优缺点优点:按需加载,依赖就近缺点:依赖打包,加载逻辑存在于每个模块中,扩展了模块的体积,同时功能上依赖于编译ES6模块化。dynamicModule=>{dynamicModule.increase();})优点:通过各个端的统一形式,集成了js模块化解决方案缺点:本质上,运行时分析解决了模块化的新思路——前面遗留的根本问题-endengineering:Dependencyanalysissolutionatruntime:执行离线编译时的依赖处理思路define('a',()=>{letb=require('b')letc=require('c')})完整体:以webpack为核心的前端工程+mvvm框架组件化+设计模式