持续更新中
- 一、 基础面试题
- 1.ajax,fetch,axios的区别
- 2.节流和防抖有什么区别?分别应用于什么场景?
- 3.px,%,em,rem,vw/vh 有什么区别?
- 4.什么时候不能使用箭头函数?
- 5.请描述TCP三次握手和四次挥手
- 6.for in 和 for of 有什么区别?
- 7.for await of有什么作用?
- 8.offsetHeight scrollHeight clientHeight有什么区别?
- 9.HTMLCollection和NodeList的区别
- 10.computed和watch的区别
- 11.vue2组件通讯有几种方式,尽量全面
- 12.vuex中mutation和action的区别
- 13.JS严格模式有什么特点?
- 14.HTTP跨域请求时为何发送options请求
- 二、原理相关面试题
- 三、移动端,http相关面试题
- 四、实际工作相关面试题
一、 基础面试题
1.ajax,fetch,axios的区别
- ajax是一种技术统称
- fetch是一个具体的API
- axios是一个第三方库
2.节流和防抖有什么区别?分别应用于什么场景?
- 防抖:防止抖动,比如有一个input框,当输入停止之后才会触发搜索
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>debounce</title>
</head>
<body>
<input type="text" id="input" />
<script>
// 防抖
const debounce = (fn, delay) => {
let timer = null;
return function () {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
};
// 测试
const ipt = document.querySelector("#input");
ipt.addEventListener(
"keyup",
debounce(() => {
console.log("search...");
}, 500)
);
</script>
</body>
</html>
- 节流:节省交互沟通,流,不一定指流量,例如drag或scroll期间触发某个回调,要设置一个时间间隔
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>throttle</title>
<style>
.box {
margin: 100px auto 0;
width: 200px;
border: 1px solid #ccc;
}
.box__header {
height: 20px;
background-color: #ccc;
}
.box__container {
height: 180px;
}
</style>
</head>
<body>
<div id="throttle" class="box" draggable="true">
<div class="box__header">可拖拽</div>
<div class="box__container"></div>
</div>
<script>
// 节流
const throttle = (fn, delay = 100) => {
let timer = null;
return function () {
if (timer) return;
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
};
};
// 测试
const drag = document.querySelector("#throttle");
drag.addEventListener(
"drag",
throttle((e) => {
console.log("鼠标位置: ", e.offsetX, e.offsetY);
})
);
</script>
</body>
</html>
- 防抖和节流的区别
- 节流: 限制执行频率,有节奏的执行
- 防抖: 限制执行次数,多次密集的触发只执行一次
- 节流关注‘过程’, 防抖关注‘结果’
3.px,%,em,rem,vw/vh 有什么区别?
px 和 %
- px基本单位,绝对单位(其它的都是相对单位)
- %相对于父元素的宽度比例
em 和 rem
- em相对于当前元素的font-size
- rem相对于根节点的font-size
vm / vh
- vw屏幕宽度的百分比
- vh屏幕高度的百分比
- vmin两者的最小值,vmax两者的最大值
4.什么时候不能使用箭头函数?
箭头函数的缺点
- 没有arguments
- 无法通过apply,call,bind改变this
不能使用箭头函数的场景:
- 对象方法
- 原型方法
- 构造函数
- 动态上下文中的回调函数
- vue生命周期和method
5.请描述TCP三次握手和四次挥手
三次握手 - 建立连接
- 客户端发包,服务端接收.
- 服务端发包,客户端接收.
- 客户端发包,服务端接收.
四次挥手 - 关闭连接
- 客户端发包,服务端接收. 客户端告诉服务端,我要关闭连接了.
- 服务端发包,客户端接收. 这时服务端已经收到要关闭连接的请求,会将剩下的包发送给客户端
- 服务端发包,客户端接收. 服务端告诉客户端所有的包已经发送完了,可以关闭连接了
- 客户端发包,服务端接收. 客户端告诉服务端关闭连接。
6.for in 和 for of 有什么区别?
- for in遍历得到key。for in不能遍历set和map。 主要用于可枚举数据,如对象、数组、字符串
- for of遍历得到value。for of不能遍历对象。主要用于可迭代数据,如数组、字符串、map、set
7.for await of有什么作用?
其实就是promise.all的替代品,用来遍历promise
8.offsetHeight scrollHeight clientHeight有什么区别?
- offsetHeight / offsetWidth = border + padding + content
- clientHeight / clientWidth = padding + content
- scrollHeight / scrollWidth = padding + 实际内容尺寸
9.HTMLCollection和NodeList的区别
- 如下图,DOM是一棵树,所有节点都是Node
- Node是Element的基类
- Element是其它HTML元素的基类,如HTMLDivElement
它俩的区别:
- HTMLCollection是Element的集合
- NodeList是Node的集合
10.computed和watch的区别
- computed用于计算产生新的数据
- watch用于监听现有数据
computed 和 method:
computed有缓存,method没有
11.vue2组件通讯有几种方式,尽量全面
- props和$emit
- 自定义事件
- $attrs $listener;
比如父组件给子组件传a,b,c三个数据,但子组件只接收了a数据,那么b和c就会放入attrs中,方法会放入listener中
这种方式虽然也可以用于多层级传值,只需要给每个层级用v-bind绑定一个$attrs,但不是最合适的- $parent
- $refs
parent和refs适合在mounted钩子中使用,因为这时候组件已经渲染完成了- provide/inject
适合多层级传值,在provide方法中返回一个对象,对象中就是需要传递下去的数据- vuex
12.vuex中mutation和action的区别
- mutation:原子操作,必须是同步代码
- action:可包含多个mutation,可包含异步代码
13.JS严格模式有什么特点?
- 全局变量必须先声明
- 禁止使用with
- 创建eval作用域
- 禁止this指向window
- 函数参数不能重名
14.HTTP跨域请求时为何发送options请求
跨域请求
- 因为浏览器同源策略,所以出现了跨域问题
- 同源策略一般限制ajax网络请求,不能跨域请求服务器
- 但不会限制<link> <img> <script> <iframe>加载第三方资源
解决跨域的方法
- jsonp,利用了不会限制这些标签加载第三方资源的特性,通过这些标签去发起请求,后台配合返回一个方法的字符串,标签会将这些字符串当作方法去加载,从而获取到数据.
- cors,服务端配置允许跨域
- vue中配置porxy
多余的options请求
- options请求,是跨域请求之前的预检查
- 浏览器自行发起的,无需我们干预,不会影响实际的功能
二、原理相关面试题
1.js内存泄漏如何检测?场景有哪些?
什么是垃圾回收?
- 全局作用域中声明的变量不是垃圾,因为程序不确定你啥时候可以用到它。
- 局部作用域中的变量会在函数执行完毕之后成为垃圾,被回收掉。
内存泄漏的检测可以通过控制台的performance
在vue中内存泄露的场景
- 被全局变量,函数引用,组件销毁时未清除
- 被全局事件,定时器引用,组件销毁时未清除
- 被自定义事件引用,组件销毁时未清除
2.浏览器和nodejs的事件循环有什么区别?
- 浏览器和nodejs的event loop流程基本相同
- nodejs宏任务和微任务分类型,有优先级
3.虚拟DOM(vdom)真的很快吗?
vdom
- Virtual DOM,虚拟DOM
- 用JS对象模拟DOM节点数据
- 由React最先推广使用
vdom快吗?
- vdom并不快,js直接操作DOM才是最快的
- 但数据驱动视图要有合适的技术方案,不能全部DOM重建
- vdom就是目前最合适的技术方案
4.遍历数组,for和forEach哪个快?
- for更快
- forEach每次都要创建一个函数来调用,而for不会创建函数
- 函数需要独立的作用域,会有额外的开销
5.什么是JS Bridge?
- JS无法直接调用 native API
- 需要通过一些特定的格式来调用
- 这些格式就统称JS-Bridge,例如微信JSSDK
js bridge常见的实现方式
- 注册全局API
- URL Scheme
6.vue每个生命周期都做了什么?
beforeCreate
- 创建一个空白的vue实例
- data method尚未被初始化,不可使用
created
- vue实例初始化完成,完成响应式绑定
- data,method都已经初始化完成,可调用
- 尚未开始渲染模板
beforeMount
- 编译模板,调用render生成vdom
- 还没有开始渲染DOM
mounted
- 完成DOM渲染
- 组件创建完成
- 开始由创建阶段进入运行阶段
beforeUpdate
- data发生变化之后
- 准备更新DOM
update
- data发生变化,且DOM更新完成
- 不要在update中修改data,可能会导致死循环
beforeDistroy
- 组件进入销毁阶段(尚未销毁,可正常使用)
- 可移除、解绑一些全局事件,自定义事件
distroy
- 组件被销毁了
- 所有子组件也都被销毁了
vue什么时候操作DOM比较合适?
- mounted和updated都不能保证子组件全部挂载完成
- 可以使用$nextTick渲染DOM
三、移动端,http相关面试题
1.移动端H5 click有300ms延迟,如何解决?
- 背景:double tap to zoom
- fastClick
- width=device-width
2.token和cookie有什么区别?
cookie
- http无状态,每次请求都要带cookie,以帮助识别身份
- 服务端也可以向客户端set-ciikie,cookie大小限制4kb
- 默认有跨域限制:不可跨域共享,传递cookie
- html5之前cookie常用于本地存储,大小只有4KB
- html5之后一般使用localStroge或sessionStroge,存储大小为5M左右
cookie和token
- cookie是HTTP规范,而token是自定义传递
- cookie会默认被浏览器存储,而token需要自己存储
- token默认没有跨域限制
JWT(JSON Web Token)
- 登录的一个解决方案
- 前端发起登录,后端验证成功之后,返回一个加密的token
- 前端自行存储这个token(其中包含了加密过的用户信息)
- 以后访问服务端接口,都带着这个token,作为用户信息
3.如何实现SSO单点登录?
基于cookie
- cookie默认不可跨域共享,但有些情况下可设置为共享
- 主域名相同,如www.baidu.com 和 image.baidu.com
- 设置cookie domain为主域名,即可共享cookie
sso
- 主域名不同,则不能使用cookie
- 这时可以使用sso
如何实现单点登录?
- 主域名相同,则可共享cookie
- 主域名不同,则需使用sso
4.script的defer和async有什么区别?
- 不加任何属性,当遇到script标签时,会暂停解析,下载js,执行js,再继续解析HTML
- 加defer属性,当遇到script标签时,HTML会继续解析,并行下载js,HTML解析完后再执行js
- 加async属性,当遇到script标签时,HTML会继续解析,并行下载js,执行js,再解析HTML
5.prefetch和dns-prefetch有什么区别?
preload和prefetch
- 在link标签中使用,<link rel=‘preload’ />
- preload资源在当前页面使用,会优先加载
- prefetch资源在未来页面使用,空闲时加载
dns-prefetch和preconnet
- dns-prefetch即DNS预查询
- preconnet即DNS预连接
prefetch和dns-prefetch的区别?
- prefetch是资源预获取(和preload相关)
- dns-prefetch是DNS预查询(和preconnet相关)
6.你知道哪些前端攻击?该如何预防?
XSS
- Cross site Script跨站脚本攻击
- 黑客将js代码插入到网页内容中,渲染时执行JS代码
- 预防:特殊字符替换
CSRF
- Cross Site Rquest Forgery 跨站请求伪造
- 黑客诱导用户去访问另一个网站的接口,伪造请求
- 预防:严格的跨域限制 + 验证码机制
点击劫持
- click jacking
- 诱导界面上蒙一个透明的ifrme,诱导用户点击
- 预防:让ifrme不能跨域访问
sql注入
- 黑客提交内容时写入sql语句,破坏数据库
- 预防:处理输入的内容,替换特殊字符
7.webSocket和HTTP有什么区别?
WebSocket
- 支持端对端通讯
- 可以由client发起,也可以由server发起
- 应用场景:消息通知,直播室讨论区,聊天室,协同编辑
区别:
- websocket协议名是ws://,可双端发起请求
- websocket没有跨越限制
- 通过send和onmessage通讯(http通过req和res)
8.从输入url到页面展示的完整过程
步骤
- 网络请求
- 解析
- 渲染
网络请求
- DNS查询(得到IP),建立TCP连接(三次握手)
- 浏览器发起HTTP请求
- 收到请求响应,得到HTML源代码
解析:字符串 ->结构化数据
- HTML构建DOM树
- CSS构建CSSOM树
- 两者结合,形成render tree
渲染:render tree绘制到页面
- 计算各个DOM的尺寸,定位,最后绘制到页面
- 遇到js可能会执行
- 异步css,图片加载,可能会触发重新渲染
9. 重绘repaint和重排(回流)reflow有什么区别?
动态网页,随时都会重绘,重排
- 网页动画
- model Dialog弹窗
- 增加/删除一个元素,显示/隐藏一个元素
…- 这些都会导致重绘或重排
重绘repaint
- 元素改变外观,如颜色,背景
- 但元素的尺寸,定位不变,不会影响其他元素的位置
重排reflow
- 重新计算尺寸和布局,可能会影响其它元素的位置
- 如元素高度增加,可能会让相邻元素改变位置
区别
重排比重绘要影响更大,消耗也更大,所以要尽量避免无意义的重排
减少重排的方法:
- 集中修改样式,或直接切换css class
- 修改之前先设置display:none,脱离文档流
- 使用BFC(内部改变不会影响外部元素)特性,不影响其它元素位置
- 频繁触发使用节流和防抖
- 使用createDocumentFragment批量操作DOM
四、实际工作相关面试题
1.h5页面如何进行首屏优化
路由懒加载
- 适用于SPA(不使用MPA)
- 路由拆分,优先保证首页加载
服务端渲染SSR
- 传统的前后端分离(SPA)渲染页面的过程复杂
- SSR渲染页面过程简单,所以性能好
- 如果是纯h5页面,SSR是性能优化的终极方案
2.后端一次性返回10w条数据,你该如何渲染?
后端返回10w条数据,技术方案设计不合理,后端应该进行分页处理
如果非要这样处理,可以使用如下方法:
自定义中间层
- 自定义nodejs中间层,获取并拆分这10w条数据
- 前端对接nodejs中间层,而不是服务器
- 成本比较高
虚拟列表
- 只渲染可视区域DOM
- 其它隐藏区域不显示,只用div撑起高度
- 随着浏览器滚动,创建和销毁DOM
3.前端常用的设计模式有哪些?并说明使用场景
前端设计模式可参考这篇博客详解前端设计模式
4.做过哪些vue的优化
- v-if和v-show
v-if会彻底销毁组件,v-show是使用css隐藏组件
- v-for使用key
- 使用computed缓存
- keep-alive缓存组件
频繁切换的组件,如tabs
- 异步组件
- 针对体积较大的组件,如编辑器,复杂表格,复杂表单等
- 拆包,需要时异步加载,不需要时不加载
- 减少主包的体积,首页会更快加载
- 路由懒加载
5.使用vue遇到过哪些坑?
内存泄露
全局变量,全局事件,全局定时器,自定义事件未销毁
vue2响应式的缺陷
data新增属性用vue.set,删除属性用vue.delete,无法直接修改数据arr[index] = value
路由切换时scroll到顶部
- spa的通病,不仅仅是vue
- 如:列表页,滚动到第二屏,点击进入详情页
- 再返回到列表页(此时组件重新渲染)就scroll到顶部
解决方案:
- 在列表页缓存数据和scrollTop值
- 当再次返回列表页时,渲染组件,执行scrollTo(xx)
6.如何统一监听vue组件报错?
==window.onerror
- 全局监听所有js错误
- 但它是js级别的,识别不了vue组件信息
- 可以捕捉一些vue监听不到的错误
errorCaptured生命周期
- 监听下级组件的所有错误
- 返回false会阻止向上传播
errorHandler配置
- vue全局错误监听,所有组件错误都会汇总到这里
- 但errorCaptured返回fanlse,不会传播到这里
7.如果一个h5很慢,该如何排查性能问题
前端性能指标
- first paint(FP),开始渲染了,但页面上不一定有内容
- first contentful paint,第一次有内容的渲染
- first Meaningful paint,第一次有意义的渲染,能看到页面的大概内容,已弃用,改用LCP
- domContentLoaded,页面的dom内容加载完成
- largest Contentfull paint(LCP),页面最大的内容已经渲染完成
- load
chrome devtools
- performance可查看上述性能指标,并有网页快照
- network可以查看各个资源的加载时间
分析后得出结果
- 如果是网页加载慢,那么可以优化服务端硬件配置,使用cdn
- 路由懒加载,大组件异步加载,减少主包的体积
- 优化http缓存策略
- 如果是网页渲染慢,优化服务端接口
- 继续分析,优化前端组件内部的逻辑