前端八股
参考资料
前端
项目优化
-
移除生产环境的控制台打印
养成良好的代码习惯,在开发基本完成后去掉无用的 console
或者使用插件自动去除,插件包括 babel-plugin-transform-remove-console、uglifyjs-webpack-plugin、terser-webpack-plugin -
第三方库的按需加载
例如 echarts,官方文档里是使用 配置文件指定使用的模块
element-ui 使用 babel-plugin-component 实现按需引入 -
前后端数据交换方面
使用蓝湖、接口文档,与后端同学协商,规范后台数据返回蓝湖,产品设计研发协作工具
-
性能问题
页面加载性能、动画性能、操作性能。Performance API,记录性能数据 -
减少请求数
JS、CSS 打包到 HTML
JS 控制图片异步加载、懒加载
小型图片使用 data-uri -
较少传输体积
尽量使用 SVG\gradient 代替图片
根据机型和网络状况控制图片清晰度
对低清晰度图片使用锐化来提升体验
设计上避免大型背景图 -
使用 CDN 加速
内容分发网络,是建立再承载网基础上的虚拟分布式网络,能够 将源站内容缓存到全国或全球的节点服务器上
用户就近获取内容,提高了资源的访问速度,分担源站压力
HTTP 和 HTTPS
-
概念
-
http
是一个客户端和服务器端 请求和应答的标准(TCP)
用于从 WWW 服务器 传输超文本 到本地浏览器的超文本传输协议 -
https
是以安全为目标的 HTTP 通道,即 HTTP 下加入 SSL 层 进行加密
其作用是:建立一个 信息安全通道,来确保数据的传输,确保网站的真实性
-
| http | https |
|---|---|
| 信息明文传输 | 加密传输,但是安全性并非绝对的 |
| 默认端口 80 | 默认端口 443 |
| 连接是无状态的 | 握手阶段较费时 |
| 需要 ca 证书,相应的收取费用 | |
| SSL 证书需要绑定域名 |
-
https 协议的工作原理
web 服务器接收到客户端的 https 请求之后会将网站的证书(证书中包含了公钥),传输给客户端
客户端和 web 服务器端开始 协商 SSL 链接的安全等级,也就是加密等级
客户端浏览器通过双方协商一致的安全等级,建立会话密钥,然后通过网站的 公钥来加密会话密钥,并传送给网站
web 服务器通过 自己的私钥 解密出会话密钥
web 服务器通过会话密钥加密与客户端之间的通信 -
HTTP 协议的发展历程
-
HTTP1.1
缺陷:高延迟的队头阻塞、无状态特性导致的巨大头部、明文传输的不安全、不支持服务器推送等问题 -
HTTP/2
新特性:二进制传输提高解析效率,Header 压缩减少冗余数据,多路复用解决请求数量限制,Server Push 改变工作模式,提高安全性
缺点:TCP 及 TCP+TLS 建连延时,队头阻塞未彻底解决,多路复用导致服务器压力上升和容易 Timeout -
HTTP/3
新特性:基于 UDP 实现快速握手,集成 TLS 加密,解决队头阻塞,实现连接迁移
-
-
HTTP 请求跨域问题
-
跨域问题
是指 浏览器不能执行其他网站的脚本
它是由浏览器的同源策略造成的 -
同源策略
是浏览器对 JavaScript 实施的安全限制
只要 协议、域名、端口有任何一个不同,都被当作是不同的域 -
跨域原理
通过各种方式,避开浏览器的安全限制
-
TCP 连接
三次握手
-
第一次握手
建立连接时,客户端发送 syn 包(syn=j)到服务器,并进入 SYN_SENT 状态,等待服务器确认SYN
Synchronize Sequence Numbers,同步序列编号 -
第二次握手
服务器收到 syn 包并确认客户的 SYN(ack=j+1)
同时也发送一个自己的 SYN 包(syn=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态 -
第三次握手
客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ack=k+1)
此包发送完毕,客户端和服务器进入 ESTABLISHED(TCP 连接成功)状态,完成三次握手
握手过程中传送的包里不包含数据
三次握手完毕后,客户端与服务器才正式开始传送数据
四次挥手
TCP/IP 如何保证数据包传输的有序可靠?
对字节流分段并进行编号然后通过 ACK 回复和超时重发这两个机制来保证
发送方将数据包发送给接收方
此时数据包先会保留在缓冲区,并为它们设置一个超时定时器
如果之后接收方发来应答消息,表示数据包接受到了,那么就可以释放掉缓冲区对应的数据包
若没有接收到,则用缓冲区的数据包重传,直到收到应答或者达到设定的重传最大次数
接收方收到数据包后
先进行 CRC 校验,如果正确,则把数据交给上层协议
然后给发送方回复一个累计应答包,表明该数据已收到
TCP 和 UDP 的区别
| TCP | UDP |
|---|---|
| 面向连接的数据传输协议 | 无连接 |
| 握手保证连接可靠 | 不可靠,通信无需建立连接,接收端也不会发送确认信号 |
| 仅支持单播传输 | 支持单播,多播,广播 |
| 头部开销比 TCP 更小,数据传输速率更高,实时性更好 |
粘包问题
接收方接收到的数据粘成一包,后一包数据的头紧接着前一包数据的尾
粘包情况有两种,粘在一起的包都是完整的数据包,而或者是有不完整的包
在流传输中出现,UDP 不会出现粘包,因为它有 消息边界
-
避免粘包的措施
- 对于发送方引起的粘包
通过 push 指令强制数据立即传送,而不必等待发送缓冲区满
但是会降低网络发送效率,影响应用程序的性能,一般不建议使用 - 对于接收方引起的粘包
可通过精简接收进程工作量、提高接收进程优先级等措施,使其及时接收数据
但是不能完全避免粘包,当发送频率较高时,或由于网络突发可能使某个时间段数据包到达接收方较快,接收方还是有可能 来不及接收,从而导致粘包 - 分包多发
接收方可以分多次接收,然后合并
但是效率较低,对实时应用的场合不适合
一种比较周全的对策是:接收方创建一预处理线程,对接收到的数据包进行预处理,将粘连的包分开
- 对于发送方引起的粘包
浏览器
| Cookie | sessionStorage | localStorage |
|---|---|---|
| 都是存储在客户端 | ||
| 数据大小不能超过 4KB | 可以达到 5MB+ | 可以达到 5MB+ |
| 在设定的过期时间之前一直有效 | 在当前浏览器窗口关闭后自动删除 | 永久存储,浏览器关闭后数据不丢失,除非主动删除数据 |
| 数据会随着 HTTP 请求自动发送到服务器(因此不建议在 Cookie 中存储敏感信息) | 仅保存在本地 | 仅保存在本地 |
| 适合用于会话管理,如 用户认证状态的保持 | 适用于同一窗口中的页面间数据共享,如 表单数据的暂存 | 适合用于持久化存储 用户偏好设置、主题选择 等 不需要频繁更新的数据 |
从输入 URL 到页面加载的全过程
我们在浏览器中输入 URL
浏览器先查看 浏览器缓存-系统缓存-路由缓存 中是否有该地址页面
如果有则显示页面内容。如果没有则进行下一步
浏览器向 DNS 服务器发起请求,解析该 URL 中的域名对应的 IP 地址
DNS 服务器是基于 UDP 的,因此会用到 UDP 协议
DNS 服务器解析出 IP 地址后,根据 IP 地址和默认 80 端口,和服务器建立 TCP 连接
浏览器发起读取文件的 HTTP 请求,该请求报文作为 TCP 三次握手的第三次数据发送给服务器
服务器对浏览器请求做出响应,并把对应的 html 文件发送给浏览器
浏览器和服务器通过四次挥手释放 TCP 连接
客户端(浏览器)解析 HTML 内容并渲染出来
-
浏览器渲染过程
-
构建 DOM 树
词法分析然后解析成 DOM 树(dom tree)
树的根是 document 对象 -
构建 CSS 规则树
生成 CSS 规则树(CSS Rule Tree) -
构建 render 树
Web 浏览器将 DOM 和 CSSOM 结合,并构建出渲染树(render tree) -
布局(Layout)
计算出每个节点在屏幕中的位置 -
绘制(Painting)
即遍历 render 树,并使用 UI 后端层绘制每个节点
-
-
JS 引擎解析过程
-
创建 window 对象
window 对象也叫全局执行环境,当页面产生时就被创建
所有的全局变量和函数都属于 window 的属性和方法,而 DOM Tree 也会映射在 window 的 doucment 对象上
当关闭网页或者关闭浏览器时,全局执行环境会被销毁 -
加载文件
完成 js 引擎分析它的 语法与词法是否合法,如果合法进入预编译 -
预编译
寻找全局 变量 声明,把它作为 window 的属性加入到 window 对象中,并给变量赋值为 ‘undefined’
同理寻找全局 函数 声明,并将函数体赋值给他(匿名函数是不参与预编译的,因为它是变量) -
解释执行
string、int 这样的值就是直接把 值 放在变量的存储空间里
object 对象就是把 指针 指向变量的存储空间
函数执行,就将函数的环境推入一个环境的 栈 中,执行完成后再弹出,控制权交还给之前的环境
-
重绘与重排
-
重绘(Repaint)
当一个元素的外观发生改变,但 没有改变布局,重新把 元素外观 绘制出来的过程 -
重排/回流(Reflow)
当 DOM 的变化影响了 元素的几何信息,浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置
表现为重新生成布局,重新排列元素
『重绘』不一定会出现『重排』,『重排』必然会出现『重绘』
重排和重绘代价是高昂的,它们会破坏用户体验,会对性能有影响
在两者无法避免的情况下,一般我们宁可选择代价更小的重绘
- 导致重排或重绘的动作
添加、删除、更新 DOM 节点
通过 display: none 隐藏一个 DOM 节点,触发重排和重绘
通过 visibility: hidden 隐藏一个 DOM 节点,只触发重绘 移动或者给页面中的 DOM 节点添加动画
用户行为,例如调整窗口大小,改变字号,或者滚动
浏览器的缓存机制
HTTP 缓存机制通过 减少不必要的网络请求,提高了资源加载的速度和效率
强缓存通过本地时间或资源的生命周期来决定是否使用缓存
而协商缓存则通过服务器和客户端之间的验证来决定是否使用缓存
-
强缓存(Expires 和 Cache-Control)
当资源在强缓存期间被请求时,浏览器会直接从本地缓存读取资源
状态码返回 200,但不会从服务器请求数据
在浏览器的开发者工具中,可以看到资源是从缓存中读取的,通常会显示 from cache 字样-
Expires
是一个 HTTP 头字段,它指定了资源到期的时间,浏览器在请求资源时会首先检查这个时间
如果当前时间小于 Expires 指定的时间,则浏览器会直接从本地缓存读取资源,而不会向服务器发送请求
但是,Expires 是 依赖于本地时间 的,如果用户修改了本地时间,可能会导致缓存失效 -
Cache-Control
是一个更现代的 HTTP 头字段,有更多的控制选项
其中的max-age指令可以指定资源的最大生命周期(以秒为单位)
即使本地时间被修改,max-age指令也能确保缓存的有效性
-
-
协商缓存
当强缓存失效后,浏览器会进入协商缓存阶段-
ETag(Entity Tag)
是一个 HTTP 头字段,用于标识资源的唯一性
每当资源发生变化时,ETag 值也会变化
服务器通过比较客户端请求头中的If-None-Match(携带上次请求时的 ETag 值)和当前资源的 ETag 值来判断资源是否被修改
如果两者相同,说明资源未被修改,服务器返回 304 状态码,告诉浏览器可以使用缓存中的资源
如果不同,则说明资源已被修改,服务器返回新的资源和新的 ETag 值 -
Last-Modified
是一个 HTTP 头字段,表示资源的最后修改时间
当客户端第一次请求资源时,服务器会在响应头中包含这个时间戳 -
If-Modified-Since
是客户端在再次请求资源时,请求头 中包含的一个字段
其值是上次请求时从服务器获得的Last-Modified时间
服务器收到这个请求后,会检查资源的最后修改时间
如果资源自上次请求以来没有被修改,服务器返回 304 状态码,告诉浏览器可以使用缓存中的资源
如果资源被修改了,服务器返回新的资源和新的Last-Modified时间
-
前端布局
CSS 选择器及优先级
-
选择器
id 选择器#myid
类选择器.myclass
属性选择器a[rel="external"]
伪类选择器a:hover, li:nth-child
标签选择器div, h1, p
相邻选择器h1 + p
子选择器ul > li
后代选择器li a
通配符选择器* -
样式属性优先级
!important > 行内样式 > ID 选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
position 属性
-
固定定位 fixed
固定定位的元素位置是相对于浏览器窗口的,即使页面滚动,也会停留在相同的屏幕位置不占据文档流中的空间,这意味着它们不会影响其他元素的布局
可能会与其他元素重叠 -
相对定位 relative
相对定位的元素是相对于它们在正常文档流中的原始位置进行偏移的
这意味着它们可以通过设置 top, right, bottom, left 属性来移动相对定位的元素仍然占据它们在文档流中的原始空间,所以它们移动后可能会覆盖其他元素
常用于 微调元素位置,而不影响其他布局 -
粘性定位 sticky
介于相对定位和固定定位之间的一种定位方式
开始时像相对定位,直到一个元素超过了指定的滚动阈值,然后像固定定位适合创建像表格标题或侧边栏这样的元素,它们在页面的某个区域内是固定的
但当页面滚动超出这个区域时,它们会随着页面滚动 -
绝对定位 absolute
绝对定位的元素是相对于其最近的已定位(非 static)祖先元素进行定位的
如果没有这样的祖先元素,它将相对于初始包含块(通常是 HTML 文档体)进行定位不占据空间,会和其他元素重叠
常用于创建 浮动的侧边栏或弹出框 -
默认定位 Static
位置由 HTML 标记的顺序决定
占据空间,并且其他元素会围绕它们进行布局
z-index 属性可以用来控制重叠元素的堆叠顺序,但它只对定位元素(即非 static 定位的元素)有效
inherit 属性规定应该从父元素继承 position 属性的值
CSS 盒子模型
在标准的盒子模型中,width 指 content 部分的宽度
故一个块的总宽度 = width + margin(左右) + padding(左右) + border(左右)
在 IE 盒子模型中,width 表示 content + padding + border 这三个部分的宽度
故一个块的总宽度 = width + margin(左右)
其中 width 已经包含了 padding 和 border 值
BFC
Block Formatting Context,块级格式化上下文
是一个独立的渲染区域,规定了内部 box 如何布局
- 创建方式
浮动元素:float属性设置为left或right的元素
绝对定位元素:position属性设置为absolute或fixed的元素
块级容器:display属性设置为inline-block、block、table、table-cell或flex、grid的元素
块级盒子:overflow属性设置为auto、scroll或hidden的块级元素
inline-block 在使用时有时会有空白间隙的问题
-
BFC 的特性
BFC 内部的盒子会垂直排列
BFC 与外部的浮动和定位元素是隔离的,不会相互影响
BFC 可以包含内部的浮动元素,阻止浮动元素溢出 BFC 的边界
BFC 与另一个 BFC 相邻时,它们的垂直外边距不会折叠 -
应用
通过创建 BFC 来实现自适应布局,例如使用overflow: auto创建 BFC 来包含浮动元素
防止相邻块级元素的外边距折叠
隔离不同部分的布局,防止它们相互影响
|
|
居中
-
水平居中
-
行内元素
text-align: center; -
确定宽度的块级元素
margin: 0 auto;
若父元素的position: relative;,设置当前元素position: absolute; margin-left: (父width-子width)/2 -
对于宽度未知的块级元素
display:inline-block; text-align:center
display:flex; justify-content:center
-
-
垂直居中
父容器相对定位,子级设置绝对定位,通过 margin 实现自适应居中
父级设置display: flex;弹性布局,子级设置 margin 为 auto 实现自适应居中 -
隐藏页面中某个元素的方法
opacity: 0修改透明度以隐藏元素,不会改变页面布局,并且依旧能够绑定、触发事件
visibility:hidden也不会改变页面布局,文档布局中仍保留原来的空间(重绘),但是不会触发该元素已经绑定的事件
display:none会改变页面布局,在文档布局中不再分配空间(回流+重绘)
页面布局
- Flex 布局
|
|
.container 类中定义了容器的 Flexbox 布局
flex-flow 属性来组合 flex-direction 和 flex-wrap 属性
justify-content 属性用于水平方向上的对齐
aside 标签的样式 flex 属性设置为 0 0 200px,表示侧边栏不缩小,基础宽度为 200px
.main 类中定义了主内容区域的样式,flex-grow 属性设置为 3,使其在可用空间中占据更多比例
-
Rem 布局
rem 布局的本质是等比缩放,一般是基于宽度
相对于根(html)的 font-size 大小来计算,如font-size:10px;,那么 1rem = 10px可以快速适用移动端布局,字体,图片高度
但是目前 ie 不支持
数据量可能很大,为了保证不同机型的适配,对于每一张图片,我们都需要给盒子一个准确的值 -
百分比布局
通过百分比单位可以使得浏览器中的组件的宽和高 随着浏览器的变化而变化,从而实现响应式的效果 -
浮动布局
当元素浮动以后可以向左或向右移动,直到它的外边缘碰到包含它的框或者另外一个浮动元素的边框为止
元素浮动以后会脱离正常的文档流,所以文档的普通流中的框就变的好像浮动元素不存在一样在图文混排的时候,浮动布局可以很好的使文字环绕在图片周围
但是浮动元素一旦脱离了文档流,就无法撑起父元素,会造成父级元素高度塌陷
JavaScript
数据类型
-
值类型(基本对象类型)
Number(数字)
String(字符串)
Boolean(布尔)
Symbol(符号)
null(空)
undefined(未定义)在内存中占据 固定大小,保存在 栈内存 中
-
引用类型(复杂对象类型)
Object(对象)
Function(函数)
Array(数组)
Date(日期)
RegExp(正则表达式)引用类型的值是 对象,保存在 堆内存 中
栈内存 存储的是 对象的变量标识符 以及对象在 堆内存中的存储地址 -
数据类型检测
-
typeof
typeof []返回 object
区分基本数据类型,但是会对 Object、Array、Null 三者都返回 object -
instanceof
[] instanceof Array返回 true
适合用于判断自定义的 类实例对象
不能判断 Number、String、Boolean 这三个基本数据类型 -
Object.prototype.toString.call()
1 2let obpt = Object.prototype.toString; obpt.call([]); // [object Array]能够精确返回数据类型
-
JS 垃圾回收机制
当某些代码操作造成 大量内存(堆/栈/上下文) 不能被合理释放
会导致页面性能会变得很慢,可能会造成内存泄漏
全局变量、闭包、DOM 元素的引用、定时器,这些都可能造成内存泄漏
-
浏览器垃圾回收机制/内存回收机制
自动垃圾回收机制 GC:Garbage Collecation
垃圾收集器会定期(周期性)找出那些 不再继续使用的变量,然后释放其内存标记清除,当变量进入执行环境时,被标记为“进入环境”,当变量离开执行环境时,会被标记为“离开环境”
垃圾回收器会销毁那些带标记的值并回收它们所占用的内存空间谷歌浏览器:不定时去 查找引用。当前内存如果没有被占用,浏览器会回收它;如果被占用,就不能回收
IE 浏览器:引用计数法。当前内存被占用一次,计数累加 1 次,移除占用就减 1,减到 0 时,浏览器就回收它
this
-
作为 普通函数 执行时,this 指向 window
-
当函数 作为对象的方法被调用 时,this 就会指向该对象
-
构造器调用,this 指向返回的这个对象
-
箭头函数的 this 绑定看的是 this 所在函数定义在哪个对象下,就绑定哪个对象
如果有嵌套的情况,则 this 绑定到最近的一层对象上 -
基于 Function.prototype 上的 apply 、 call 和 bind 调用模式
apply 接收参数的是数组,call 接受参数列表
bind 方法通过传入一个对象,返回一个 this 绑定了传入对象的新函数
原型 && 原型链
-
原型关系
每个 class 都有显式原型prototype
每个 实例 都有隐式原型__proto__
实例的__proto__指向对应 class 的prototype -
原型
在 JS 中,每当定义一个对象(函数也是对象)时,对象中都会包含一些 预定义的属性
其中每个函数对象都有一个 prototype 属性,这个属性指向函数的 原型对象 -
原型链
函数的原型链对象 constructor 默认指向函数本身
原型对象除了有原型属性外,为了实现 继承,还有一个原型链指针__proto__
该指针是指向上一层的原型对象,而上一层的原型对象的结构依然类似Object 原型对象用
Object.prototype.__ proto__ = null表示原型链顶端
如此形成了 js 的 原型链继承 -
new 运算符的实现机制
首先创建了一个新的空对象
设置原型,将对象的原型设置为函数的 prototype 对象
让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)
判断函数的返回值类型,如果是值类型,返回创建的对象;如果是引用类型,就返回这个引用类型的对象
函数和原型链
在 JavaScript 中
函数声明会提升(hoisting):这意味着即使函数在代码中后面被定义,它也可以在定义之前被调用
函数表达式(即使用 var 或 let/const 声明的函数)不会提升
|
|
原型链上的 a 方法(即 Foo.prototype.a)并没有被覆盖
它仍然存在,但是由于实例上的 a 方法(this.a)具有 更高的优先级
所以在调用实例的 a 方法时,原型链上的 a 方法不会被执行
EventLoop 事件循环
JS 是单线程的
为了防止一个函数执行时间过长阻塞后面的代码,所以会先将同步代码压入执行栈中,依次执行
将异步代码推入异步队列,异步队列又分为宏任务队列和微任务队列
因为宏任务队列的执行时间较长,所以微任务队列要优先于宏任务队列
-
宏任务(macrotask)
ajax、setTimeout、setInterval、setTmmediate(只兼容 ie)
script、requestAnimationFrame、messageChannel、UI 渲染、一些浏览器 api -
微任务(microtask)
promise.then、then、queueMicrotask(基于 then)
mutationObserver(浏览器提供)、messageChannel 、mutationObersve
JS 运行的环境一般为浏览器或者 Node
在浏览器环境中,有 JS 引擎线程和渲染线程,且两个线程互斥
Node 环境中,只有 JS 线程
-
事件环的运行机制
是由 JS 的宿主环境(浏览器)来实现的
先会执行栈中的内容
栈中的内容执行后执行微任务
微任务清空后再执行宏任务
先取出一个宏任务执行,再去执行微任务,然后在取宏任务清微任务这样不停的循环 -
事件循环步骤
函数先入栈,执行同步任务
当执行栈 Stack 中执行到异步任务的时候,就将它丢给 WebAPIs
接着继续执行同步任务,直到执行栈 Stack 为空
在此期间,WebAPIs 把微任务放到微任务队列,宏任务放到宏任务队列
执行栈 Stack 为空时,就去把微任务队列执行清空
微任务队列清空后,进入宏任务队列取第一项任务,将其放入 Stack 中执行
执行完成后,查看微任务队列是否有任务,有的话,清空微任务队列
再继续从宏任务中取一项任务执行,执行完成之后,继续清空微任务
如此反复循环,直至清空所有的任务
setTimeout、Promise、Async/Await
-
setTimeout settimeout 的回调函数放到宏任务队列里,等到执行栈清空以后执行
-
Promise Promise 本身是同步的立即执行函数
当在 executor 中执行 resolve 或者 reject 的时候, 此时是异步操作会先执行 then/catch 等,当主栈完成后,才会去调用 resolve/reject 中存放的方法执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26console.log("script start"); let promise1 = new Promise(function (resolve) { // 同步执行的,而 resolve 则是异步执行的 console.log("promise1"); resolve(); console.log("promise1 end"); }).then(function () { // 此处会放入微任务队列中 // 等待执行栈清空后再执行 console.log("promise2"); }); setTimeout(function () { // 会放入宏任务队列中 console.log("settimeout"); }); console.log("script end"); // 执行栈清空后,开始执行微任务队列的事件 // 输出顺序 // script start // promise1 // promise1 end // script end // promise2 // settimeout
async/await
async 函数会返回一个 Promise 对象
而 await 表达式用于等待一个 Promise 解决(resolve)
它会暂停 async 函数的执行直到等待的 Promise 被解决
然后继续执行 async 函数体内的剩余语句
|
|
同步代码 console.log(‘script start’); 被执行
async1 函数被调用,console.log(‘async1 start’); 被同步执行
遇到 await async2();,async2 函数被调用,console.log(‘async2’); 被同步执行
async1 函数暂停执行,控制权返回到调用栈
同步代码 console.log(‘script end’); 被执行,因为这是下一个同步操作
执行栈现在为空,事件循环开始处理微任务队列
async2 函数执行完毕,async1 函数恢复执行,console.log(‘async1 end’); 被同步执行
进程、线程和协程
-
进程
是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程
是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体
进程是一种抽象的概念,从来没有统一的标准定义进程由 内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程 组成
-
线程
是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位
一个进程可以有一个或多个线程,各个线程之间 共享 程序的内存空间(也就是所在进程的内存空间)
不同进程的线程间要利用 消息通信 的办法实现同步一个标准的线程由 线程 ID、当前指令指针(PC)、寄存器和堆栈 组成
-
协程
英文 Coroutines,是一种基于线程之上,但又比线程更加轻量级的存在
这种由程序员自己 写程序来管理的轻量级线程 叫做『用户空间线程』
具有 对内核来说不可见 的特性
| 进程 | 线程 |
|---|---|
| 拥有资源的基本单位 | 调度和分配的基本单位 |
| 进程之间可以并发执行 | 同一个进程的多个线程之间也可并发执行 |
| 拥有资源的一个独立单位 | 不拥有系统资源,但可以访问隶属于进程的资源 |
| 需要分配和回收资源,故开销较大 | 无,故开销小 |
| 进程之间不会互相影响 | 一个进程死掉就等于其内部所有的线程死掉 |
节流、防抖
-
节流
例如:点击按钮,第一次点击过后执行处理,之后在设定的时间内按钮不再可用 事件执行后,规定时间内,事件处理函数不能再次被调用
也就是说在规定的时间内,函数只能被调用一次,且是 最先被触发调用的那次滚动加载更多、搜索框远程搜索联想功能、高频点击、表单重复提交……
-
防抖
例如:输入框输入内容,在输入停顿后一会儿进行搜索联想,例如匹配对象。而不是每输入一个字符就进行联想
在规定时间内,用户只能执行一次事件;如果多次触发就 不断重置,重新从新触发的时间开始计时
规定时间过后可以再次执行邮箱验证输入检测、窗口大小 resize 变化后,再重新渲染
|
|
|
|
框架知识
对 Vue 和 React 框架的原理、生命周期、组件通信等方面进行了阐述。