缓存相关
本地存储与 cookie 的区别
Cookie 是小甜饼的意思。顾名思义,cookie 确实非常小,它的大小限 制为 4KB 左右。它的主要用途有保存登录信息,比如你登录某个网站市 场可以看到“记住密码”,这通常就是通过在 Cookie 中存入一段辨别用 户身份的数据来实现的
localStorage
localStorage 是 HTML5 标准中新加入的技术,它并不是什么划时代的 新东西。早在 IE 6 时代,就有一个叫 userData 的东西用于本地存储, 而当时考虑到浏览器兼容性,更通用的方案是使用 Flash。而如今, localStorage 被大多数浏览器所支持,如果你的网站需要支持 IE6+, 那以 userData 作为你方案是种不错的选择
sessionStorage
sessionStorage 与 localStorage 的接口类似,但保存数据的生命周期 与 localStorage 不同。做过后端开发的同学应该知道 Session 这个词 的意思,直译过来是“会话”。而 sessionStorage 是一个前端的概念, 它只是可以将一部分数据在当前会话中保存下来,刷新页面数据依旧存 在。但当页面关闭后,sessionStorage 中的数据就会被清空。
三者的异同
特性Cookie localStorage sessionStorage 数据的生命期 一般由服务器生成,可设置失效时间。如果在浏览器端生成 Cookie,默 认是关闭浏览器后失效 除非被清除,否则永久保存 仅在当前会话下有效,关闭页面或浏览器后被清除
存放数据大小
4K 左右 一般为 5MB 与服务器端通信 每次都会携带在 HTTP 头中,如果使用 cookie 保存过多数据会带来性能 问题仅在客户端(即浏览器)中保存,不参与和服务器的通信 易用性 需要程序员自己封装,源生的 Cookie 接口不友好 源生接口可以接受,亦可再次封装来对 Object 和 Array 有更好的支持
http相关
http特性
HTTP0.9 特性
- 没有请问头和请求体只有请求行
- 只能发送html文件
HTTP1.0 特性
- 可以发送javaScript、CSS、图片、音频
- 加上请求头和请求体
- 状态码
- cache 机制可传参
- 每进行一次 HTTP 通信,都需要经历建立 TCP 连接、传输 HTTP 数据和断开 TCP 连接三个阶段
HTTP1.1 特性
- 持久连接的方法,它的特点是在一个 TCP 连接上可以传输多个 HTTP 请求,只要浏览器或者服务器没有明确断开连接,那么该 TCP 连接会一直保持(提高性能)
- 持久连接虽然能减少 TCP 的建立和断开次数,但是它需要等待前面的请求返回之后,才能进行下一次请求。如果 TCP 通道中的某个请求因为某些原因没有及时返回,那么就会阻塞后面的所有请求,这就是著名的队头阻塞的问题(在 HTTP 1.1 中,每一个链接都默认是长链接,因此对于同一个 TCP 链接,HTTP 1.1 规定:服务端的响应返回顺序需要遵循其接收到相应的顺序。但这样存在一个问题:如果第一个请求处理需要较长时间,响应较慢,将会“拖累”其他后续请求的响应,这是一种队头阻塞。)
- 引入了 Cookie、虚拟主机的支持、对动态内容的支持
- 浏览器为每个域名最多同时维护 6 个 TCP 持久连接(提高性能)
- 使用 CDN 的实现域名分片机制。(提高性能)
- 对带宽的利用率却并不理想(tcp 启动慢、头部堵塞、tcp 竞争)
HTTP2 特点
- 只使用一个 TCP 长连接来传输数据,实现资源的并行请求,也就是任何时候都可以将请求发送给服务器,解决头部堵塞(多路复用)
- 二进制传输
- 多路复用(原理二进制分帧层,携带id的帧流到服务器)
- 头部压缩
- 头部被压缩,减少了数据传输
- 服务端推送
- 有了二进制分帧层还能够实现请求的优先级、服务器推送、头部压缩等特性,从而大大提升了文件传输效率
- 但是HTTP2还是会存在 tcp 堵塞(理解,http 堵塞就是需要等待前面的http包发送完成而造成的等待,tcp 堵塞是TCP 传输过程中,由于单个数据包的丢失而造成的阻塞)
HTTP3
QUIC 看成是集成了“TCP+HTTP/2 的多路复用 +TLS 等功能
TCP与UDP的区别
1、基于连接与无连接;
2、对系统资源的要求(TCP较多,UDP少);
3、UDP程序结构较简单;
4、流模式与数据报模式 ;
5、TCP保证数据正确性,UDP可能丢包;
6、TCP保证数据顺序,UDP不保证。
TCP 握手过程
- 建立tcp链接(三次握手,客户端发送 syn=j 给服务端然后处于 syn_send 状态;
- 服务端接受到syn,然后发送自己的syn包syn=k,和 ack=j+1(确认客户端包),状态为 syn_recv;
- 客户端收到ack和syn则发送 ack=k+1给服务端表示确认,服务端和客户端都进入了establish状态),
- 为什么要3次握手:确认客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常
HTTP 缓存
强缓存(浏览器内部完成)
max-age:数值,单位是秒,从请求时间开始到过期时间之间的秒数。基于请求时间(Date字段)的相对时间间隔,而不是绝对过期时间
expires:和max-age一样指缓存过期时间,但是他的指定了具体时间GMT格式,HTTP/1.1,Expire已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存则会直接失效,这样的话强制缓存的存在则毫无意义
协商缓存(需要询问服务器)Last-Modified/If-Modified-Since(服务端时间对比):本地文件在服务器上的最后一次修改时间。缓存过期时把浏览器端缓存页面的最后修改时间发送到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行对比,如果时间一致,那么返回304,客户端就直接使用本地缓存文件。(浏览器最后修改时候和服务端对比,如果一致则走缓存)
问题:
1. 现在大多数服务端都采用了负载均衡策略,可能导致不同虚拟主机返回的Last-Modified时间戳不一致,导致对比失败~
2. 文件也许会周期性的更改,但是他的内容并不改变,不希望客户端重新getEtag/If-None-Match:(EntityTags,内容摘要)是URL的tag,用来标示URL对象是否改变,一般为资源实体的哈希值。和Last-Modified类似,如果服务器验证资源的ETag没有改变(该资源没有更新),将返回一个304状态告诉客户端使用本地缓存文件。Etag的优先级高于Last-Modified,Etag主要为了解决 Last-Modified无法解决的一些问题。
文件缓存策略
1. 有文件指纹:index.html 用不用缓存,其他用强缓存+文件指纹
2. 无指纹:index.html 用不用缓存,其他用协商etag缓存(文件变了就缓存)
浏览器渲染相关
一个页面从输入 URL 到页面加载显示完成,这个过程中都 发生了什么?
1、HTTP 请求准备阶段
- 构建请求--浏览器构建请求行信息,准备发起网络请求 GET /index.html HTTP1.1
- 查找缓存--如果浏览器发现请问资源在浏览器中存在副本,根据强缓存规则,如没有过期那么直接返回资源,如何查找失败进入下一个环节:
--准备 ip 地址和端口
--DNS(域名和ip的映射系统) 域名解析,拿到ip之后找端口,默认为80
--建立tcp链接(三次握手)
--如果是https 还需要建立TLS连接
2、HTTP 发送请求
浏览器向服务端发起http请求,把请求头和请求行一起发送个服务器,服务端解析请求头如发现cache-control和etag(if-none-match),if-modified(if-modified-since)字段就会判断缓存是否过期,如果没有返回304,否则返回200
3、HTTP 响应返回
- 浏览器拿到响应数据,首先判断是否是4XX或者5XX是就报错,如果是3XX就重定向,2XX就开始解析文件,如果是gzip就解压文件
- TCP断开连接
- 4次挥手
- 浏览器解析渲染
- 建立根据html建立dom树和css树,如果遇到script首选判断是否defer和async否则会阻塞渲染并编译执行js,如果没有则组合生成render tree,最后浏览器开启GPU进行绘制合成图层,将内容显示屏幕。
css相关
画一条 0.5px 的线
方式一:采用 meta viewport 的方 式
方式二:采用 border-image 的方 式 采用 transform: scale() 的方式
css盒子模型
margin、border、padding\content
默认情况盒子的width和height设置只是跟content的宽高
真正宽:内容宽度+左右填充+左右边距+左右边框
真正的高:内容高度+上下填充+上下边距+上下边框
css3新特性
边框:
border-radios 添加圆角边框
border-shadow:给框添加阴影 (水平位移,垂直位移,模糊半径,阴 影尺寸,阴影颜色,insetr(内/外部阴影))
border-image:设置边框图像
border-image-source 边框图片的路径
border-image-slice 图片边框向内偏移
border-image-width 图片边框的宽度
border-image-outset 边框图像区域超出边框的量
border-image-repeat 图像边框是否平铺(repeat 平铺 round 铺满 stretch 拉伸)
背景:
Background-size 背景图片尺寸
Background-origin规定
background-position属性相对于什么位置定位
Background-clip 规定背景的绘制区域(padding-box,border-box, content-box)
渐变:
Linear-gradient()线性渐变
Radial-gradient()径向渐变
文本效果:
Word-break:定义如何换行
Word-wrap:允许长的内容可以自动换行
Text-overflow:指定当文本溢出包含它的元素,应该干啥
Text-shadow:文字阴影(水平位移,垂直位移,模糊半径,阴影颜色)
转换:
Transform 应用于 2D3D 转换,可以将元素旋转,缩放,移动,倾斜
Transform-origin 可以更改元素转换的位置,(改变 xyz 轴)
Transform-style 指定嵌套元素怎么样在三位空间中呈现
2D 转换方法:
rotate 旋转 translate(x,y)指定元素在二维空间的位移 scale(n) 定义缩放转换
3D 转换方法:
Perspective(n)为 3D 转换 translate rotate scale
过渡:
Transition-proprety 过渡属性名
Transition-duration 完成过渡效果需要花费的时间
Transition-timing-function 指定切换效果的速度
Transition-delay 指定什么时候开始切换效果
动画:
animation Animation-name 为@keyframes 动画名称
animation-duration 动画需要花费的时间
animation-timing-function 动画如何完成一个周期
animation-delay 动画启动前的延迟间隔
animation-iteration-count 动画播放次数
animation-direction 是否轮流反向播放动画
JS 动画和 css3 动画的差异性
渲染线程分为 main thread 和 compositor thread,如果 css 动画 只 改 变 transform 和 opacity , 这 时 整 个 CSS 动 画 得 以 在 compositor trhead 完成(而 JS 动画则会在 main thread 执行, 然后出发 compositor thread 进行下一步操作),特别注意的是如果 改变 transform 和 opacity 是不会 layout 或者 paint 的。
区别:功能涵盖面,JS 比 CSS 大 实现/重构难度不一,CSS3 比 JS 更加简单,性 能跳优方向固定对帧速表现不好的低版本浏览 器,css3 可以做到自然降级 css 动画有天然事件支持 css3 有兼容性问题
React源码
react 组件之间的数据传递
正向传值用 props 逆向传值用函数传值 通过事件调用函数传递 同级传值用 pubsub-js 用 pubsub.publish(事件名,数据)抛出数据 用 pubsub.subscribe(监听的事件,()=){})接收数据 跨组件传递 用 context 要使用 context 进行跨组件传值就需要使用 createContext() 方 法 , 这 个 方 法 有 两 个 对 象 provider 生 产者 Consumer 消费者
调用 setState 之后发生了什么
React 在调用 setstate 后,react 会将传入的参数对象和组件当前的状态 合并,触发调和过程, 在调和过程中,react 会根据新的状态构建 react 元素树重新渲染整个 UI 界面,在得到元素树之后,react 会自动计算新老节点的差异,根据差 异对界面进行最小化重新渲染
react 生命周期函数
componentWillMount 组件渲染之前调用
componentDidMount 在第一次渲染之后调用
componentWillReceiveProps 在组件接收到一个新的 props 时调用shouldComponentUpdate 判断组件是否更新 html
componentWillupdate 组件即将更新 html 时调用
componentDidupdate 在组件完成更新后立即调用
componentWillUnmount 在组件移除之前调用
为什么虚拟 dom 会提高性能?
虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能
请简述虚拟 dom 与 diff 算法
虚拟DOM也就是常说的虚拟节点,它是通过js的object对象模拟DOM 中的节点,然后再通过特定的渲染方法将其渲染成真实的 DOM 节点。频繁的操作 DOM,或大量造成页面的重绘和回流Diff 算法:把树形结构按照层级分解,只比较同级元素,给列表结构的 每个单元添加唯一的 key 值,方便比较
diff 原理
tree diff web UI 中 dom 节点跨层级的移动操作特别少,可以忽略不计
component diff 拥有相同类的两个组件将会生成相似的树形结构,拥有 不同类的两个组件会生成不同的树形结构
element diff 对于同一层级的一组子节点,他们可以通过唯一的 id 进行 区分
何为高阶组件(higher order component)?
高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。最常见的可能是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC 最好 的方式是共享 React 组件之间的行为。如果你发现你在不同的 地方写了大量代码来做同一件事时,就应该考虑将代码重构为可 重用的 HOC。
vue源码
vue 中 keep-alive 的理解?
概念:
keep-alive 是 vue 的内置组件,当它动态包裹组件时,会缓存不 活动的组件实例,它自身不会渲染成一个 DOM 元素也不会出现在父组 件链中
作用:
在组件切换过程中将状态保留在内存中,防止重复渲染 DOM,减 少加载时间以及性能消耗,提高用户体验。生命周期函数:Activated 在 keep-alive 组件激活时调用,deactivated 在 keep-alive 组件停用时调用
Vue 组件中的 data 为什么是函数
Data 是一个函数时,每个组件实例都有自己的作用域,每个实例相互独 立,不会相互影响
如果是引用类型(对象),当多个组件共用一个数据源时,一处数据改变, 所有的组件数据都会改变,所以要利用函数通过 return 返回对象的拷贝, (返回一个新数据),让每个实例都有自己的作用域,相互不影响。
组件中写 name 选项有什么作用?
项目使用 keep-alive 时,可搭配组件 name 进行缓存过滤
DOM 做递归组件时需要调用自身 name
vue-devtools 调试工具里显示的组见名称是由vue中组件name决定的
Vue 双向绑定的原理
Vue2 双向绑定就是:数据变化更新视图,视图变化更新数据 Vue 数据双向绑定是通过数据劫持和观察者模式来实现的, 数据劫持,object.defineproperty 它的目的是:当给属性赋值的时候, 程序可以感知到,就可以控制改变属性值 观察者模式 当属性发生改变的时候,使用该数据的地方也发生改变
vue3使用了proxy。
proxy优点:
1、直接监听对象而非属性
2、直接监听数组的变化
3、拦截的方式有很多种(有13种,set,get,has)
4、Proxy返回一个新对象,可以操作新对象达到目的
proxy缺点:
1、 proxy有兼容性问题,不能用polyfill来兼容(polyfill主要抚平不同浏览器之间对js实现的差异)
说说对 proxy 的理解
vue 的数据劫持有两个缺点: 1、无法监听通过索引修改数组的值的变化 2、无法监听 object 也就是对象的值的变化所以 vue2.x 中才会有 $set 属性的存在
proxy 是 es6 中推出的新 api,可以弥补以上两个缺点,所以 vue3.x 版本用 proxy 替换 object.defineproperty
计算属性与 watch 区别
Computed watch 区别就是 computed 的缓存功能,当无关数据数 据改变时,不会重新计算,直接使用缓存中的值。计算属性是用来声明 式的描述一个值依赖了其他的值,当所依赖的值后者变量发生变化时, 计算属性也跟着改变, Watch 监听的是在 data 中定义的变量,当该变量变化时,会触发 watch 中的方法
Route 与 router 区别
1. router 是 VueRouter 的一个对象,通过 Vue.use(VueRouter)和 VueRouter 构造函数得到一个 router 的实例对象,这个对象中是一个全 局的对象,他包含了所有的路由包含了许多关键的对象和属性。
2.route 是一个跳转的路由对象,每一个路由都会有一个 route 对象,是 一个局部的对象,可以获取对应的 name,path,params,query 等
Vue 的 nextTick 的原理是什么?
1)为什么需要 nextTick
Vue 是异步修改 DOM 的并且不鼓励开发者直接接触 DOM,但有时候业务需要必须对数据更改--刷新后的 DOM 做相应的处理,这时候就可以使用 Vue.nextTick(callback)这个 api 了。
2)理解原理前的准备
首先需要知道事件循环中宏任务和微任务这两个概念(这其实也是面试常考点)。
常见的宏任务有:
script, setTimeout, setInterval, setImmediate, I/O, UI rendering
常见的微任务有:
process.nextTick(Nodejs),Promise.then(), MutationObserver;
3)理解 nextTick
而 nextTick 的原理正是 vue 通过异步队列控制 DOM 更新和 nextTick 回调函数先后执行的方式。如果大家看过这部分的源码,会发现其中做了很多 isNative()的判断,因为这里还存在兼容性优雅降级的问题。可见 Vue 开发团队的深思熟虑,对性能的良苦用心
Vue3.0 是如何变得更快的?
diff 方法优化
Vue2.x 中的虚拟 dom 是进行全量的对比。
Vue3.0 中新增了静态标记(PatchFlag):在与上次虚拟结点进行对 比的时候,值对比带有 patch flag 的节点,并且可以通过 flag 的信息 得知当前节点要对比的具体内容化。hoistStatic 静态提升
Vue2.x : 无论元素是否参与更新,每次都会重新创建。
Vue3.0 : 对不参与更新的元素,只会被创建一次,之后会在每次渲染时 候被不停的复用。cacheHandlers 事件侦听器缓存 默认情况下 onClick 会被视为动态绑定,所以每次都会去追踪它的 变化但是因为是同一个函数,所以没有追踪变化,直接缓存起来复用 即可。