前端面试题2026
2024-03-11 16:49:48 0 举报
AI智能生成
前端面试题大全涵盖了各种关于前端开发的核心问题,包括但不限于HTML、CSS、JavaScript等基础知识,以及React、Vue、Angular等流行框架的使用。此外,还包括了对浏览器兼容性、性能优化、响应式设计等方面的考察。这些问题旨在全面评估应聘者的前端开发技能和解决问题的能力。无论你是初级前端开发者还是有经验的专家,这份面试题都能帮助你更好地准备面试,提升你的技术水平和竞争力。
作者其他创作
大纲/内容
icon
掌握
没有掌握
了解即可
计算机网络
说一下3次握手和四次挥手以及为什么?
客户端发SYN,服务端回SYN和ACK,客户端回ACK
不两次握手是怕网络原因服务器没有收到请求,但是客户端一直等,导致浪费资源/连接错误
客户端发FIN,服务端发ACK,服务端发FIN,客户端发ACK
不三次挥手是因为服务端要告诉客户端已经没有数据要发送了,然后客户端收到信号
说一下TCP和UDP的区别?
TCP会建立连接才能数据传输,所以有连接性,而UDP不需要连接直接可以发送数据
TCP有错误检测,重传机制,和用滑动窗口来做流量控制和拥塞控制机制,所以有可靠性
TCP会给数据包排序,所以有顺序性,而UDP没有可能导致乱序的数据
所以TCP常常用做网页,邮件,文件下载,UDP用于需要实时性的直播,音视频
说一下http1.1的队头阻塞?
1.1是串型传输的,每个请求需要在前一个请求完成后才能发送和处理,当多个并行请求请求同一台服务器,服务器会按照顺序处理请求,如果一个请求比较耗时,会阻塞后面的请求,直到前面的请求完成<br>
TCP层面的阻塞?
接收缓存区阻塞
发送缓冲区阻塞
网络拥塞阻塞
说一下http2有哪些新增特性?<br>
默认永久连接,相比于1.1的connection:keep-alive
二进制分帧,数据流
相比于1.1文本形式,整个报文都是二进制的,引入帧和流的概念
按大小将报文段分成不同的帧,帧就是将报文段分割成一个个的小块,每个小块就是一个帧,来回传输的过程称为流,用首部的帧来做标识,所以有了顺序,就可以做多路复用
多路复用
允许多个请求同时通过一个连接并发处理,避免了队头阻塞
<div>头部信息压缩</div>
把报文中的信息压缩成一张表,每次只需要发送这张表的id就可以了,比如cookie等字段,每次复用就好了
服务器推送、server push
如一个html引用其他资源,服务器可以把别的资源一起返回,可以并行传输数据
优先级机制,每个请求可以带一个优先级,前端就是加header,主要后端处理优先级
说一下http3?
QUIC协议,底层是基于UDP的,解决了TCP层面的阻塞问题<br>
有哪些特性?
基于UDP
多路复用
快速连接建立
内置TLS握手,速度更快
低延迟
重传和冗余消除
动态流量控制
前向错误纠正
说一下https加密原理?
是http加上SSL/TSL安全层
使用了对称加密 加密密文,非对称加密 加密密钥,数字证书加密
客户端发请求到服务端,服务端返回公钥和数字证书到客户端,客户端验证证书,并用服务端公钥和随机数加密生成“对称密钥”到后端,后端收到后用私钥解密得到对称密钥,然后用对称密钥进行加密解密<br>
说一下常见状态码?
204 no content 成功但没有内容。常用于前端错误上报
301永久重定向
302临时重定向-自己网站挂了,定位到公告
304协商缓存
307类似 302,区别在于能够确保请求方法和消息主体不会发生改变,get请求没有区别,post的时候302会尝试转换为get
400客户端请求出错,参数错误
401没有权限,比如token丢失
403forbidden,禁止访问
404 Not Found资源不存在
405请求方式出错
500服务器内部错误
502错误的网管或代理服务器
说一下强缓存和协商缓存的区别?
强缓
expires
cache-control
no-store
no-cache
走协商
max-age/s-max-age
启发式缓存
如果一个可以缓存的请求没有设置Expires和Cache-Control,但是响应头有设置Last-Modified信息,这种情况下浏览器会有一个默认的缓存策略:(Date - Last-Modified)*0.1,这就是启发式缓存
协缓
etag/if-none-match
last-modify/if-modify-since
last-modify和etag的区别?
etag唯一资源标识会计算资源hash,所以增加服务器负担,last-modify只能秒级,分布式的时候last-modify需要保证服务器时间戳一致
说一下跨域解决方案?<br>
jsonp的原理?
发送一个callback到后端,后端拼接数据并返回,缺点是只支持get请求
说一下解决跨域后如何可以携带cookie?<br>
前端请求头加上with-credientials=true/fetch的时候withCredientials:'include',后端Access-Ctrol-Allow-Origin不为*且Aceess-Control-Allow-credientials=true
说一下简单请求和复杂请求?<br>
简单请求是指使用 GET、HEAD、POST 三个方法中的任意一种,并且请求头中的 Content-Type 类型只能是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 中的一种。这种请求不会触发 CORS 预检请求,因为它们不会对服务器产生影响,且不会携带敏感信息
而复杂请求则是指使用了其他请求方法(如 PUT、DELETE 等)或者 Content-Type 类型为 application/json、application/xml 等,以及使用了自定义请求头等情况,这些会被认为是对服务器产生了影响,因此在发送前需要进行 CORS 预检请求,以确保请求的安全性
TCP怎么保障可靠性?
前端安全
说一下xss和csrf?
xss(跨站脚本攻击)
<br>
存储型和反射型都是注入恶意脚本
解决
字符转义
不使用v-html/dangerouslySetInnerHTML
CSP的主要作用是控制网页中哪些资源可以被加载和执行,从而防止恶意脚本的注入。存储型和反射型XSS攻击都是通过向网页中注入恶意脚本来实现攻击的,CSP可以通过限制网页中脚本的来源和执行方式来防御这两种攻击。
http-only
在脚本中却不能访问这个cookie,这样就避免了XSS攻击利用JavaScript的document.cookie获取cookie,只是一部分防御措施,攻击者可以用别的方式
csp的头?
Content-Security-Policy
Content-Security-Policy-Report-Only
script-src
style-src...
csrf(Cross—Site Request Forgery)跨站请求伪造,如钓鱼网站
双重token
判断cookie和header里的是否相同
验证referer,但是如果浏览器也是伪造的还是会有问题
same-site
strict只能同站点发送cookie
same-site有哪些值都有什么用?
sime-site有strict/lax/none
jwt
头部、载荷和签名
既可以解决csrf,还可以解决分布式session、跨域问题
放到header里,不会像cookie一样自动携带,由于JWT是基于签名进行验证的,因此攻击者无法伪造一个合法的JWT。即使攻击者通过某些方式获取到了用户的JWT,也无法修改其内容,因为任何修改都会导致签名验证失败
git
git rebase 和 git merge 的区别?
都会把两个分支合并到一起,但是rebase不会创建新的提交对象,它的提交记录是线性的
它的使用是在目标分支使用git rebase 分支名 然后如果有冲突需要手动解决然后git add 解决完后git rebase --continue,可以git log看合并结果, 如果要回退git rebase --abort
git cherry-pick
合并指定提交
如何回退版本?
回滚上次commit,且有提交记录
git revert HEAD
git commit -m 'xxxx'
git push
回滚指定commit
git reflog
git log --oneline
<br>git reset --hard xxxxx
git push -f
如果回退一个
git reset HEAD~1
css
h5有哪些新增?
地图api,拖拽api,input的type,indexDB(localforage),web component,语义化标签,音视频标签,worker
drag api的了解?
dragable
dragstart
dargenter
dragOver
说一下bfc?
块级格式化上下文,是一个独立的空间
它的规则有块级元素会在垂直方向上一个一个排列。内部元素改变不会影响外部元素
垂直方向的距离由margin决定,属于同一个BFC的两个相邻的标签外边距会发生重叠
所以设置其中一个为bfc,可以解决外边距重叠问题
计算BFC的高度的时候,浮动元素也会参与其中
触发bfc的条件
overflow不为visible
float不为none
行内块,弹性盒,table-ceil
position为absolute/fixed
说一下css的盒子模型?
box-sizing:content-box为w3c标准盒模型,设置的width/height实际设置的时候content box元素的大小由content+border+padding决定<br>
box-sizing:border-box为IE怪异盒模型(替代(IE)盒),content 宽高包括 border 和 padding,元素的大小就等于width/height+margin构成,
怎么用css画一个三角形?扇形?
.triangle {<br> width: 0;<br> height: 0;<br> border-top: 50px solid transparent;<br> border-right: 50px solid #f00;<br> border-bottom: 50px solid transparent;<br>}
div高度和宽度都为0,通过边框绘制三角形,边都要有长度,但是只有一个边有颜色就可以了,其他边transparent
扇形加一个50%的border-radius
说一下css选择器的权重?
通配符是0,标签是1,类是10,id是100,style是1000
css如何开启图层?
可以通过定位,3D变换的CSS属性,video,canvas,C3动画,will-change
说一下flext:1?
flex-grow,默认值为1,放大比例
flex-shrink,默认值为1,缩小比例
flex-basis,默认值为auto,占据主轴空间
Javascript
说一下js有哪些数据结构?
number string array object symbol bigint boolean null undefined
说一下ES6有哪些新增?
模板字符串,let/const,箭头函数,promise,生成器迭代器,set/map/symbol/bigint proxy等
说一下const let var区别
const 和 let是es6的,有块级作用域不能重复声明,有暂时性死区,const定义常量不能修改(但引用类型可以修改),var可以变量提升,重复声明
箭头函数和普通的函数的区别?
写法简单,可以简写
箭头函数因为没有prototype和arguments不能当作构造函数
箭头函数里没有this,this指向上层作用域
说一下原型和原型链的理解?
Function instanceof Object和Object instanceof Function都返回true
Function.__proto__ === Function.prototype
Object.__proto__=== Function.prototype
Function.prototype.__proto__===Object.prototype
Function.__proto__ instanceof Object<br>
Object.__proto__ instanceof Function <br>
查找对象的属性的时候,如果在对象身上找不到,就会去对象的原型去找,对象的原型又有自己的原型,直到找到Object.prototype.__proto__为null,这条查找链就是原型链
new 一个构造函数,生成一个实例对象,构造函数的prototype和实例对象的__proto__都指向同一个对象,这个对象就是原型对象,实例对象的constructor是指向构造函数,这样就形成了一个三角关系
说一下new的原理?
1.创建一个空对象
2.空对象的__proto__指向传入函数的prototype
3.绑定this并且传入参数执行函数且拿到执行结果
4.如果是引用类型就返回这个函数执行的结果,如果是值类型就返回创建的对象
说一下instanceof的原理?
遍历左边的原型链看能否等于右边的prototype
如何判断一个对象/数组?
判断对象
constructor
Object.prototype.toString.call()
判断数组
constructor
Object.prototype.toString.call()
Array.isArray()
instanceof
[].__proto__ === Array.prototype
这里需要注意的是Object.prototype.toString.call()不能检测包装类型,然后toStringTag在ES6也支持修改
还要注意constructor不是一个靠谱的方法,因为constructor属性可以被修改
slice和splice有什么区别?
slice是纯函数,不会改变数组
索引
splice不是纯函数,可以修改数组,可以删除和添加
call/apply/bind有什么区别?
call是一个一个传参,apply是传一个数组,bind是一个一个传参,call/apply会立即执行,bind不会立即执行
call/apply是执行时改变this指向,bind是声明时改变this指向
箭头函数可以调用call/apply/bind吗
首先它不会报错,因为箭头函数的隐式原型还是指向了构造函数Function.prototype,所致这些方法都是能被找到的
使用这些方法不会改变this指向,因为bind是在执行的时候确定this的,而箭头函数在解析的时候就确定了this
多次bind的结果是什么?
this只会指向第一次bind的结果,因为第一次bind已经将this指向通过返回的function确定了,后续的bind只是对返回函数的包装是不会生效的
对于bind,如果使用new实例化,this不会被改变,而是构造函数实例化的this
说一下可选链和空值合并运算符?
可选链空值不报错返回undefined
只有null 或 undefined返回后面的,区别于逻辑或
说一下es6模块化和commonjs模块化的区别?
语法不同
加载方式不同,esm是静态加载,编译确定依赖关系,所以可以编译时做tree-shaking,cjs是动态加载,运行时候确定依赖关系
作用域不同,es6使用严格模式,模块内部变量和函数不会暴露到全局作用域,但是cjs会
说一下防抖节流的区别?怎么样实现一个防抖/节流函数?
防抖在规定的时间内再次触发,会重新计时,如用户点击提交按钮防止重复提交
节流规定一个单位时间内只能触发一次事件,常用在操作dom的时候,如页面滚动懒加载,下拉刷新
说一下map和weakmap的区别?
weakmap利于垃圾回收,只能使用对象作为key
说一下回调地狱和解决?
就是异步的时候,一直回调,解决是promise或者async/await
说一下对Promise的了解?
有三个状态:Pending,Fulfilled,Rejected
Promise.all和Promsie.race都有短路特性,all是一次性执行数组里面的promise,race赛跑是全部执行,返回最先改变状态的一个promise
Promise.allSettled相比于Promise.all可以拿到成功和失败的结果(全部执行完,而不会被短路),原理是遍历执行promise,然后用一个数组拿到成功的结果,然后在catch的时候拿到失败的结果,最后用finally去返回成功和失败的结果
Promise.any是ES12新增的API,只要有一个成功,就返回那个成功的结果
可以用Promise.race实现一个请求超时,原理是把一个超时Promise和一个请求放进数组让promise执行,如果超时的promise先完成,则说明该请求超时<br>
可以用Promise.race做并发控制,原理创建一个事件池和控制最大并发数变量max,是在for循环里创建promise实例,这个promise实例状态改变就从事件池移除,然后放入事件池,当并发池的length达到max的时候,使用promise.race去执行并发池,这样就会让并发池先执行完一个请求然后移除,然后又推入,这样循环可以达到并发控制效果
静态方法的话,成功是返回值,失败是返回失败的promsie
promise捕获错误的机制有哪几种,错误捕获优先级是怎样的
then传第二个函数
优先级更高
.catch
async await的原理?
async await 语法是 ES7出现的,是基于ES6的 promise和generator生成器实现的
说一下symbol的作用?
使用symbol做对象的key,可以避免key值重复
可用Symbol.iterator来定义迭代器,这样就可以使用for...of循环来遍历对象。
用普通的for of不能遍历symbol的值,Object.getOwnPropertySymbols()可以遍历出symble属性,所以可以模拟私有变量
如react里使用了symbol,$$typeof标识react元素类型,防止xss,不支持symbol的环境会是个数字(如果后端支持传的json,json模拟react元素),因为json不支持symbol
说一下深拷贝和浅拷贝?
深拷贝对于多层引用数据结构,也不会互相影响,浅拷贝只有第一层不影响
说一下数组去重有哪些方法?
利用Set去重
双重for循环
filter加includes
indexOf
为什么0.1+0.2不等于0.3?
JS使用双精度浮点数类型存储的,遵循IEEE754规范,在转为二进制计算的时候精度会丢失
说一下for in 和for of的区别?
for in 一般用来遍历对象,他会遍历原型对象上的属性,一般会加一层hasOwnProperty
for of 是遍历实现了iterator迭代器的对象,比如数组 set map,不会遍历原型上的属性
map和set有哪些方法?
map有get和set,set有个has,size,add,delete,clear
说一下isNaN和number.isNaN的区别?
isNaN会尝试转化,而number.isNaN严格判断
Number.isNaN('abc')//false,es6新增,除了NaN返回true,其他都是false
isNaN('abc')//true<br>
object.is和==和===的区别?
object.is接收两个参数判断是否相等,基本和===一样,不过+0和-0为false还有NaN为true的时候与===不同
说一下纯函数?
相同的输入相同的输出,没有副作用
说一下defer和async的区别?
defer和async都是domContentLoaded之后执行,都是异步加载,defer可以保证顺序,async不能保证顺序所以不影响dom不在乎js顺序的可以使用async
说一下DOMcontentLoaded和onload的区别?
DOMContentLoaded事件在页面的DOM结构加载完成后触发,而onload事件在整个页面(包括图片、样式表、脚本等资源)都加载完成后触发。
html和css解析的顺序?
并行的,不会阻塞解析
css解析会阻塞页面渲染吗?
因为和js互斥(js也可能改变样式),所以渲染会阻塞
说一下js事件循环机制?<br>
js是单线程的,同步任务放入执行栈执行,异步任务放到异步任务队列,异步任务队列分为宏任务队列和微任务队列,当执行栈中代码执行完后,会去检查微任务队列是否有任务,有的话全拿出来执行,执行完后取下一个宏任务执行,如果遇到微任务会先执行微任务再执行下一个宏任务
可以理解为一开始是宏任务,因为script是宏任务,然后宏任务是一个一个执行的,微任务是批量执行的
对函数式编程的理解?
是一种编程范式,比如纯函数,函数不可变,高阶函数,函数一等公民等
是更好的一种编程方式,比面向过程,面向对象好
宏任务有哪些?微任务有哪些?
宏任务:script,定时器,I/O,dom事件,ajax,MessageChannel,UI rending,rfa
微任务:promise.then(),nextTick,mutationObserver,queueMicroTask
说一下reduce?
高阶函数,做累计的操作
说一下函数柯里化?
把多个传参改为一个一个的,可以函数复用
说一下js继承?
原型链继承
构造函数继承
组合继承
原型继承
寄生继承
es6继承
说一下web worker?
用于多开线程,做耗时操作,然后通过postmessage通信
说一下闭包?
可以缓存函数
可以防抖节流柯里化操作
可以模拟私有变量
如何解决深拷贝循环引用问题?
使用weakmap/map,如果已经拷贝过直接返回
哪些操作会导致内存泄漏?
闭包被全局变量引用,闭包中变量将无法被回收
interval引用了本应该回收的外部变量,将无法被回收
DOM在页面中已经删除了,但内存中还引用着这个DOM结点,DOM结点将无法被回收
说一下raf做动画有什么好处?
CPU节能,切换至后台时,会暂停刷新任务
减少DOM操作,合并每一帧的DOM操作,每一帧只执行一次
函数节流,为了防止在一个刷新间隔内发生多次函数执行,在每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销,一个刷新间隔内函数执行多次时没有意义的,因为多数显示器每 16.7ms 刷新一次,多次绘制并不会在屏幕上体现出来
词法作用域和语法作用域是什么?
词法:词法作用域是在代码编写过程中确定的作用域,也被称为静态作用域
语法:this,可以动态的修改,语法作用域是在代码执行过程中确定的作用域,也被称为动态作用域
闭包有时会代替作用域链,来代替变量的查找
说一下 typeof null 等于 object 的原理?
因为 typeof null 返回的类型标签前三位是000和object的一样,所以返回object
说一下mutationObserver?
监听dom变化
说一下service worker?
离线缓存
消息推送
必须https
pwa用的
和ES6的class继承有什么区别?
Typescript
说一下type和interface的区别?
interface只能定义对象
type可以定义普通数据类型,可以使用联合类型交叉类型,类型别名
type是类型别名不会创建新的类型
intercface可以extends继承其他接口,实现复用
说一下ts的extends?
当定义多个接口时,可以把公用的属性方法定义在一个父接口种,其他子接口继承它,提高复用性可维护性
type使用&联合类型也能实现一样的继承,不过只是类型的一种定义方式
说一下什么是泛型?
用尖括号<>传入一个类型变量,可以用这个类型变量去推断别的类型
说一下ts的函数重载?
同一个函数名根据不同的参数类型和数量实现不同的函数体
传不同参数返回不同类型
说一下ts中的内置工具类型?
Partial
全部变为可选
Omit
去除一个属性
Pick
挑出一个属性
Exclude/Extract
取并集/交集
Record<K, T>表示将类型K中所有属性的类型都变为T的新类型。
keyof T表示获取类型T中所有属性名组成的联合类型
type Person = {<br> name: string;<br> age: number;<br> gender: string;<br>};<br><br>type PersonKey = keyof Person; 变成了type PersonKey = 'name' | 'age' | 'gender';
说一下对infer的了解?
它可以用于从泛型类型中推断出某个类型,并将其作为一个新的类型变量来使用
infer通常和条件类型(Conditional Types)一起使用,用于从条件类型中推断出某个类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;<br>
说一下逆变和协变?
浏览器原理
说一下从输入url到页面渲染浏览器做了哪些事情?
https://gitmind.cn/app/docs/m3inc866
url规范化,缓存检查,dns解析,网络进程做tcp连接3次握手和解析响应头等,响应数据,接收数据,4次挥手,渲染进程做生成dom树,cssom树,样式计算,布局,分层,绘制,分块,光栅化,合成
说一下浏览器有哪些进程?
主进程
管理整个浏览器
渲染进程,每个标签页
主线程
也成为渲染线程,负责处理 DOM 的构建、样式计算、布局和绘制等核心渲染任务
事件触发线程
异步http请求线程
定时器线程
插件进程
GPU进程,图形加速相关
说一下重绘和回流?
重绘就是重新绘制,会重新计算样式,比如改变背景颜色,改变字体大小都是重绘
回流就是重排,除了会重新计算样式,还会重新布局,比如改变元素的位置就是重排
这些事情可以想到有哪些优化点?
可以想到网络层面优化(如dns预解析),渲染层面的优化(如动画图层),代码层的优化合并更新减少重绘回流
说一下浏览器的垃圾回收机制?
引用计数
有循环引用问题
标记清除
分代回收
新生代svavenge算法
新生代短期存在的对象,from和to空间,如果存活则复制到to空间,然后反转to和from,晋升到老生代的条件是to空间超过25%和已经经历过scavenge
老生代算法
Mark-Sweep(标记清除) 只清除死亡对象和 Mark-compact(标记整理)
并行垃圾回收和延迟清理,增量标记等,不阻塞主线程的情况下垃圾回收,解决全停顿问题
说一下jsonp的原理?
jsonp的原理是发送一个callback到后端,后端拼接数据并返回,缺点是只支持get请求
Nodejs
怎么发布一个包?
npm login/npm publish
说一下node有哪些模块?
fs/http/path/child_process/querystring/url/util等
说一下buffer?
Buffer 是用于处理二进制数据的类。它提供了一种在 JavaScript 中操作字节的方式,可以用来创建、读取、写入和转换二进制数据
说一下path.join和path.resolve的区别?
path.join方法会将参数中的所有路径片段连接起来,常用来文件名路径
path.resolve 方法也会将参数中的所有路径片段连接起来,但是它会根据当前目录进行解析,并将相对路径转换为绝对路径,返回一个新的绝对路径字符串。这个方法常用于获取完整的绝对路径。<br><br>
说一下怎么开启子进程?
exec 方法:用于执行一个 shell 命令
execFile 方法:用于执行一个可执行文件
spawn 方法:以流的形式启动一个命令
fork 方法:创建一个新的 Node.js 进程,并通过 IPC 通道进行通信,当然还有别的很多通信方式
通过 fork 方法开启子进程,并可以通过 message 事件和 send 方法进行进程间通信
nod的事件循环?
Vue
v-if和v-show的区别?
v-if是真正的渲染和销毁,而不是显示和隐藏,v-show通过css dispaly控制显示和隐藏
为何v-for中用key?
在diff算法中,判断是否是sameNode,只需要移动,不用删除和消耗,减少渲染次数,提高渲染性能
为什么data是一个函数?
防止组件间data互相影响
说一下computed和watch的区别?
computed可以把值缓存起来,当依赖发生变化才会重新计算,所以能用computed的尽量用computed,computed是多对一的,通过多个值计算出一个需要的值
watch支持异步,当监听的值改变后会重新执行,支持异步,watch是一对多的,监听某一个值,可以去修改多个地方的值
父子组件之间生命周期执行的顺序是怎么样的?
在父组件beforeMounted之后,执行整个子组件生命周期,再回头执行父组件mounted
说一下vue的作用域插槽?
说一下对mixin的了解?
mixin用来逻辑复用,但是会有命名冲突问题
变量名不好查找等问题
说一下有写过自定义指令吗?
说一下vue-router的路由守卫?<br>
全局守卫
beforeEach
afterEach
独享守卫
beforeEnter
组件内守卫
beforeRouteEnter
beforeRouteleave
activated路由组件被激活时触发。deactivated路由组件失活时触发。
说一下组件间有哪些通信方式?
说一下provider和inject?
有ABCDEF组件,C的父组件有AB,但DE不知道数据是从A还是B传来的--容易造成混乱
父子组件props和this.$emit
自定义事件 event.$on event.$off event.$emit
vuex
说一下对vuex的了解?
用state存数据,可以mapState获取数据
用mutation定义可以改变state的方法,接受到state和payload参数,通过commit触发或者mapMutations
用action可以做异步操作,接受到context和payload参数,用dispatch触发action或者mapActions;
用getter也可以存数据,相当于vue的计算属性(有缓存)
用module可以用来拆分模块
Object.defineProperty可以监听数组吗?
可以,但是过滤掉了数组,因为数组结构可能很深,遍历很深影响性能
vue中可以做哪些性能优化?
合理使用v-show和v-if,computed,v-for时加key,避免和v-if同时使用
子主题
事件销毁,合理使用异步组件,keep-alive,data层级不要太深
webpack层面的(后面) 图片懒加载,SSR
说一下router和route的区别?
$router是VueRouter的一个对象,全局的对象,他包含了所有的路由,包含了许多关键的对象和属性,push等
每一个路由都会有一个$route对象,是一个局部的对象,可以获取对应的name,path,params,query等
路由懒加载的原理?
也就是用异步插入标签
说一下虚拟dom?
封装一层真实dom,可以使用声明式的方法去操作真实dom
虽然直接去操作dom比较快,但是有可能造成多次重绘回流,用虚拟dom模拟真实dom,体积较小,js计算速度较快,批量更新的时候可能会比操作真实dom速度更快
axios封装
取消请求
AbortController
cancelToken
说一下vue的生命周期都用来做什么事情?
created和mounted可以用来发请求
mounted可以用来获取dom节点
beforeDestroy用来清除定时器,取消事件监听等
vue的nextTick的使用场景?
改了一个数据后,等dom更新后再触发的场景,在用this.$refs去拿dom数据的时候,created里想要拿到dom相关信息
说一下你用过vue的哪些修饰符?
.sync .native .trim .number .once .stop .self .prevent等
vue2和vue3的区别?
一个是性能上的优化
优化方面,响应式使用proxy代替defineProperty,性能更高效监听范围更广(Vue2中需要用),用到才执行是懒监听而不是一次直接递归监听;还有diff算法优化(静态节点优化,最长递增子序列),函数式模块化Tree-shaking减少包体积(Vue2中大量Api放在vue对象的原型上不利于Tree-shaking)
一个是给开发者更好的开发体验
开发体验上面,setup(3.2)和compositon api解决了反复横跳问题;watchEffect这种api还可以智能收集依赖;生命周期命名和合并优化;新增了Teleport/Suspence组件;函数式编程;TS重构能更早发现问题
pinia和vuex的区别?
更好的ts支持,支持按需引入
pinia可以有多个store,而vuex需要命名空间
说一下vitest和jest的区别?
acxx?disacxxx
Vue底层原理
pnpm为什么更快?
1.采用软连接,.pnpm下的互相引用都是软链接
不会重新下载包,可以带版本号,解决幽灵依赖问题
.pnpm下的互相引用都是软链接
2.采用硬链接到.pnpm
复用包,节省磁盘空间,都指向一片磁盘空间
对mvvm的理解?
1.数据驱动视图
2.关注业务逻辑,不用去关注手动操作dom
说一下虚拟dom?
维护性更好
可以夸平台
直接操作真实dom会导致重绘重排,用虚拟dom批量更新性能更好
操作虚拟dom提高效率
new vue做了什么事情?
初始化数据,编译template模版生成reder函数,在不同阶段触发生命周期,render执行生成vnode然后patch到页面
Vue的响应式原理?
1、object.defineProperty加观察者模式实现的
2.初始化的时候会创建一个Watcher,Dep,使用observer监听data里的数据,用defineProperty给每一个key设置getter和setter
3.render执行的时候会触发getter,并在getter里通过Dep.addSub去通知watcher收集依赖
vue3则采用track去收集依赖,采用trigger去通知更新,采用proxy去代理对象,采用effect作为更新函数
4.更新的时候,会触发setter,通过Dep.notify去通知watcher更新页面
vue的diff算法?
1.首先时间复杂度是On,原因是不跨层比较,根据key,tag决定是否深度比较
2.头头 尾尾 头尾 尾头 剩下的找到则置为空放最前面 没有找到则新建插入放前面
3.vue3则中间是最长递增子序列
说一下分支切换和effect嵌套怎么解决的?
分支切换是每次重新收集依赖重新计算
effect是通过栈解决的,或者属性描述
computed原理?
是基于ComputedRefImpl类,把计算属性定义为响应式数据(通过设置类的get/set,手动track和trigger),主要是保存了一个_dirty标记,用于标记计算属性是否重新计算,当发生变化时变为true表示需要重新计算
nextTick的原理?
1.vue2用了promise,mutationObserve,setImmidate,setTimeout,4层降级,vue3直接promise.resolve().then
2.将函数放到微任务队列最后,完成异步更新
3.用flushCallbacks将所有的cb执行
说一下v-modal的原理?
vue2中是v-bind和input事件的语法糖
然后v-bind绑定的数据是响应式数据
说一下vue的模板编译原理?
1.解析vue模板,用正则循环匹配(开始和结束标签,文本和属性),用到栈结构,头节点压栈尾节点出栈,生成ast对象
2.optimize标记静态节点
3.有个这个对象后,生成一段可以执行的代码字符串,用new Function包装生成一个可执行函数,这个函数就是render函数
如果没有render才编译 : parse(正则/栈结构)生成ast -> optimize(标记静态节点) -> generate(ast转化成render function)
keep-alive的原理?
本身是一个全局组件,用于将动态组件缓存起来,用于切换时保留状态避免重新渲染
如果有max则会走LRU(最近最少使用)
放到hashmap最前面表示最近访问,获取的时候置为最近访问,放入的时候,如果满了就删除最后一个
其他就是监听include,exclude,销毁组件,不渲染组件等
学了源码后给项目带来了哪些好处?
学到一些新进的技术,比如monorepo,git-simple-hook,查漏补缺完全搞懂api用法,遇到bug可以更快定位问题
说一下路由原理?
hash
onhashchange
history
popstate
pushstate
Object.defineProperty(Vue.prototype, '$router', {<br> get () { return this._routerRoot._router }<br> })
Vue.component('RouterView', View)
说一下vuex原理?
1.调用install方法安装,用mixin在beforeCreate注入vuexInit方法,所以每个实例都会调用这个方法,并且保存Vue对象
2.vuexInt可以实现vm访问store,原理是如果是更节点就把配置的sotre给this.$store,否则去parent上去查找
3.store的构造函数进行实例化这样就是响应式的(对象形式),然后commit调用mutation,dispatch是包装了一层promise.all来调用action
说一下pinia的原理?
说一下mixin的原理?
mergeOpitons做的
全局组件和局部组件怎么设计的?
状态机?
React
说一下类组件和函数组件的区别?
性能主要取决于代码的作用,而不是选择函数式还是类组件。尽管优化策略有差别(scu和memo),但性能差异可以忽略不计。
以前函数组件没有状态,有了hook后,解决了这个问题
函数组件没有this问题
说一下受控组件和非受控组件的区别?
受控组件,表单的值受state控制,需要自己监听onChange去更新state
非受控组件,自己去用ref拿取节点
说一下SCU有什么用?
性能优化,浅比较,判断props,state变化来决定子组件是否要渲染
说一下对immer/immutable的了解?
不可变数据
原理是使用proxy代理做的
说一下你知道的hooks?
useState
useEffect/useLayoutEffect
useRef
useContext
useReducer
useInpretiveHandle
useMemo/useCallback
useDefferedValue/useTransiton
use/useid
还有些写库需要的
说一下组件间通信方式有哪些?
props
自定义事件
Redux/Context
说一下react.memo?
父组件更新,子组件没必要更新的时候,相当于pureComponent和SCU
如果父组件的状态跟子组件的状态有关不需要使用,不影响子组件的时候可以用
说一下forwardRef和useImperativeHandle?
子组件暴露给夫组件的时候,用于父组件调用子组件的方法
说一下高阶组件HOC有什么用?
接收一个组件,返回一个组件,其实就是多了一层中间层
代码复用
增强props
做权限
为什么useState要这样设计?
设计成数组结构的方式,是因为可以自定义变量名
多个状态的时候,是写多个useState还是怎么处理?
useImmer最好
对hooks的理解?
函数式编程,逻辑复用
react18性能优化?
useDefferedValue useTransition
data fetching cache
rsc
suspence
useDefferedValue/useTransiton的区别?
useDeferredValue 使用延迟值 主要用于减少连续状态更新带来的性能开销,将状态更新延迟到下一次渲染中
useTransition 主要用于优化异步操作的过渡处理,提供平滑的用户体验并避免页面卡顿
说一下render props?
父组件传一个render为函数的prop到子组件
加了心智负担,感觉无用
而且数据流从下到上不太好
说一下react的生命周期?
说一下什么时候会产生无限循环?
useEffect没写[],或者依赖的时候引用数据类型
说一下redux的数据流?
通过dispatch去派发action,去通知reducer生成新的state,然后渲染到页面
setState是同步还是异步?
isBatchingUpdate = true;<br> // 你需要执行的一些代码<br> // ...<br> isBatchingUpdate = false
为true走异步更新,为false走同步更新,定时器这些因为延迟所以为false了,就会走同步,普通react管理的走异步
react18之后都为异步
说一下react闭包陷阱?
闭包引起的值不更新的问题,拿到的是旧的值
import { useRef } from 'react';<br><br>function useLatest<T>(value: T) {<br> const ref = useRef(value);<br> ref.current = value;<br><br> return ref;<br>}<br><br>export default useLatest;
说一下useEffect和useLayoutEffect有什么区别?
useEffect异步的不会阻塞渲染,而useLayoutEffect同步的会阻塞渲染
useEffect解决不了的时候才用useLayoutEffect
说一下useCallback和useMemo场景区别?
useCallback用于传入一个函数到子组件的时候,需要给子组件套一层React.memo,依赖的值不发生变化,这个子组件就不会随着父组件更新而更新
useMemo用于复杂计算量的时候,依赖不变就不用重新计算
注意本身也有开销,没有性能问题可以不用
怎么让这个缓存值永久不变?
使用useRef
说一下useState和useReducer的区别?
const [state, dispatch] = useReducer(reducer, initialState)
useState 用于管理简单的、相互独立的状态
而 useReducer 适用于管理复杂的、有关联的状态
new
通信
高阶组件
redux数据流
createStore/aciton/dispatch/reducer新state/监听然后更新value
redux中间件机制
dispatch增强
在dispatch action之间
redux异步请求
redux-thunk
体积小
耦合严重
功能弱,要自己封装功能
redux-saga
异步解藕,逻辑清晰
异常处理,try catch好处理异常
功能强大,比较灵活,方便测试
体积大,功能多
redux-promise
redux和vuex的区别
vuex弱化了dispatch,取消了action,弱化了reduce
数据可预测
diff算法
跨层diff
component diff
element diff
jsx怎么转为真实dom,createElement原理
hooks
usememo usecallback区别
useLayoutEffect
和组件渲染任务相同
useEffect
useState返回数组<br>
useState同步异步
有没有进入react调度流程
react18 createRoot开始都是批量处理
useRef理解
保存和ui渲染无关的状态,和useState不一样,额外的空间
useContext理解
数据共享
调试困难
hooks限制
memorizeState单链表没有名字没有key
事件机制
绑定到button对应的fiber树,绑定到onclick,diff阶段判断是否合成事件,在document注册,监听函数里找到原生事件集合,遍历依赖项数组绑定事件,最后统一处理(绑定监听)
并发和并行
fiber
fiber和element
链表的好处,插入删除高效,移动占用空间
use useID cache rsc useDefferedValue useTransiton createRoot flushSync 组件返回值可以null和undefined
react不能到组件
react错误捕获
方向优化
跳过组件重复更新
减少提交阶段耗时
通用更新
子主题
React底层原理
说一下react和vue的区别?
jsx不能静态编译优化,但是vue的template有更多限制,diff不同,优化手段不同等
react的两个阶段
react 把 schedule 和 reconcile 叫做 render 阶段,这个阶段就是把 vdom 转换为 fiber
reconcile阶段
也就是diff调和子节点
scheduler阶段
控制打断更新,执行js还是浏览器渲染
之后把 filber 更新到 dom 的过程就叫做 commit 阶段
说一下事件机制的原理?
react自己写了一套事件系统模拟原生事件,好处是抹平浏览器差异,跨平台,事件池复用,利用冒泡机制减少内存使用
所以return false会失效,而原生的stopPropogation和preventDefault是react重写过的所以会生效
现在是root,而不是document
利于多个react版本共存
说一下fiber?
架构变化Stack Reconciler到Fiber Reconciler
历史原因:因为GUI线程和JS线程互斥,老版本React遇到组件更新耗时的时候,一次大量的递归更新会因为占用JS线程,导致浏览器没有时间渲染造成页面卡顿
好处/解决的问题:而fiber架构可以拆分任务,中断任务,异步更新方面,解决不可中断的递归更新卡顿问题
先说它是什么,1、是一种架构,支持时间分片/优先级调度/异步可打断更新;2、可以看成是最小粒度执行单元,保存了节点的状态和副作用以及更新的优先级(自身过期时间expirationTime(lane)判断是否有空闲时间执行更新,没有接把控制权给浏览器渲染),可以理解为虚拟dom,是根据虚拟dom生成的;
react链表是怎么关联的?
return指向父fiber child指向子fiber sibling指向兄弟fiber
说一下时间分片?
RIC浏览器空闲时间执行,防止浏览器没有空闲时间而卡死
setTimeout(fn, 0)由于递归执行会延迟4ms左右,所以不用这种方式
给任务分5个优先级
两套优先级
fiber和scheduler
expirationTime
只能区分
lane车道模型
更加细粒度
二进制yangma
很长的数字
用MessageChannel去模拟RIC,去请求浏览器空闲时间
任务分割
切分/任务队列/优先级排序/空闲时间从队列取出优先级高的完成,dom树渲染,是否时间到,任务挂起,任务分割暂停从新吊起
说一下react的双缓存技术?
渲染动画的时候,如果上一帧计算量比较大,导致上一帧画面绘制当前帧画面之间有较长间隙,出现白屏
为了解决这个问题,在内存中绘制当前动画,绘制完毕后直接用当前帧替换上一帧画面,省去两帧替换的计算时间,不会出现白屏
React用workInProgress(内存中构建的树)和curren(渲染树)来实现更新逻辑,双缓存一个在内存中构建,一个渲染视图,两棵树用alternate指针互相指向,在下一次渲染的时候,直接复用缓存树作为下一次的渲染树,上一次的渲染树又作为缓存树,这样防止只用一颗树更新状态丢失的情况,又加快了Dom节点的替换和更新
说一下react的并发更新?
concurrent mode就是把render改为了createRoot,主要是使用useTransition和useDeferredValue来设置优先级
也就是可打断更新,用scheduler调度器判断fiber的优先级和lane
setState/react批量更新?
setState只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的
1.把newState存入pending队列
2.判断是否是batch update,如果是则放入dirtyComponents中
3.如果不是则遍历dirtyComponents调用updateComponent,更新pending state props
调用多个setState的时候,react会对这些state批量处理,减少渲染次数提高性能
setState更新流程?
fiber树初始化和更新流程?
初始化
1、创建RootFiber做为根
2、生成workInprogress和current单链表fiber树,用alternate关联
3、遍历fiber树,调和子节点,commit提交更新渲染视图
更新
重新创建workInProgress树,复用当前alternate指向的树,渲染完毕后,workInProgrress再次变为current树
说一下redux中间件的原理?
就是在拦截了dispatch(action)这一步,然后执行别的逻辑再走dispath
说一下react diff?
第一轮和vue一样,后面开始记录位置,如果能在老节点里找到,则移动到前面,没有则新增一个在前面,然后新的多了新增,旧的多了删除
说一下redux的原理?
hooks怎么保证顺序的?
fiber怎么管理和打断任务的?
子主题
Nextjs
为什么渲染更快?
不使用ssr的话,先加载首页再获取异步数据动态渲染到首页,而开启ssr,省略了链式fetch异步数据,返回一个有数据的首页,浏览器直接渲染
做过哪些seo优化?
sitemap.xml
canonical网址规范化
ssr
语义化标签
说一下ssr/ssg/isr的区别?
ssr服务端渲染
ssg静态站点生成
isr增量静态再生
说一下next怎么流式渲染的?
pages router需要使用use
app router默认服务端组件
RSC通过Suspence加异步组件流式渲染
说一下app router和pages router的区别?
默认RSC
解决持久化缓存layout问题
强大的文件约束,如loading,error等
服务端渲染原理?
一些组件在服务端渲染好,所以叫服务端渲染
生成一些字符串给前端,然后前端进行一些hydrate操作
然后把props,data这些扔进去
在服务器上流式传输 HTML。<br><br>要实现这个功能,需要从原来的方法切换renderToString切换到新renderToPipeableStream方法。<br><br>客户端的选择性注水作用。<br><br>使用 hydrateRoot 代替 createRoot 方法。
说一下fallback字段?
fallback:false
没有则404,静态和预渲染站点
fallback:true
路由功能渲染,下次访问缓存该页面,基于数据的动态页面
会显示fallback页面
fallback:blocking
服务端渲染,不会出现闪烁或加载问题,但是白屏直到渲染完成
自定义组件
构建的页面没有生成,会返回这个自定义组件
https://nextjs.org/docs/pages/api-reference/functions/get-static-paths#getstaticpaths-return-values
webpack/vite
webpack
说一下webpack/roolup/vite/esbuild的区别?
webpack有做过哪些优化?
thread-loader
cache-loader
合理使用exclude & include
压缩
treeshaking
gzip
external
热更新
合理sourcemap,base64
说一下hash的种类?
loader和plugin的区别?
webpack本身只能打包js文件,而loader的功能就是让webpack可以去打包别的文件,plugin则是做一些扩展的功能,比如代码压缩
怎么把css打包到一个文件?
MiniCssExtractPlugin
说一下url-loader和file-loader的区别?
url-loader封装了file-loader,小于limit的可以做图片base64,大于limit的用file-loader处理
webpack5废弃了url-loader,使用asset-module
说一下生产环境和开发环境分别使用什么sourcemap,为什么?
开发环境用eval-cheap-source-map,可以定位源码位置和展示
生产环境用nosources-source-map只能定位源码位置,不能源码展示
loader的原理?
loader的执行顺序是从右到左的
本质上是一个函数,每个loader单一职责,会被链式调用,然后去配置webpack提供的参数
plugin的原理?
是基于devServer实现的 ,devServer本身就是一个后端服务 通过websocket和浏览器通信,devServer一旦监听到webpack有新的编译 devServer通过websocket通知浏览器,浏览器收到信号再通过jsonp去请求编译后的文件内容更新到客户端
说一下HMR的原理?
是基于devServer实现的 ,devServer本身就是一个后端服务 通过websocket和浏览器通信,devServer一旦监听到webpack有新的编译 devServer通过websocket通知浏览器,浏览器收到信号再通过jsonp去请求编译后的文件内容更新到客户端
说一下webpack的原理?
说一下webpack怎么打包成多页面?
多个entry和多个htmlwebpackplugin
说一下webpackd的模块联邦?
说一下webpack提示安装第三方包?
说一下tree-shaking的原理?
打包过程,每步做了什么?
webpack code split原理?
webpack写loader和plugin?
vite
说一下vite的依赖预构建?
vite使用esm模块,当项目有不是esm模块就需要依赖预构建,但是有时候vite识别不到,可能会重复构建,可以指定optimizeDeps解决
vite的原理?
vite的原理就是依赖预构建,用esm的方式加载,然后esbuild开发环境打包,生产环境用rollup打包
说一下truborepo?
rust写的,速度更快
函数级别缓存
按需编译
在nextjs中0配置使用,不过还不支持生产环境
性能指标
core web vitals
lcp最大内容绘制2.5s
以用户为中心的指标,因为fcp如果遇到loading这种情况会不准确
fid首次输入延迟100ms
textarea a标签也可以,网页交互首印象
cls累计布局偏移0.1
以高度偏移计算
性能优化
可以这些方面回答
网络层
代码层
构建层
渲染层
webpack迁移到vite
drop console/manualChunks/optimizeDeps
打包方面,vite已经做好了,但是也提一下,比如html,css,js压缩,图片base64,legacy在线上才开启等
图片视频元素路由懒加载
图片webp
tailwind减少css体积
seo/ssg优化
减少空dom元素
prefetch
第三方外链,dns-prefetch
监控埋点
用户行为
程序异常
window.onerror捕获网络错误
Vue.config.errorHandler捕获vue组件错误
react ErrorBoundary
运行性能
方案设计
页面埋点
数据上报/数据采集
sendBeacon不占用网络请求资源,通常尝试在卸载(unload)文档之前向 Web 服务器发送数据
数据存储/数据清洗
汇总统计
报警展示
优化整改
监控的目的是让系统更优,然后根据性能监控优化项目吗
https://juejin.cn/post/7285608128040206391
项目亮点/难点
说一下grid瀑布流和定位瀑布流怎么做的?
grid有网格数量限制的兼容性问题
定位瀑布流
确定元素大小和gap
计算列数
元素给上定位
根据列数,和每次计算当前列的高度,找到最小高度,计算元素需要的left和top值
grid瀑布流
首先给个网格grid
然后让每个元素先渲染,然后计算元素的高度
通过grid-row指定单元格的高度????????????
根据元素的高度指定元素占据多少个单元格
主要是动态设置每一个元素的grid-row为auto / span 占据多少个网格
说一下webpack迁移到vite?
建vite模版
迁移代码
排坑
/deep/需要用:deep()
ts报错处理
vite优化
如开启css sourcemap,用optimizeDeps防止依赖重复构建,用manualchunks切割chunk
主题换肤怎么做的?
css3变量做的,一个初始化主题的函数(判断本地localStorage是否有主题),一个监听变化的函数(使用window.matchMedia('prefers-color-scheme:dark')),然后给html加dark,然后css3变量改变主题
后期使用tailwind darkmode
matchMedia = window.matchMedia('(prefers-color-scheme:dark)')<br> // 监听主题变更<br> matchMedia.onchange = function () {<br> toggleTheme(matchMedia.matches, true)<br> }
设计模式
工厂模式
工厂模式的核心思想是定义一个工厂函数或类来封装对象的创建过程,将对象的实例化过程从业务逻辑中分离出来,使得代码更加灵活和可维护
单例模式
一个类仅有一个实例,并提供一个全局访问点,单例模式的核心思想是使用一个变量来存储类的实例,并提供一个静态方法来获取这个实例
策略模式
js中抽离变的数据,通过map来做
适配器模式
适配器作为中间层,根据不同情况,输出不同接口
发布订阅模式
观察者模式
观察者和发布订阅的区别?
手写题
防抖节流
深拷贝
尾递归
其他类型
数组转树
数组拍平
const flat = (arr) => {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? flat(cur) : cur)
}, [])
}
new
function myNew(fn,...args){<br> const obj = Object.create(fn.prototype)<br> const res = fn.apply(obj,args)<br> return typeof res === 'object' && res!==null ? res : obj<br>}
instanceof
function MyInstanceOf(a, b) {<br> let proto = a.__proto__ //隐式原型<br> let prototype = b.prototype //显式原型<br> while (true) {<br> if (proto === null) return false<br> if (proto === prototype) return true<br> proto = proto.__proto__<br> }<br>}<br>
手写发布订阅
手写柯里化
threejs
场景Scene、相机PerspectiveCamera、渲染器WebGLRenderer、加载模型的GLTFLoader、环境光DirectionalLight、材质、纹理、贴图
算法题
说一下数组和链表的区别?
数组的存储空间是有序的,元素的查找更快,链表是不连续存储空间,元素的删除插入更快
两数之和
说一下知道的排序算法和它的时间复杂度?
最长回文子串?
最长递增子序列?
判断链表有环?
反转链表?
LRU缓存?
判断一个整数是否为k的幂?
大数相加?
最长回文子串:https://forum.juejin.cn/youthcamp/post/7052356626124111903?from=2<br>字符全排列:https://forum.juejin.cn/youthcamp/post/7047733568084115487?from=2<br>数字金额格式化:https://forum.juejin.cn/youthcamp/post/7052355503636086814?from=2<br>判断一个整数是否为k的幂:https://forum.juejin.cn/youthcamp/post/7052355622095814670?from=2
排序算法?
树的遍历?
层序遍历(广度优先)O(n)在一层循环中读取left和right
做了哪些基建?
关键路径渲染?
0 条评论
下一页