天坑专业转行开始找实习啦,自己水平不够,边看别人的面经边总结相关的知识吧。
一. HTML/5
二. CSS/3
2.0 盒模型
2.1 有很多li标签且顺序不固定,怎么把最后一个class为b的li改为红色
<ul>
<li class="a" />
<li class="b" />
<li class="b" />
<li class="a" />
</ul>
思路1:使用伪类:last-child
:last-child 代表父元素的最后一个子元素。
li:last-child { background-color: xxx; }
拓展1:还有哪些常用伪类
//a标签专属
:link /*超链接未访问时的状态 鼠标放上去的时候 */
:visited /*超链接访问过后的状态 点击后 */
:hover /*鼠标悬停的状态 鼠标放上去的时候 */
:active /*激活状态,鼠标按下状态 点击的一瞬间 */
:focus /* 元素获取焦点的时候触发 */
//其他伪类
:first-child //表示在一组兄弟元素中的第一个元素
:first-of-type //表示一组兄弟元素中指定类型的第一个元素
:last-child //表示在一组兄弟元素中的最后一个元素
:last-of-type //表示一组兄弟元素中指定类型的最后一个元素
:not(selector) //一个否定伪类,用于匹配不符合参数选择器的元素
:nth-child //这个 CSS 伪类首先会找到当前元素的兄弟元素,然后按照位置的先后顺序从1开始排序,选择的结果为第(an+b)个元素的集合(n=0,1,2,3...)。如果 an+b 为 0,无法选中任何元素
:nth-of-type //与 nth-child 相似,不同之处在于它是只匹配特定类型的元素
:nth-last-child(an+b) //与 nth-child 相似,它是从最后一个子元素开始计数的
:nth-last-of-type //与 nth-of-type 相似,不同之处在于它是从最后一个子元素开始计数的
//伪元素选择器
/* 向前面追加文本 content属性里面添加内容 */
::before {
content: "before";
color: teal;
margin-right: 20px;
}
/* 向后面追加文本 content属性里面添加内容 */
::after {
content: "123456";
color: sienna;
}
::first-letter //选中某块级元素第一行的第一个字母,并且文字所处的行之前没有其他内容
::first-line //在某块级元素的第一行应用样式。
::selection //用于文档中被用户高亮的部分
2.2 有一个类似表格的布局,每个单元格的border为1px,相邻单元格中间的border也为1px怎么实现?如何实现选择某一单元格高亮?
A:从第二列开始margin-left: -1px, 第二排开始maigin-top: -1px;加z-index = 999实现。
2.3 多种方式实现上面100px下面自适应的布局
2.4 分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景
结构:
display:none: 会让元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击,
visibility: hidden:不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,不能点击
opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,只是内容不可见,可以点击
继承:
display: none和opacity: 0:是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示。
visibility: hidden:是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。
性能:
displaynone : 修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大
visibility:hidden: 修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容
opacity: 0 :修改元素会造成重绘,性能消耗较少
联系:它们都能让元素不可见
2.5 link
与@import
的区别
-
link
是 HTML 方式,@import
是 CSS 方式 -
link
最大限度支持并行下载,@import
过多嵌套导致串行下载,出现FOUC -
link
可以通过rel="alternate stylesheet"
指定候选样式 -
浏览器对
link
支持早于@import
,可以使用@import
对老浏览器隐藏样式 -
@import
必须在样式规则之前,可以在 css 文件中引用其他文件 -
总体来说:link 优于@import
2.6 display: block
和display: inline
的区别
block
元素特点:
1.处于常规流中时,如果width
没有设置,会自动填充满父容器 2.可以应用margin/padding
3.在没有设置高度的情况下会扩展高度以包含常规流中的子元素 4.处于常规流中时布局时在前后元素位置之间(独占一个水平空间) 5.忽略vertical-align
inline
元素特点:
1. 水平方向上根据direction
依次布局
2. 不会在元素前后进行换行
3. 受white-space
控制
4. margin/padding
在竖直方向上无效,水平方向上有效
5. width/height
属性对非替换行内元素无效,宽度由元素内容决定
6. 非替换行内元素的行框高由line-height
确定,替换行内元素的行框高由height
,margin
,padding
,border
决定
7. 浮动或绝对定位时会转换为block
8. vertical-align
属性生效
2.7 清除浮动
常用的一般为三种.clearfix
, clear:both
,overflow:hidden
;
2.8 display,float,position 的关系
display position float 之间的关系_BigDaddy233333的博客-CSDN博客_display float position关系
2.9 如何水平居中一个元素
-
如果需要居中的元素为常规流中 inline 元素,为父元素设置
text-align: center;
即可实现 -
如果需要居中的元素为常规流中 block 元素,1)为元素设置宽度,2)设置左右 margin 为 auto。3)IE6 下需在父元素上设置
text-align: center;
,再给子元素恢复需要的值 -
如果需要居中的元素为浮动元素,1)为元素设置宽度,2)
position: relative;
,3)浮动方向偏移量(left 或者 right)设置为 50%,4)浮动方向上的 margin 设置为元素宽度一半乘以-1 -
如果需要居中的元素为绝对定位元素,1)为元素设置宽度,2)偏移量设置为 50%,3)偏移方向外边距设置为元素宽度一半乘以-1
-
如果需要居中的元素为绝对定位元素,1)为元素设置宽度,2)设置左右偏移量都为 0,3)设置左右外边距都为 auto
2.10 BFC(block formatting context, 块级格式化上下文)
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
什么是BFC?看这一篇就够了_Leon的博客-CSDN博客_bfc
应用场景:
1.解决margin塌陷(上方浮动,下方外套一个div加overflow:hidden构成BFC)
2.自适应两栏布局 (左侧浮动,右侧元素加overflow:hidden构成BFC)
3.清除浮动(给父元素加overflow:hidden构成BFC)
2.11 Flex和inline-flex的区别
flex:父元素的尺寸不由子元素尺寸动态调整,不设置时默认是100%
inline-flex :则会使父元素尺寸跟随子元素们的尺寸动态调整
上面为flex,下面为inline-flex。
三. JavaScript/ECMAScript
3.1 在不改动原有api的前提下实现多参数加法
假如现在本地无法实现加法功能,有其他团队提供的api:
await asyncAdd = (a, b, (err, res) => {
利用网络请求实现a+b, 结果成功返回res
})
现需要改进该api, 利用其实现一个add方法,使其能够实现多个数组相加。
思路1:利用arguments分解多传入的参数,用reduce将两两依次送入api中计算并返回结果。
function asyncAdd(a, b){
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a+b)
}, 1000)
})
}
async function add(){
let arr = Array.prototype.slice.call(arguments)
const res = await arr.reduce((s, v) => {return s.then((res) => asyncAdd(res, v))}
, Promise.resolve(0))
return res;
}
add(1, 2, 3).then((res) => {
console.log(res)
})
3.2 bind/apply/call/new (原理and手写实现?)
3.3 函数闭包
3.4 ES6新增哪些特点
3.5 事件模型
3.6 原型链:手写instanceof
3.7 Promise,async/await
3.7.1 Promise如何一次进行多个异步请求
3.8 如何判断数据类型的多种方式,有什么区别,适用场景
3.9 事件循环、宏任务与微任务
3.10 深拷贝和浅拷贝
【面试题解】JavaScript的深浅拷贝,如何手写深拷贝? - 掘金
3.11 后端一次给10w条数据,如何优化?
https://juejin.cn/post/7031923575044964389
四. 计网等基础知识
4.1 前端性能优化,(能实际实现的)
1.减少HTTP的请求次数和传输报文的大小:svg图,图片延迟(懒)加载,合并页面css/js文件。
2.设置各种缓存、预处理和长连接机制:建立DNS缓存,做CDN分布,使用HTTP2协议实现多TCP通道共存。
3.代码方面的性能优化:减少闭包,避免使用iframe,减少对DOM的直接操作,低耦合高内聚,使用事件委托,函数防抖节流,尽可能减少选择器的层级,尽可能减少table布局...
暂时来不及看,先存着。
函数防抖节流 :
例子:避免鼠标滚动条多次触发事件(防抖)和一定时间之后自动触发事件(节流)
https://segmentfault.com/a/1190000018428170https://segmentfault.com/a/1190000018428170
4.2 用js操作dom,怎么判断DOM已经操作好了
思路1:HTML5新API
思路2:利用浏览器队列特性
4.3 网页请求至浏览器渲染的原理与过程
用户输入url到页面最后呈现有哪些过程:
-
用户输入URL地址
-
浏览器解析URL解析出主机名
-
浏览器将主机名转换成服务器ip地址(浏览器先查找本地DNS缓存列表 没有的话 再向浏览器默认的DNS服务器发送查询请求 同时缓存)
-
浏览器将端口号从URL中解析出来
-
浏览器建立一条与目标Web服务器的TCP连接(三次握手)
-
浏览器向服务器发送一条HTTP请求报文
-
服务器向浏览器返回一条HTTP响应报文
-
关闭连接 浏览器解析文档
-
如果文档中有资源 重复6 7 8 动作 直至资源全部加载完毕
-
解析HTML;
-
解析样式;
-
执行JavaScript;
-
布局;
-
绘制;
-
关于浏览器怎么解析获取的数据:
涉及到DOM和CSSOM的渲染以及JS的阻塞作用,回流和重绘
典型例子:
回流:整个页面重新绘制,都改变;display:none;
重绘:某个div重新绘制,只有它改变;visibility:hidden;
https://segmentfault.com/a/1190000010298038https://segmentfault.com/a/1190000010298038
4.4 计网书本相关问题
4.4.1 网络分层结构
计算机网络体系大致分为三种,OSI七层模型(应用、表示、会话、传输、网络、链路、物理)、TCP/IP四层模型(应用、传输、网络、链路)和五层模型(应用、传输、网络、链路、物理)。一般面试的时候考察比较多的是五层模型。
-
应用层:为应用程序提供交互服务。在互联网中的应用层协议很多,如域名系统DNS、HTTP协议、SMTP协议等。
-
传输层:负责向两台主机进程之间的通信提供数据传输服务。传输层的协议主要有传输控制协议TCP和用户数据协议UDP。
-
网络层:选择合适的路由和交换结点,确保数据及时传送。主要包括IP协议。
-
数据链路层:在两个相邻节点之间传送数据时,数据链路层将网络层交下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。
-
物理层:实现相邻节点间比特流的透明传输,尽可能屏蔽传输介质和物理设备的差异。
4.4.2 三次握手/四次挥手
https://blog.csdn.net/qq_38950316/article/details/81087809
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
【问题3】为什么不能用两次握手进行连接?
【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?
4.4.3 TCP/UDP对比
TCP的特点:
-
TCP是面向连接的运输层协议。
-
点对点,每一条TCP连接只能有两个端点。
-
TCP提供可靠交付的服务。
-
TCP提供全双工通信。
-
面向字节流。
对比:
-
TCP面向连接;UDP是无连接的,即发送数据之前不需要建立连接。
-
TCP提供可靠的服务;UDP不保证可靠交付。
-
TCP面向字节流,把数据看成一连串无结构的字节流;UDP是面向报文的。
-
TCP有拥塞控制;UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如实时视频会议等)。
-
每一条TCP连接只能是点到点的;UDP支持一对一、一对多、多对一和多对多的通信方式。
-
TCP首部开销20字节;UDP的首部开销小,只有8个字节。
4.4.4 HTTP协议的特点
-
HTTP允许传输任意类型的数据。传输的类型由Content-Type加以标记。
-
无状态。对于客户端每次发送的请求,服务器都认为是一个新的请求,上一次会话和下一次会话之间没有联系。
-
支持客户端/服务器模式。
4.4.5 HTTP报文格式
HTTP请求由请求行、请求头部、空行和请求体四个部分组成。
-
请求行:包括请求方法,访问的资源URL,使用的HTTP版本。
GET
和POST
是最常见的HTTP方法,除此以外还包括DELETE、HEAD、OPTIONS、PUT、TRACE
。 -
请求头:格式为“属性名:属性值”,服务端根据请求头获取客户端的信息,主要有
cookie、host、connection、accept-language、accept-encoding、user-agent
。 -
请求体:用户的请求数据如用户名,密码等。
HTTP响应也由四个部分组成,分别是:状态行、响应头、空行和响应体。
-
状态行:协议版本,状态码及状态描述。
-
响应头:响应头字段主要有
connection、content-type、content-encoding、content-length、set-cookie、Last-Modified,、Cache-Control、Expires
。 -
响应体:服务器返回给客户端的内容。
4.4.6 HTTP状态码
- 1开头的:信息,服务器收到请求,需要请求者继续执行操作
- 2开头的:成功,操作被成功接收并处理
200:OK,请求成功。一般用于GET与POST请求。
201:Created,已创建,成功请求并创建了新的资源。
202:Accepted,已接受,已经接受请求,但未处理完成。
204:No Content,无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档。
- 3开头的:重定向,需要进一步的操作以完成请求
300:Multiple Choices,多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择。
301:Moved Permanently,永久移动,请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替。
302:Found,临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI。
303:See Other,由于请求对应的资源存在着另一个 URI,应使用 GET方法定向获取请求的资源。
304:Not Modified,未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源。
- 4开头的:客户端错误,请求包含语法错误或无法完成请求
400:bad request,请求报文存在语法错误。
401:unauthorized,需要认证(第一次返回)或者认证失败(第二次返回)。
403:forbidden,请求被服务器拒绝了。
404:not found,服务器上无法找到请求的资源。
- 5开头的:服务器错误,服务器在处理请求的过程中发生了错误
500:Internal Server Error,服务器内部错误,无法完成请求。
501:Not Implemented,服务器不支持请求的功能,无法完成请求。
502:Bad Gateway,作为网关或者代理工作的服务器尝试请求时,从远程服务器收到了一个无效的响应。一般是因为连接超时,我们向服务器发送请求,由于服务器当前链接太多,导致服务器方面无法给于正常的响应,产生此类报错。
503:Service Unavaliable,服务器超载挂掉了。
504:Gateway Time-out, 充当网关或代理的服务器,未能及时从远端服务器获取请求。
4.4.7 HTTP1.0/1.1/2.0的区别
-
长连接:HTTP1.0默认使用短连接,每次请求都需要建立新的TCP连接,连接不能复用。HTTP1.1支持长连接,复用TCP连接,允许客户端通过同一连接发送多个请求。不过,这个优化策略也存在问题,当一个队头的请求不能收到响应的资源时,它将会阻塞后面的请求。这就是“队头阻塞”问题。
-
断点续传:HTTP1.0 不支持断点续传。HTTP1.1 新增了 range 字段,用来指定数据字节位置,支持断点续传。
-
错误状态响应码:在HTTP1.1中新增了24个错误状态响应码,如
409(Conflict)
表示请求的资源与资源的当前状态发生冲突、410(Gone)
表示服务器上的某个资源被永久性的删除。 -
Host头处理:在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名。到了HTTP1.1时代,虚拟主机技术发展迅速,在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP地址,故HTTP1.1增加了HOST信息。
HTTP2.0相比HTTP1.1支持的特性:
-
新的二进制格式:HTTP1.1 基于文本格式传输数据;HTTP2.0采用二进制格式传输数据,解析更高效。
-
多路复用:在一个连接里,允许同时发送多个请求或响应,并且这些请求或响应能够并行的传输而不被阻塞,避免 HTTP1.1 出现的”队头堵塞”问题。
-
头部压缩,HTTP1.1的header带有大量信息,而且每次都要重复发送;HTTP2.0 把header从数据中分离,并封装成头帧和数据帧,使用特定算法压缩头帧,有效减少头信息大小。并且HTTP2.0在客户端和服务器端记录了之前发送的键值对,对于相同的数据,不会重复发送。比如请求a发送了所有的头信息字段,请求b则只需要发送差异数据,这样可以减少冗余数据,降低开销。
-
服务端推送:HTTP2.0允许服务器向客户端推送资源,无需客户端发送请求到服务器获取。
HTTPS与HTTP的区别?
-
HTTP是超文本传输协议,信息是明文传输;HTTPS则是具有安全性的ssl加密传输协议。
-
HTTP和HTTPS用的端口不一样,HTTP端口是80,HTTPS是443。
-
HTTPS协议需要到CA机构申请证书,一般需要一定的费用。
-
HTTP运行在TCP协议之上;HTTPS运行在SSL协议之上,SSL运行在TCP协议之上
4.4.8 数字证书
服务端可以向证书颁发机构CA申请证书,以避免中间人攻击(防止证书被篡改)。证书包含三部分内容:证书内容、证书签名算法和签名,签名是为了验证身份。
服务端把证书传输给浏览器,浏览器从证书里取公钥。证书可以证明该公钥对应本网站。
数字签名的制作过程:
-
CA使用证书签名算法对证书内容进行hash运算。
-
对hash后的值用CA的私钥加密,得到数字签名。
浏览器验证过程:
-
获取证书,得到证书内容、证书签名算法和数字签名。
-
用CA机构的公钥对数字签名解密(由于是浏览器信任的机构,所以浏览器会保存它的公钥)。
-
用证书里的签名算法对证书内容进行hash运算。
-
比较解密后的数字签名和对证书内容做hash运算后得到的哈希值,相等则表明证书可信。
4.4.9 HTTPS原理
4.4.10 DNS解析过程?DNS查询方式有几种?
解析过程
-
浏览器搜索自己的DNS缓存
-
若没有,则搜索操作系统中的DNS缓存和hosts文件
-
若没有,则操作系统将域名发送至本地域名服务器,本地域名服务器查询自己的DNS缓存,查找成功则返回结果,否则依次向根域名服务器、顶级域名服务器、权限域名服务器发起查询请求,最终返回IP地址给本地域名服务器
-
本地域名服务器将得到的IP地址返回给操作系统,同时自己也将IP地址缓存起来
-
操作系统将 IP 地址返回给浏览器,同时自己也将IP地址缓存起来
-
浏览器得到域名对应的IP地址
查询方式
4.4.11 Cookie、sessionStorage、localStorage的区别
cookie和session的区别:
-
作用范围不同,Cookie 保存在客户端,Session 保存在服务器端。
-
有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
-
隐私策略不同,Cookie 存储在客户端,容易被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
-
存储大小不同, 单个 Cookie 保存的数据不能超过 4K;对于 Session 来说存储没有上限,但出于对服务器的性能考虑,Session 内不要存放过多的数据,并且需要设置 Session 删除机制。
-
Cookie:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下,存储的大小很小只有4K左右。(key:可以在浏览器和服务器端来回传递,存储容量小,只有大约4K左右)
-
sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持,localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。(key:本身就是一个回话过程,关闭浏览器后消失,session为一个回话,当页面不同即使是同一页面打开两次,也被视为同一次回话)
-
localStorage:localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。(key:同源窗口都会共享,并且不会失效,不管窗口或者浏览器关闭与否都会始终生效)
补充说明一下cookie的作用:
-
保存用户登录状态。例如将用户id存储于一个cookie内,这样当用户下次访问该页面时就不需要重新登录了,现在很多论坛和社区都提供这样的功能。cookie还可以设置过期时间,当超过时间期限后,cookie就会自动消失。因此,系统往往可以提示用户保持登录状态的时间:常见选项有一个月、三个 月、一年等。
-
跟踪用户行为。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气情况。如果每次都需要选择所在地是烦琐的,当利用了 cookie后就会显得很人性化了,系统能够记住上一次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区的天气情况。因为一切都是在后 台完成,所以这样的页面就像为某个用户所定制的一样,使用起来非常方便
-
定制页面。如果网站提供了换肤或更换布局的功能,那么可以使用cookie来记录用户的选项,例如:背景色、分辨率等。当用户下次访问时,仍然可以保存上一次访问的界面风格。
4.4.12 什么是对称加密和非对称加密?
对称加密:通信双方使用相同的密钥进行加密。特点是加密速度快,但是缺点是密钥泄露会导致密文数据被破解。常见的对称加密有AES
和DES
算法。
非对称加密:它需要生成两个密钥,公钥和私钥。公钥是公开的,任何人都可以获得,而私钥是私人保管的。公钥负责加密,私钥负责解密;或者私钥负责加密,公钥负责解密。这种加密算法安全性更高,但是计算量相比对称加密大很多,加密和解密都很慢。常见的非对称算法有RSA
和DSA
。
4.4.13 为什么有ip了还需要mac地址
https://www.zhihu.com/question/21546408/answer/28155896
4.4.14 滑动窗口及其实现
解析TCP之滑动窗口(动画演示)_taoqilin的专栏-CSDN博客
简单来说,接收端窗口左端确认就可以把自己的窗口右移,根据累计确认原理,如果整个窗口都满了就整个右移动,发送端则必须要等收到当前窗口的最后一位的ACK才能右移。
4.4.15 PUT和POST的区别
首先,都是向服务端发送数据。其次,POST主要作用在一个集合资源之上的(url),而PUT主要作用在一个具体资源之上的(url/xxx),因此可以理解POST为创建,PUT为更新(一个页面)。POST经常用于提交表单,PUT如果是提交到某个特定的url,而url不存在,则会新增这个url的内容。因此,PUT为幂等性的,POST为非幂等的(即多次操作的副作用不一定相同)。
4.5 前端缓存
前端缓存分为强缓存和协商缓存两种。
4.5.1 强缓存
强缓存主要使用Expires、Cache-Control 两个头字段,两者同时存在Cache-Control 优先级更高。当命中强缓存的时候,客户端不会再请求,直接从缓存中读取内容,并返回HTTP状态码200。
- Expires
响应头,代表该资源的过期时间。是一个GMT 格式的标准时间。
当客户端请求服务器的时候,服务器会返回资源的同时还会带上响应头Expires,表示资源的过期具体时间,如果客户端在过期时间之前再次获取该资源,就不需要再请求我服务器了,可以直接在缓存里面拿。
使用Expires强缓存优点:
-
在过期时间以内,为用户省了很多流量。
-
减少了服务器重复读取磁盘文件的压力。
使用Expires强缓存缺点
-
缓存过期以后,服务器不管文件有没有变化会再次请求服务器。
-
缓存过期时间是一个具体的时间,这个时间依赖于客户端的时间,如果时间不准确或者被改动缓存也会随之受到影响。
- Cache-Control
请求/响应头,缓存控制字段,精确控制缓存策略。
为了让强缓存更精确,HTTP1.1增加了Cache-Control字段。Cache-Control既能出现在请求头又能出现在响应头,其不同的值代表不同的意思,下面我们具体分析一下。
Cache-Control 服务端参数:
-
max-age: 在多少秒内有效,是一个相对时间,这样比Expires具体的时间就更精确了。当为0的时候就是不使用强缓存,类似no-cache。
-
s-maxage: 就是用于表示 cache 服务器上(比如 cache CDN,缓存代理服务器)的缓存的有效时间的,并只对 public 缓存有效。
-
no-cache:不使用本地强缓存。需要使用缓存协商。
-
no-store:直接禁止浏览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
-
public:可以被所有的用户缓存,包括终端用户和中间代理服务器。
-
private:只能被终端用户的浏览器缓存,不允许中间缓存代理进行缓存。(这个是默认值)
Cache-Control 客户端参数:
-
max-stale: 5 表示客户端到代理服务器上拿缓存的时候,即使代理缓存过期了也不要紧,只要过期时间在 5 秒之内,还是可以从代理中获取的。
-
min-fresh: 5 表示代理缓存需要一定的新鲜度,不要等到缓存刚好到期再拿,一定要在到期前 5 秒之前的时间拿,否则拿不到。
-
only-if-cached 这个字段加上后表示客户端只会接受代理缓存,而不会接受源服务器的响应。如果代理缓存无效,则直接返回 504(Gateway Timeout)。
4.5.2 协商缓存
协商缓存主要有四个头字段,它们两两组合配合使用,If-Modified-Since 和 Last-Modified一组,Etag 和 If-None-Match一组,当同时存在的时候会以Etag 和 If-None-Match为主。当命中协商缓存的时候,服务器会返回HTTP状态码304,让客户端直接从本地缓存里面读取文件。
- If-Modified-Since
请求头,资源最近修改时间,由浏览器告诉服务器。其实就是第一次访问服务端返回的Last-Modified的值。
- Last-Modified
响应头,资源最近修改时间,由服务器告诉浏览器。
- Etag
响应头,资源标识,由服务器告诉浏览器。
- If-None-Match
请求头,缓存资源标识,由浏览器告诉服务器。其实就是第一次访问服务端返回的Etag的值。
Last-Modified 和 If-Modified-Since
当客户端第一次请求服务器的时候,服务端会返回一个Last-Modified响应头,该字段是一个标准时间。客户端请求服务器的时候会带上If-Modified-Since请求头字段,该字段的值就是服务器返回的Last-Modified的值。服务器接收到请求后会比较这两个值是否一样,一样就返回304,让客户端从缓存中读取,不一样就会返回新文件给客户端并更新Last-Modified响应头字段的值。
使用If-Modified-Since 和 Last-Modified的优点:
-
当缓存有效时服务器不会返回文件给客户端,而是直接返回304状态码,让客户端从缓存中获取文件。大大节省了流量和带宽以及服务器的压力。
使用If-Modified-Since 和 Last-Modified的缺点:
-
Last-Modified 过期时间只能精确到秒。如果在同一秒既修改了文件又获取文件,客户端是获取不到最新文件的。
Etag 和 If-None-Match
为了解决文件修改时间只能精确到秒带来的问题,我们引入 Etag 响应头。Etag 是由文件修改时间与文件大小计算而成,只有当文件文件内容或修改时间变了Etag的值才会发生变化。
当客户端第一次请求服务器的时候,服务端会返回一个Etag响应头。客户端请求服务器的时候会带上If-None-Match请求头字段,该字段的值就是服务器返回的Etag的值。服务器接收到请求后会比较这两个值是否一样,一样就返回304,让客户端从缓存中读取,不一样就会返回新文件给客户端并更新Etag响应头字段的值。
使用Etag 和 If-None-Match的优点:
-
当缓存有效时服务器不会返回文件给客户端,而是直接返回304状态码,让客户端从缓存中获取文件。大大节省了流量和带宽以及服务器的压力。
-
并且解决了一秒内修改并读取的问题。
4.6 Socket
Socket原理讲解_Tony-jiang的博客-CSDN博客_socket
五. React, axios, koa2等框架相关
5.1 React中有哪几种组件
无状态组件、有状态组件、容器组件、高阶组件、回调组件
React组件五种形式的详细介绍:
例如自己写的Todo List里面,footer部分的全选和清除所有就只接受属性,属于无状态组件,App.js作为储存todo内容的state就是容器组件,其他部分自己也有状态,所以是有状态组件。
5.2 如何实现组件,前端组件的设计原则?
5.3 React 生命周期
5.3.1 (生命周期)看代码写输出
class Example extends React.Component {
constructor() {
super();
this.state = {
val: 0
};
}
componentDidMount() {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 1 次 log
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 2 次 log
setTimeout(() => {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 3 次 log
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 4 次 log
}, 0);
}
render() {
return null;
}
};
1、第一次和第二次都是在 react 自身生命周期内,触发时 isBatchingUpdates 为 true,所以并不会直接执行更新 state,而是加入了 dirtyComponents,所以打印时获取的都是更新前的状态 0。
2、两次 setState 时,获取到 this.state.val 都是 0,所以执行时都是将 0 设置成 1,在 react 内部会被合并掉,只执行一次。设置完成后 state.val 值为 1。
3、setTimeout 中的代码,触发时 isBatchingUpdates 为 false,所以能够直接进行更新,所以连着输出 2,3。
输出: 0 0 2 3
5.4 React Router
5.5 React Hooks相关
5.5.1 为什么要用Hook
5.5.2 常用Hook有哪些
5.5.3 使用useEffect怎么清除副作用
5.6 MVC/MVVM模型
5.7 对比React/Vue/Angular
5.8 虚拟DOM、Diff算法
5.9 受控组件,非受控组件
https://blog.csdn.net/qq_41846861/article/details/86598797
5.8.1 写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么?
vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点。在vue的diff函数中(建议先了解一下diff算法过程)。
在交叉对比中,当新节点跟旧节点头尾交叉对比
没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key => index 的map映射)。如果没找到就认为是一个新增节点。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点。一种一个map映射,另一种是遍历查找。相比而言。map映射的速度更快。
5.9 React 中 setState 什么时候是同步的,什么时候是异步的?
在React中,如果是由React引发的事件处理(比如通过onClick引发的事件处理),调用setState不会同步更新this.state,除此之外的setState调用会同步执行this.state。所谓“除此之外”,指的是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生的异步调用。
原因:在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是,有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state。
六. Node.js, webpack, sql, mongodb等后端和工程化相关
6.1 webpack原理、基本配置
6.2 koa的洋葱圈模型