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

2022前端开发知识总结

时间:2023-04-05 14:10:50 HTML5

原文链接目录查看js基本事件循环异步解决方案浏览器渲染原理网络协议前端框架性能优化设计模式结束js基本数据类型5+1基本类型-number,string,undefined,布尔值,空值;引用类型——对象;目前基本类型增加了两个新成员:symbol、BigInt;基本类型和引用类型的区别:前者是按值访问的,所以我们操作的是变量存储的实际值;后者不能直接操作对象所在的内存空间。在操作对象时,实际操作的是对象的引用。基本类型存放在栈中;引用类型的'变量'名称存储在堆栈中,同时存储指针,指向堆中的真实值;(栈和堆的概念可以直接搜索《js中栈和堆的概念及区别》)参考:阮一峰ECMAScript6(ES6)标准入门教程第三版参考书:Rhino书本指向箭头函数:this继承了第一个封装箭头函数的普通函数中的this;普通函数:new(this指向New对象)-bind/apply/call(this是必须的this)-this指向函数上下文对象-this指向window;参考文章:https://juejin.cn/post/6844903941021384711参考书籍:红宝书closures一个函数引用另一个函数的内部变量就会形成一个闭包。闭包在正常开发中很常见;了解范围链的创建和使用细节对于理解闭包非常重要;参考文章:https://juejin.cn/post/6844903747957719053参考书:红皮书原型每个对象在创建时都与另一个对象相关联,并从另一个对象继承其属性。这里的另一个对象是原型;原型存在的意义在于形成原型链。写对象属性的时候,先从对象本身找,如果找不到,就去对象的原型,如果还是找不到,再去对象原型的原型,依次类推直到找到为止;由原型组成的搜索链为原型链;参考文章:https://juejin.cn/post/6844903936365690894参考书:红皮书继承组合继承:通过调用修改子类this,并将子类原型指向新的父类();寄生组合继承:修改子类this通过调用,将子类原型指向父类原型(Object.create(parentclass.prototype)),将子类原型构造函数指向子类;参考书:红皮书模块模块化的特点:可重用性和可维护性;commonJs最先作为标准在NodeJs中引入,作为NodeJs模块化标准;在commonJs中,require在第一次加载时会执行整个脚本,并在内存中生成一个对象缓存。可以在下次加载时直接从缓存中获取;对于循环加载,只输出执行的部分。尚未执行的部分不输出;静态加载ES6的最新ESModule;加载脚本时,它成为对加载模块的引用,不会被缓存;并发和并行的区别:并发是两个或多个事件在同一个时间间隔内发生;并行性是指两个或多个事件同时发生;并行性可以通过提高硬件能力来实现,只需要多核CPU;并发中最常听到的就是高并发。在一定时间内,服务器的吞吐量和每秒QPS响应请求数是一定的。这种情况下,要解决高并发问题,最简单的方法就是提高机器性能,加内存、加硬盘、升级网速。当然,通过架构层面的设计,你也可以有所作为,部署多台机器,加一个负载均衡层,均匀请求;数据库分库分表,读写分离;引入消息中间件等;引入缓存集群;异步解决方案回调函数:在浏览器端,异步问题就是对Ajax网络请求的异步响应,回调函数可以在一定程度上解决这个异步响应的问题。缺点是:不易维护,不易读取,不能直接返回;Generator:封装了多个内部状态异步方案,generator函数;会返回一个迭代器,配合next()函数,可以控制开始、暂停、恢复代码;场景:控制流管理,异步操作;Promise:解决异步操作方案,包括异步操作结果对象;内部三种状态,一旦启动就无法更改;问题:无法取消,需要回调捕获错误;Promise是一个链式调用,每次调用then后返回一个Promise,是一个全新的Promise;PromisePromise/A+规范的实现基础——三种状态:pedding、fulfilled、rejected;(以Promise封装的Ajax为例)异步处理流程:执行Promise回调函数,由于异步操作,内部状态不变。继续执行then回调,内部状态没有变化,回调队列中的then回调暂时不会执行。此时异步执行完成(网络请求响应),状态发生变化,Promise内部调用resolve函数,执行回调队列;async/await:异步方案,需要配合使用;在函数中加入async后,函数会返回一个Promise;里面awaitGenerator是实现的,await是一个异步操作。如果后面的表达式不返回Promise,会被打包成Promise.resolve(返回值),然后执行函数外的同步代码;eventloop有一个eventloop和一个或多个tasksQueue;任务队列是一组任务;1、每个事件循环都是一个正在运行的任务,可以是task也可以是null;2、每个事件循环都有一个微任务队列(microtaskqueue),初始为空;3、每个eventloop都有一个boolean值,用于执行microtaskcheckpoints,初始为false;1、js事件循环是如何循环执行的?浏览器事件循环的执行顺序:首先执行脚本同步代码,这是一个宏任务;当前所有同步任务执行完毕,执行栈为空,查询是否有异步任务代码执行;执行当前宏任务下的所有微任务;microtask执行后,如果需要,页面会被渲染;然后下一轮事件循环开始;2.什么是宏任务和微任务?宏任务:script、setTimeout、setInterval、setImmediate、I/O、UIRender;微任务:process.nextTick、promise、MutationObsever;3.Nodejs事件循环和浏览器事件循环有什么区别?在Nodejs和浏览器端,宏任务和微任务交替执行,调用顺序基本一致。Nodejs的执行会分阶段,分为6个阶段:参考:Node.js事件循环文档,每进入一个阶段,就会从回调队列中取出函数执行。当队列为空或回调函数达到系统设定的阈值时,进入下一阶段。异步方案可以使用ajax异步回调作为浏览器端的初始异步方案。异步回调-->Promise实例-->Generator-->async/await大致就是这么一行。我们需要关注的可能主要是promises和async/await的解决方案。1、你了解Promise的内部实现吗?它的具体工作流程是怎样的?Promise是一种异步解决方案,它包含了异步操作结果的对象。它具有三种内部状态。状态一旦改变,状态就无法改变;Promise是一个链式调用。每次调用then回调函数,都会返回一个新的Promise,并且是一个全新的Promise;Promise异步处理流程:执行Promise实例的回调函数。由于异步请求或操作,此时状态没有改变。继续执行then回调,由于state没有变化,回调会放在回调数组中。直到Promise实例中的异步请求或操作完成,状态发生变化,调用resolve函数,遍历并执行回调数组,then回调函数获取到相关数据。2、谈谈async/await参考:Promise原理分析图Promise流程浏览器渲染原理浏览器是一个多进程的应用。每打开一个Tab页,就相当于创建了一个独立的浏览器进程。浏览器进程包括:浏览器进程(主进程)、插件进程、GPU进程、渲染进程(浏览器内核)。只有一个主进程负责协调应用程序,默认情况下每个标签页都有一个渲染进程,互不影响。我们常说的Js线程和GUI渲染线程都包含在渲染进程中,还包括异步http请求线程、事件触发线程等。1、在地址栏输入域名地址后发生了什么?1、DNS服务查询域名对应的目标服务IP地址;2、根据目标IP地址找到目标服务器,建立TCP连接;3、服务器响应数据或文本信息;4.客户端获取数据后,页面Rendering;2.浏览器渲染的过程?1.请求html文件处理html标签构建DOM树;2.请求css文件处理css标签构建CSSOM树;3.将DOM和CSSOM合并为一棵渲染树;4.根据渲染树布局信息计算出每个节点的几何结构;5.在屏幕上绘制每个节点;当有阻塞的css资源时,浏览器会延迟JS的执行和DOM的构建;3、重绘回流?重绘是在不影响布局的情况下需要改变节点的外观;回流是在需要更改布局或几何属性时;参考:渲染性能参考:从浏览器多进程到JS单线程浏览器页面渲染机制你所不知道的网络协议关于TCP关于UDP的介绍,TCP的三次握手和四次握手就不细说了.相关文章可参考:【传输层协议TCP与UDP】(https://juejin.cn/post/684490...),TCP三次握手四次挥手;http协议是一种常用的网络传输协议,全称是超文本传输??协议,它规定了http请求和响应的具体结构,当然还包括其他的东西,比如:缓存,文件类型,参数,请求类型,status等。它是基于传输层TCP协议的。TCP握手成功后,就可以进行网络数据传输了。HTTP/HTTPS1。什么是http协议?它是什么样子http是TCP/IP协议的一个应用层协议,主要负责传输数据或文字图片等内容。它基于传输层的TCP协议。HTTP分为请求消息和响应消息,Web客户端向Web服务器发送的HTTP消息称为请求消息(requestmessage)。服务器向客户端发送的消息称为响应消息,消息分为:起始行、头字段、正文等;2、http和https有什么区别?http和https的字面区别是一个s,这个s就是SSL/TCL加密协议。说到加密协议,就绕不开加密技术。在SSL/TCL加密协议中,同时使用了非对称加密和对称加密。SSL/TCL加密协议相当于在应用层和传输层之间加了一层,可以称之为加密层。大体流程:客户端向服务器端请求加密证书,获取公钥等证书信息;双方协商生成“对话密钥”;双方使用“对话密钥”进行加密通信。非对称加密保证“对话密钥”的安全传输,对称加密保证客户端和服务端对数据进行加密和解密。3、如何配置http网络缓存?如果需要开启强缓存和协商缓存,可以在服务端的nginxweb服务器上进行相应的配置,开启相应的网络缓存。还可以配置其他服务器端Web服务器。(网上有很多配置细节)4、强缓存和协商缓存有什么区别?强缓存:Cache-Control,常用属性有max-age、no-cache、no-store等,max-age表示在一个相对时间内缓存,在此期间不会再次请求对应的资源;no-cache表示不缓存,表示在使用缓存资源之前,必须经过服务器的校验;no-store意味着没有缓存。Negotiationcache:Last-modified和ETag,类似,可以理解为文件标识符。您还可以将ETag(您选择的版本ID)或上次修改日期添加到响应标头。客户端下次获取资源时,会通过If-None-Match(对应ETage)和If-Modified-Since(对应Last-Mofied)这两个请求头将值发送给服务端。如果服务器发现这两个值相等,则返回一个HTTP304。它们的区别:ETag会随着资源的变化而变化;Last-modified不识别秒内的修改。如何使用————保证HTML资源在前端是最新的,比如:max-age=300、ETag、Last-modified,当然也可以考虑使用no-cache、ETag,last-modified合作。但是,CSS和JS资源已经注入到HTML中。资源文件地址通常使用哈希值添加到文件名中,以确保资源是最新的。css和js文件可以设置:max-age=31536000或者last-modified配合使用。5、你知道http2.0吗?为什么http2.0更好?http2.0基于二进制框架层,http2.0可以在共享TCP连接的基础上同时发送请求和响应。在http1.x中,数据以文本形式传输。基于文本的数据传输存在诸多缺陷,文本的表达形式多样。所以,出于健壮性的考虑,肯定有很多场景,但是binary就不一样了。只有0和1的组合,所以选择二进制传输,实现起来方便且鲁棒。为了保证http不受影响,需要在应用层(HTTP2.0)和传输层(TCP或UDP)之间增加一个二进制分帧层。在二进制分帧层,http2.0将所有传输的信息分成更小的消息和帧,并以二进制格式进行编码。http1.x的header信息会被封装到Headersframe中,而RequestBody会被封装到Dataframe中。在传输过程中,会共享一个TCP流(TCP连接中的虚拟通道,可以承载双向消息),这样就不会重复连接。参考:书籍:HTTP权威指南概述SSL/TLS协议的运行机制。研究完问题以后可以考虑把源码翻过来。由于工作原因,对react比较了解,所以分享主要是关于react的。React和Vue作为前端框架,本质上做的是一样的事情。在浏览器和开发操作之间增加了一个中间层,以辅助项目的管理和开发。React框架1.JSX的本质是什么,它和JS有什么关系?为什么要使用JSX?JSX是一种类HTML的语法结构,本质上是JS的语法扩展。语法结构简洁,通俗易懂,大大提高了研发效率和体验。2、JSX背后的功能模块是什么,这个功能模块有什么作用?JSX通过babel语法改造后,实际上是通过React.createElement函数创建React元素。createElement接收三个参数type类型,config配置,children子元素。可以通过createElement创建虚拟DOM对象。3、react16.3的新旧生命周期分别是什么,以及已经消失的旧生命周期?移除ComponentWillMount和ComponentWillReceiveProps并升级为getDeicvedStateFromProps以确保更简单和更可控的生命周期;删除ComponentWillUpdate并添加getSnapshotDeforeUpdate;4.React团队为什么要移除旧的生命周期函数?React16+引入了Fiber架构。Fiber会将一个大的更新任务拆解成多个小任务,可以挂起和恢复。React16+生命周期分为渲染和提交两个阶段。render阶段在执行过程中允许被打断,而commit阶段操作涉及到真正的DOM渲染,不能被打断。ComponentWillMount、ComponentWillUpdate、ComponentWillReceiveProps的生命周期都在render阶段。在Fiber架构中,渲染阶段会被中断并重复执行。在这些生命周期中你可能习惯做的事情可能包括:setState、异步请求、操作真实DOM等,在Fiber异步渲染的控制下,这些生命周期可能会导致非常严重的bug(比如在这些中调用支付接口废弃的生命周期)。5、React组件数据如何流动?实现数据通信的解决方案有哪些?React是一种自上而下的单向组件数据流1.父子组件通过prop属性传递数据,子父组件可以传递函数;2、兄弟组件共享同一个父组件,实现兄弟组件通信;3.ContextAPI实现全局通信;(还没试过)4.Redux数据状态容量,用于可预测的状态管理;5、发布/订阅模式实现任意组件通信;6.为什么选择ReactHooks?与Class组件相比,功能组件更轻巧,更符合UI=render(data)的特点。同时,在Fiber架构的加持下,Hooks的实现也不在话下。随着功能组件的发展,Hooks应运而生,让功能组件真正把数据和渲染绑定在一起。当然Hooks还是有一些不足的:有些循环不存在;它不能很好地消化“复杂性”,组件的拆分和组织是一个很大的挑战,不容易掌握。7、为什么Hooks的执行顺序如此重要?钩子本质上是链表。比如使用useText和useState创建状态时,hook创建的状态会以单链表的形式保存。更新时,会再次调用函数组件,hooks会依次遍历单链表,读取数据并更新。这个过程完全按照这里的创建顺序。所以在更新的时候,一旦位置改变了,执行顺序就被替换了,运行起来就会有bug。8、reconciliation(协调)和diff有什么关系或区别?协调是指将虚拟DOM映射到真实DOM的过程。和解过程不能等同于差异。Reconciliation是一个“一致”的过程,而diff是一个“找不同”的过程,只是“一致”过程中的一个环节。(当然,经常说的reconciliation相关的问题,大部分都和diff过程有关)9.React的diff逻辑和思路?1.由于耗时原因,diff过程只比较同层节点;2、对于同类型的元件,需要做进一步的比较;3.对于链表组件,key属性用于维护节点标识的稳定性,避免总是产生新的节点;10、setState的工作流程是怎样的?非并发模式:setState会出现异步和同步。在生命周期和合成事件上是同步的,在setTimeout、setInterval、DOM原生函数等函数上是同步的。那是为什么呢?当合成事件或生命周期执行时,批量更新任务锁被打开,我们所做的setState操作会被放入批量更新队列中,直到函数执行完毕才会关闭批量更新任务锁。批量更新任务锁是一个同步操作,一旦在setTimeout函数中使用了setState,setTimeout函数回调会被放到下一个宏任务执行中,当执行完setState时,批量更新任务锁关闭,它不会被放入批量更新队列,而是直接执行。并发模式:setState不会出现异步和同步。因为时间片的存在,只要当前时间片没有结束,多个setState还是可以合并为一个,即使是在setTimeout中调用。对于超过当前时间片的操作,会通过MessageChannel放到下一个宏任务中继续执行。(MessageChannel接收消息晚于Promise的microTask,但早于setTimeout)11.StackReconciler堆栈协调的局限性是什么?Js线程和浏览器中的渲染线程是互斥的。这两个线程不能穿插执行,必须串行化。而当Js线程长期占据主线程时,渲染线程的更新就会等待很长时间,从而导致页面卡顿。StackReconciler堆栈协调是一个同步递归过程,虚拟DOM树diff算法的遍历是深度优先遍历。因为是同步的,所以不能中断。在处理结构复杂、体积较大的虚拟DOM树时,StackReconciler时间会很长,认为Js主线程会长时间占用主线程,从而导致渲染卡顿/页面卡顿上文提到的。12.请介绍一下Fiber架构?特点:可中断、可恢复、优先级存在。Scheduler————>Reconciler————>Renderer更新优先级FinddifferencesRenderdifferences在Fiber架构模式下,每个更新任务都会被赋予一个优先级。当然,任务A以更高的优先级进入调度器,而任务B已经在Reconciler中执行,那么Reconciler就会终止任务B,将更高优先级的任务A推入Reconciler。当任务A完成后,新一轮的调度会将之前中断的任务B推回Reconciler继续其渲染之旅。Renderstarts——————>(workunit|workunit|workunit)——————>commit提交渲染13.ReactDOM.render调用栈初始化阶段,render阶段初始化阶段:将创建根对象对象挂载_internalRoot属性,_internalRoot也是FiberRoot。FiberRoot的本质是一个FiberRootNode对象,它包含了当前的属性,当前对象是一个FiberNode实例。当前对象是一个Fiber节点,是Fiber树的头节点;判断Fiber的优先级,根据优先级创建当前Fiber的更新对象,入队调度FiberRoot;然后进入渲染阶段;(此时相当的因为只有一个Fiber头节点)渲染阶段:通过createWorkInProgress函数,创建一个rootFiber节点的copyworkInProgress节点树(即当前节点的copy节点),他们引用互相通过交替;然后会触发beginWork函数,实现新FiberNode的创建。循环遍历,会不断创建组成元素Fiber(每个元素节点对应一个Fiber节点),直到创建完最后一个,此时Fiber树(单链表)基本完成;重点是此时已经遍历到了单链表的尾部,然后底部节点会从下往上生成真正的DOM节点,同时被其父组件sideeffects链接起来。这个副作用链也是一个单链表,遍历到根节点。此时,根节点上的副作用链包括整个DOM更新。那么剩下的只需要在root下获取sideeffectchainupdate即可。参考:简单复习一下React架构的演进-从同步到异步React架构演进-从递归到循环React架构演进-更新机制React架构演进-Hooks实现性能优化可以使用ChromeLighthouse进行性能评估,根据to评估结果还可以得出一些改进点:在reactframework层面可以做的优化方向的核心点:减少re-renders的次数;减少计算量,主要是减少重复计算。具体有以下解决方案:1、拆分公共组件和业务组件,按照具体业务分开,降低组件粒度;2、拦截shouldComponentUpdate中的非渲染;3、对于简单的数据类型,可以考虑使用React.PureComponent;4..功能组件考虑使用React.meno,React.memo与React.PureComponent非常相似;(版本React16.6.0)5.ReactHooks组件使用useCallback缓存函数,避免每次返回一个新的函数;(版本Reactv16.8)6.ReactHooks组件使用useMemo缓存计算值;(版本Reactv16.8)一个前端项目下的通用优化技术:使用缓存、节流、压缩、按需加载、全局管理等方法或技术。如下:1、避免频繁的渲染更新,即使有必要,也需要考虑是否使用节流功能;2、对于长列表页面,考虑翻页加载,点击下一页或者虚拟长列表,避免数据量过大,渲染卡顿;3、在项目中统一控制定时器功能,避免定时器偷偷摸摸;4.拆分Js文件,考虑按需加载提高加载速度;5.保证首屏必要的数据渲染,可以增加Transition图片,提升用户体验;6、对于后台接口上的冗余数据,可以考虑清理数据,只保留必要的数据;7、为避免过多的数据请求,可以考虑使用数据缓存来提升用户体验;8、考虑大图CDN图片加载,也可以考虑图片懒加载;9.避免使用太多嵌套的css选择器;10.代码文件gzip压缩等,服务器相关缓存配置;以上是关于各种技巧和原理的更多内容,如果想了解具体的标准,可以参考谷歌为Web性能开发者提供的文档。google.cn/Web性能设计模式参考文章:JavaScriptDesignPatterns