1、TCP UDP
网络连接是TCP协议 传输内容是HTTP协议 建立TCP连接,先建立连接,再传输内容
TCP 协议:有连接,有断开,稳定传输 UDP协议:无连接,无断开,不稳定传输,但效率高
三次握手,四次挥手 TLS握手(https的加密过程,非对称加密+对称加密)- https协议的工作原理
2、HTTP和HTTPS的区别
1、HTTPS协议需要CA证书,费用高;HTTP协议不要 2、HTTP协议是超文本传输协议,明文传输;HTTPS是具有安全性的SSL加密传输协议 3、HTTP默认端口80,HTTPS默认端口443 4、HTTP连接简单,无状态;HTTPS握手费时
3、cookie 和 token 的区别
1、cookie 是 HTTP 规范,每次请求都会带上cookie,以帮助识别身份,而 token 是自定义传递 2、cookie 会默认被浏览器存储,而 token 需要自己存储 3、cookie 默认有跨域限制,token 默认没有跨域限制 4、cookie 配合 session 使用,token 用于 JWT
4、HTTP状态码
(1)2xx(Success 成功状态码)
1、200 成功 2、204 无内容 3、206 部分内容
(2)3xx(Redirection 重定向状态码)
1、301 永久移动 2、302 临时移动 3、303 查看其他位置 4、304 内容未更改(命中协商缓存) 5、307 临时重定向,不能在 POST 和 GET 之间切换
(3)4xx(Client Error 客户端错误状态码)
1、400 请求错误,客户端请求有问题 2、401 未授权,请求要求身份验证 3、403 禁止访问,服务器拒绝请求 4、404 未找到,未找到请求的资源 5、405 方法禁用
(4)5xx(Server Error 服务器错误状态码)
1、500 服务器内部错误 2、502 网关错误 3、503 暂停服务,服务不可用 4、504 网关超时
5、http1.0,http1.1 和 http2.0 的区别
连接方面:http1.0默认短连接,http1.1默认长连接,一次TCP连接可以进行多次http请求
资源方面:http1.1支持断点续传,返回206
缓存方面:http1.0 强缓存Expires,协商缓存Last-Modified/If-Modified-Since;http1.1 强缓存Cache-Control,协商缓存ETag,If-None-Match
http1.1增加新的方法,如PUT,OPTIONS,
http1.1增加host头
HTTP2.0: 1、压缩头部, 2、多路复用,一次TCP连接可以多个http并行请求 3、服务端推送 4、二进制格式
6、浏览器输入网址后回车发生什么?
- 解析URL
- 缓存判断
- DNS解析-获取URL域名的IP地址
- 获取MAC地址
- TCP三次握手
- HTTPS握手-HTTPS协议的工作原理(如何保证安全)
- 返回数据
- 页面渲染 - 构建DOM树,CSSOM树,生成Render Tree,并进行绘制
- TCP四次挥手
7、WebSocket
基于TCP传输协议,复用HTTP的握手通道,一次握手可以创建持久性连接,并进行双向数据传输
最大的特点:服务器可以向客户端主动推送消息,客户端也可以主动向服务器推送消息
- 支持端对端
- 可以由client发起,也可以由server发起
- 用于:消息通知,直播间讨论区,聊天室,协同编辑
WebSocket 连接过程
- 先发起一个 HTTP 请求
- 成功之后再升级到 WebSocket 协议,再通讯
WebSocket 和 HTTP 区别
- WebSocket 协议名 ws://,可双端发起请求
- WebSocket 没有跨域限制
- 通过 send 和 onmessage 通讯(HTTP 通过 req 和 res)
WebSocket 特点:
- 支持双向通信,实时性强
- 可以发送文本,也可以发送二进制数据
- 建立在TCP协议之上,服务端的实现比较容易
- 数据格式比较轻量,性能开销小,通信高效
- 没有同源限制
let ws = new WebSocket('ws://localhost:9999');
ws.onopen / ws.onmessage / ws.onclose
短轮询:每隔一段时间向服务端发送http请求,不论是否有数据更新,服务端都直接响应
长轮询:服务器收到客户端请求后,不直接响应,先挂起,有数据更新才进行响应,一直没有数据更新,则到达一定的时间限制才返回,客户端再次发出请求,重新建立连接
SSE:服务端向客户端发送流信息,就是,发送的不是一次性的数据包,而是一个流数据,会连续不断地发送过来(与 视频播放类似)
8、项目亮点:
- 前端监控
- 大文件上传
- IM
- 权限管理
- PPT 导出
- 数据传输加密
9、HTML5 语义化理解
- 代码更加容易维护
- CSS 未加载出来时也能很好的展示结构
- 有利于SEO
标签:
- header 文档的头部区域
- nav 导航栏
- section 定义文档中的节(section、区段)
- footer 文档的底部区域
- aside 侧边栏信息
- article 定义独立的内容
10、前端性能优化
1. 页面渲染优化
- 避免 CSS 阻塞,尽早(将 CSS 放在 head 标签里)和尽快(启用 CDN 实现静态资源加载速度的优化)的将 CSS 资源加载
- 避免 JS 阻塞
- 使用字体图标 iconfont 代替图片图标
- 降低 CSS 选择群的复杂度
- 减少重绘和回流
2. JS 中的性能优化
- 使用事件委托
- 防抖和节流
- 尽量不要使用 JS 动画
3. 图片的优化
- 雪碧图:减少 HTTP 请求次数
- 图片懒加载
- 使用 CSS3 代替图片
4. webpack 优化
- 代码压缩:HTML,CSS,JS 文件压缩
- Tree shaking 去除死代码
- babel-plugin-transform-runtime 减少ES6转化ES5的冗余
- 提升打包速度
5. Vue优化
- 路由懒加载
- 合理使用 computed 和 watch
- v-for 添加 key
- v-for 的同时避免使用 v-if
- destory 时销毁事件:比如addEventListener 添加的事件、setTimeout、setInterval、bus.$on 绑定的监听事件等
- 第三方插件按需引入
6. react 优化
- map 循环展示添加key
- 路由懒加载
- 使用 SCU,memo 或者 pureComponent 避免不必要的渲染
11、IM 重难点
- 正在发送的消息的展示,发送成功之后,用发送成功的消息替换
- 大量使用Map,在进行查找时不需要进行遍历,最后还能转成数组
12、cookie,session, token,JWT,SSO
常见的几种登陆方案
- Cookie + Session 登录
- Token 登录
- SSO 单点登录
- OAuth 第三方登录
一、Cookie + Session 登录
背景:HTTP 是无状态协议,每次请求都是独立的,服务器无法判断每次请求是否来自同一用户,进而无法判断用户的登录状态
原理:当用户登录,将登陆状态记录到 Session 中,要实现服务端对客户端的登录信息进行验证,就需要再客户端保存一些信息(SessionId),并要求客户端在之后的每次请求中携带。在 Cookie 中保存 SessionId,每次请求都携带,服务端收到请求后,通过验证 Cookie 中的信息判断用户是否登录
Cookie + Session 实现流程: 用户初次登录时:
- 1、用户访问 a.com/pageA,并输入密码登录
- 2、服务器验证密码无误,创建 SessionId,并将其保存起来
- 3、服务器响应该 HTTP 请求,并通过 Set-Cookie 将 SessionId 写入 Cookie
第一次登录完成之后,后续的访问就可以直接使用 Cookie 进行身份验证了
- 4、之后的每次请求会自动带上登录时返回的Cookie
- 5、服务器对比 Cookie 中 SessionId 和 服务器 SessionId 是否一致
- 6、一致,身份验证成功;无效,需要用户重新登录
优点:原理简单,用户信息存在服务端,可以快速封禁用户
缺点:
- 占用服务器内存,硬件成本高
- 多进程,多服务器时,不好同步 -- 需要使用第三方缓存,如 redis
- 默认由跨域
二、Token 登录(令牌)
Token 机制实现流程 用户首次登录时:
- 用户访问 a.com/PageA,输入账号密码登录
- 服务端验证账号密码无误,创建Token
- 服务端将 Token 返回给客户端, 由客户端自由保存
后续页面访问时:
- 用户之后的请求都带上登录时获取的 Token
- 服务端验证该 Token ,有效则身份验证成功,无效则重新登录
Token 生成方式 最常见的 Token 生成方式 JWT JWT 组成: header 指定签名算法 playload 表明 JWT 意图 signature JWT 的签名,为了让 JWT 不能被随意篡改
优点:不占用服务器内存,没有跨域限制,多进程、多服务器不受影响
缺点:服务端不方便收回权;如果服务端密钥泄漏,用户信息丢失;
三、SSO 单点登录
三种实现方式:
- 父域 Cookie
- 认证中心
- LocalStorage 跨域
-
父域 Cookie:父域的 Cookie 被子域共享,也就是,子域会自动继承父域中的 Cookie;利用这个特点,可以将 SessionId(或Token)保存在父域中;将 Cookie 的 domain 属性设置为父域的域名(主域名),同时将 Cookie 的 path 属性设置为根路径,这样所有的子域名应用就都可以访问到这个 Cookie。这要求应用系统的域名建立在一个共同的主域名下,如 tieba.baidu.com 和 map.baidu.com,它们都建立在 baidu.com 这个主域名下,那么它们就可以通过这种方式来实现单点登录
-
认证中心:实现相对复杂,支持跨域,扩展性好,时单点登录的标准做法
-
LocalStorage 跨域:前端拿到 SessionId(或 Token)后,除了写入自己的 LocalStorage 外,还可以使用特殊手段将它写入多个其他域下LocalStorage中
-
单点登录退出:当其中一个退出,认证中心遍历其下的所有产品,并调用对应的退出 api ,完成退出
四、OAuth 第三方登录
13、重绘,重排
重绘:元素外观被改变
重排:重新生成布局,重新排列元素
如何触发重绘,重排?
- 添加、删除、更新DOM
- display:none 触发重排
- visiblility:hidden 只触发重绘
- 移动或者给页面中DOM添加动画
- 添加一个样式表,调整样式属性
- 用户行为:调整窗口大小,改字号,滚动
如何避免
- 集中改变样式
- 为动画的HTML元素使用 fixed 或者 absoult 的position
- 不使用 table 布局
- 尽量只修改 position:absolute 或者 fixed 元素
- 动画GPU加速,使用translate
- 提升为合成层 使用 will-change: transform;
14、实现浏览器内多个标签之间的通信
- 使用 websocket 协议
- 使用 ShareWorker 的方式:使用共享线程进行数据交换
- 使用 localStorage 的方式:监听 localStorage 的变化
- 使用 postMessage 方法
15、如何解决跨域
1、CORS:
简单请求至少设置 Access-Control-Origin, 非简单请求至少设置字段: Access-Control-Origin,Access-Control-Methods,Access-Control-Headers
2、JSONP
原理:利用 <script> 标签没有跨域,通过 src 属性发送带有 callback 参数的 GET 请求,服务端将接口返回数据拼凑到 callback 函数中,返回给浏览器
缺点:仅支持get,不安全,可能会遭受XSS攻击
3、postMessage 跨域
- 可以解决以下问题:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的 iframe 消息传递
- 以上三个场景的跨域数据传递
4、nginx代理跨域
5、proxy代理
6、document.domain + iframe跨域
7、window.name + iframe跨域
8、WebSocket协议跨域
16、事件委托
利用浏览器的冒泡机制,把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个元素的事件
特点:
- 减少内存消耗
- 动态绑定事件
17、position 属性的值
- 固定定位 fixed
- 相对定位 relative
- 绝对定位 absolute
- 粘性定位 sticky
- 默认定位 Static
18、BFC(块级格式化上下文)
如何创建BFC:
- 根元素,即HTML元素
- float 值不为 none
- position 为 absolute 或 fixed
- display 为 inline-block、table-cell、tabel-caption
- overflow 不为 visible
使用场景:
- 去除边距重叠现象
- 清除浮动
- 避免某元素被浮动元素覆盖
19、HTTP缓存
强缓存:
expirescache-control(优先级更高)
协商缓存:
Last-Modified/If-Modified-SinceEtag/If-None-Match(优先级更高)
设置Expires的时间为 Expires = 前时间 + 有效时间
Cache-Control: max-age=30 30s内都走本地缓存,不回去请求服务端
协商缓存:
与强缓存不同的是,强缓存是在有限时间内,不走服务端,只走本地缓存;而协商缓存是要走服务端的,如果请求某个资源,去请求服务端时,发现命中缓存则返回304,否则返回所请求的资源。
Last-Modified/If-Modified-Since 用最后一次修改时间做判断
Etag/If-None-Match 读取资源内容,转成hash值,对比资源内容,来确定资源是否修改
总结:
- 用户请求资源,判断是否使用强缓存
- 如果存在强缓存,判断缓存是否过期,没有过期就直接使用缓存,过期了就向服务器发送请求,
- 如果不存在强缓存就向服务器发送请求,
- 向服务器发送请求后,验证协商缓存是否命中,如果命中则返回304,否则返回新的资源数据
20、用CSS实现三角符号
口诀:盒子宽高均为零,三面边框皆透明
div:after {
position: absolute;
width: 0px;
height: 0px;
content: " ";
border-right: 100px solid transparent;
border-top: 100px solid #ff0;
border-left: 100px solid transparent;
border-bottom: 100px solid transparent;
}
21、清除浮动的方式
- 添加额外标签
- 父元素添加 overflow 属性,或者设置高度
- 建立伪类选择器清除浮动
.parent:after {
content: '';
display: block;
clear: both;
}
22、JS 数据类型
基本类型:Number(数字)、String(字符串)、Boolean(布尔值)、Symbol(符号)、undefined、null
引用类型:Object,Function,Array
-
typeof 能区分的类型:
number, string, boolean, symbol, undefined, object, function -
instanceof 能区分的类型:
Array, Object, Function -
Object.prototype.toString.call() 能精准判断数据类型
var toString = Object.prototype.toString;
console.log(toString.call(1)); //[object Number]
console.log(toString.call(true)); //[object Boolean]
console.log(toString.call('mc')); //[object String]
console.log(toString.call([])); //[object Array]
console.log(toString.call({})); //[object Object]
console.log(toString.call(function(){})); //[object Function]
console.log(toString.call(undefined)); //[object Undefined]
console.log(toString.call(null)); //[object Null]
23、对requestAnimationFrame的理解
requestAnimationFrame 就是请求动画帧
语法:window.requestAnimationFrame(callback); 宏任务
cancelAnimationFrame 取消执行动画,传入 requestAnimationFrame 的默认返回的id
优点:
- CPU节能
- 函数节流
- 减少DOM操作
递归执行
24、对CSS工程化的理解
实践:
- 预处理器:Less、Sass 等
- 重要的工程化插件 PostCss
- Webpack Loader
预处理器特点
- 嵌套代码的能力
- 支持定义 CSS 变量
- 提供计算函数
- 允许对代码片段进行 extend 和 Mixin
- 支持循环语句的使用
- 支持将 CSS 文件模块化,实现复用
Less 变量
@width: 10px;
@height: @width + 10px;
#header {
width: @width;
height: @height;
}
Mixins
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu a {
color: #111;
.bordered();
}
.post a {
color: red;
.bordered();
}
嵌套: & 表示当前选择器的父级
#header {
color: black;
.navigation {
font-size: 12px;
}
.logo {
width: 300px;
&:after {
content: " ";
display: block;
font-size: 0;
height: 0;
clear: both;
visibility: hidden;
}
}
}
将一些混合(mixins)和变量置于 #bundle 之下,为了以后方便重用或分发
#bundle() {
.button {
display: block;
border: 1px solid black;
background-color: grey;
&:hover {
background-color: white;
}
}
.tab { ... }
.citation { ... }
}
#header a {
color: orange;
#bundle.button(); // 还可以书写为 #bundle > .button 形式
}
计算函数
if, boolean, range, each, Math Function, Type Function, image-size, svg-gradient
Example: image-size("file.png");
Output: 10px 10px
循环
when, each
PossCss
可以编译尚未被浏览器广泛支持的现金的 CSS 语法,为兼容语法添加前缀,由强大的插件机制
Webpack loader 处理 CSS
- css-loader:导入 CSS 模块,对 CSS 代码进行编译处理;
- style-loader:创建style标签,把 CSS 内容写入标签。
先编译再写入
25、z-index 在什么情况下失效
- 父元素 position 为 relative,子元素 z-index 失效,解决:父元素 position 改为 absolute 或 static
- 元素没有设置 position 为非 static 属性, 解决:设置该元素为 relative,absolute 或 fixed 中的一种
- 同时设置 z-index 和 float 浮动,解决:float 去除,改为 display:inline-block
26、常见布局单位
px, %, em, rem, vw/vh
27、画一条0.5px的线
transform:scale(0.5, 0.5)
28、如何解决1px问题
29、var, let, const
30、作用域和作用域链
作用域:定义:简单来说作用域就是变量与函数的可访问范围,由当前环境与上层环境的一系列变量对象组成
全局作用域、函数作用域
作用:隔离变量
作用域链:查找变量时,如果在当前作用域没有查到,就会向上级作用域去查,直到查到全局作用域,这个查找的过程形成的链条就叫作用域链
31、闭包
闭包是指有权访问另一个函数作用域中的变量的函数--《JavaScript高级程序设计》
闭包形成的条件:
- 函数的嵌套
- 内部函数引用外部函数的局部变量,延长外部函数的变量的生命周期
闭包的用途:
- 模仿块级作用域
- 保护外部函数的变量
- 封装私有变量
- 创建模块
闭包的缺点:会导致函数的变量一直保存在内存中,过多的闭包可能会导致内存泄漏
32、JS 中 this 的五种情况
- 作为普通函数执行时,
this指向window - 当函数作为对象的方法被调用,
this指向该对象 - 构造器调用,
this指向返回的对象 - 箭头函数的 this 绑定看的是
this所在函数定义在哪个对象下,就绑定哪个对象。如果有嵌套的情况,则this绑定在最近的一层对象上 - Function.prototype上的
apply、call 和 bind改变函数 this 指向。apply 接收参数为数组,call 接受参数列表,bind方法通过传入一个对象,返回一个this绑定了传入对象的新函数
- call,apply,bind都是可以
改变函数体内this的指向。 - call,apply,bind使用时,传入的
第一个参数都是用来传递this的指向的,也就是对上下文的指定 - call,apply,bind都是可以传入多个参数,不同的是,
call和bind的后续参数都是按照顺序传参,而apply的传参类型是数组,bind的参数可以在函数执行的时候再次添加。
33、new 一个对象发生了什么?new一个对象的过程
- 创建一个空对象,继承构造函数的原型
- 执行构造函数(将obj作为this)
- obj
function customNew(constructor, ...args) {
// 1、创建一个空对象,继承 constructor 的原型
const obj = Object.create(constructor.prototype)
// 2、将 obj 作为 this,执行 constructor,传入参数
const result = constructor.apply(obj, args);
// 3、返回 obj
return obj
}
34、nextTick
- 修改数据后在
$nextTick中获取更新后的 DOM - Vue 才采用
异步更新策略,监听到数据变化时,Vue 会开启一个队列,缓存在同一事件循环中的所有数据变更。将多次数据更新合并成一次,减少 DOM 的操作。如果同一个 watcher 被多次触发,只会被推入到队列中一次; - 源码中,在
callbacks里面加入出入的函数,然后用timerFunc异步方式调用,首选Promise
原理:$nextTick 主要使用宏任务和微任务,将传入的回调函数包装成异步任务;nextTick 提供了四种异步方法 Promise.then、MutationObserver、setImmediate、setTimeout(fn,0)
35、Vue 插槽
具名插槽,作用域插槽,具名插槽的缩写
36、Vuex 状态管理
- Vuex 的状态存储,是响应式的;
- 改变 store 中状态的唯一途径就是显式地提交(commit)mutation(管家),方便跟踪每一个状态的变化
State:应用的状态数据
Getter:store 的计算属性
Mutation:唯一更改 store 中状态的方法,必须同步
Action:提交的是 mutation,而不是直接变更状态,可以包含任意异步操作。
Module:Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块
37、keep-alive
场景:tabs标签页,vue性能优化
作用:组件缓存,保持组件状态,避免反复渲染导致的性能问题;频繁切换时不需要重复渲染
原理:keep-alive 组件的缓存是基于 VNode 节点的,不是直接存储 DOM 结构;它将满足条件的组件缓存在cache 对象中,在需要重新渲染时将 Vnode 从 cache 对象 中取出渲染
38、mixin
多个组件有重复的逻辑就会用到mixin,多个组件有相同的逻辑,抽离出来
缺点:
- 变量来源不明确,不利于阅读
- 多个mixin可能造成命名冲突
- 提升了项目的复杂度
39、Vue 组件通信
props/$emit父子组件通信$parent$refs$emit/$on$attrs/$listenners(vue3 废除)provide/inject
40、vue 中 date 是函数
因为组件会被多次引用,创建多个实例,如果是对象会影响到所有实例,所以为了保证组件的不同实例之间data不冲突,data必须时一个函数
41、MVVM
视图模型双向绑定,是 Model-View-ViewModel 的缩写
Model 层代表数据模型,View 代表UI组件,ViewModel 是 View 和 Model 层的桥梁
数据绑定到 viewModel 层并自动将数据渲染到页面中,视图变化的时候会通知 viewModel 层更新数据;
数据驱动试图
优点:
低耦合可重用独立开发可测试
42、Vue生命周期
Vue2 生命周期钩子
Vue3 生命周期钩子
43、computed 和 watch
- computed 用于计算产生新的数据,有缓存
- watch 用于监听现有数据
44、Vue2、Vue3 和 React 三者 diff 算法有何区别
diff算法:如果严格 diff 两棵树,时间复杂度 O(n^3),不可用
Tree diff 的优化:
- 只比较同一层级,不跨级比较
- tag 不同则删除重建(不再去比较内部细节)
- 子节点通过 key 区分(key 的重要性)
优化后的时间复杂度 O(n)
区别:
- Vue2 -
双端比较 - Vue3 -
最长递增子序列 - React -
仅右移
45、Vue React 为何循环时必须使用key
- vdom diff 算法会
根据 key 判断元素是否要删除 - 匹配 key,则
只移动元素- 性能好 - 未匹配 key,则
删除重建- 性能差
46、React 事件
<div onClick={this.handleClick.bind(this)}>点我</div>
React并不会将click事件绑定到div的真实DOM上,而是在document监听了所有事件,当事件发生并且冒泡到document时,React将事件内容封装并交由真正的处理函数运行。这样的方式不仅仅减少了内存的消耗,还能在组件挂载销毁时统一订阅和移除事件。
此外,冒泡到document上的事件不是原生的浏览器事件,而是React的合成事件(SyntheticEvent),因此阻止事件冒泡调用event.preventDefault()方法
合成事件的目的:
抹平了浏览器之间的兼容问题,具有跨浏览器开发的能力- 对于原生事件,浏览器会给监听器创建一个时间对象,如果有很多的事件监听,那么就需要分配很多的事件对象,造成高额的内存分配问题。对于合成事件,有一个事件池管理他们的创建和销毁,当事件需要被使用时,就会从池子中复用对象,时间回调结束就会销毁对象上的属性,从而便于下次复用事件对象。
47、React的事件和普通的HTML事件有什么不同
区别:
- 名称命名方式,原生事件为全小写,react事件采用小驼峰
- 函数处理语法,原生事件为字符串,react事件为函数
- react必须要用
preventDefault()来阻止默认行为
48、React高阶组件、Render props、hooks 有什么区别,为什么不断迭代
是目前react解决代码复用的主要方式:
- 高阶组件(HOC)是