前端八股文精华
# 1. cookies、sessionStorage 和 localStorage 区别
1、cookie 是用来跟踪浏览器用户身份的会话方式。
2、cookie 机制:如果不在浏览器中设置过期时间,cookie 被保存在内存中,生命周期随浏览器的关闭而结束,
这种 cookie 简称会话 cookie。如果在浏览器中设置了 cookie 的过期时间,cookie 被保存在硬盘中,
关闭浏览器后,cookie 数据仍然存在,直到过期时间结束才消失。
3、单个 cookie 保存的数据不能超过 4kb
4、sessionStorage 为临时保存,而 localStorage 为永久保存
5、localStorage 和 sessionStorage 的存储数据大小一般都是:5MB
6、localStorage 和 sessionStorage 都保存在客户端,不与服务器进行交互通信。
# 2. flex:1 代表什么?
当一个元素设置 “flex:1” 时,它表示这个元素的 “flex-grow”(扩展比例)为 1、“flex-shrink”(收缩比例)为 1、“flex-basis”(初始大小)为 0%。
# 3. 强缓存和协商缓存
"强缓存和协商缓存是 HTTP 缓存的两种机制。
强缓存不向服务器发送请求,而是根据响应头中的缓存策略,决定是否直接从本地读取。
协商缓存会发送请求到服务器,由服务器判断资源是否变化:
未变化:返回 304,浏览器使用本地缓存
已变化:返回 200 和新资源
# 4. 标签上 title 属性与 alt 属性的区别是什么?
title 属性通常用于为元素提供额外的信息,当鼠标移入时显示出来
alt 属性是一个专门用于<img>标签的属性,当图像因为各种原因无法显示时,替代文本将被显示处理
# 5. 列举常用的 ES6 特性:
1.let、const 2.箭头函数 3.类的支持 4.字符串模块
5.symbols
6.Promises
# 6. Pinia 相对 vuex 的优点
Pinia 是一个基于 Vue3 的状态管理库,相较于 Vuex, pinia 更加轻量
它的代码量更少,体积更小,加载速度更快。
pinia 采用分离模式,每个组件都拥有自己的 store 实例,通过创建 store 实例来管理状态
vuex 采用单列模式,通过一个 store 来管理所有的状态。
pinia 简化了 api,无需 mutations,直接使用 state,getters 和 actions,语法更直观,
vuex 使用 mutations,actions 和 getters 来定义状态,修改和异步操作,api 较为繁琐
# 7. 父组件子组件的通信方式
1. props
2. $emit和$on
3. $parent 和 children
4. $attrs 和 $listeners
5. provide 和 inject
6. eventBus
7. vuex
8. $refs
# 8. px-%-em-rem-vw-vh
px: 屏幕像素单位
%: 百分百单位
em: 元素的 font-size 字体大小
rem: 根元素<html>的 font-size 大小
vw/vh: 浏览器可视窗口大小
# 9. 遍历一个数组用 for 和 foreach 那个更快
答案是 for
forEach 是一个高阶函数:它需要为数组中的每个元素调用一次回调函数,每次函数调用都会产生一定的开销
for 循环没有额外调用
# 10. js 严格模式有什么特点
1.变量必须声明后再赋值 2.禁止使用 with 语句 3.禁止 this 关键字指向全局对象 4.禁止函数参数重名
# 11. 如何进行首屏加载优化
减少 HTTP 请求 : 合并 CSS、JS 文件,减少并发请求数量
使用雪碧图(CSS Sprites)合并小图标,减少图片请求
压缩资源体积 : 对 HTML、CSS、JS 启用 Gzip 或 Brotli 压缩,显著减小传输体积
图片优化 : 采用现代格式(如 WebP),比 JPEG/PNG 小 30%–50%
设置强缓存/协商缓存
部署 CDN 加速
预加载关键资源: 使用<link rel="preload">提前加载首屏必需的 CSS、JS 或字体
# 12. webSocket 和 http 协议有什么区别
http 的通信模式是单向的,websocket 是全双功
http 只能由客服端发起请求,websocket 可以由客服端或者服务端发起
http 有跨域限制,websocket 没有跨域限制
# 13. 什么是 SSR(服务端渲染),原理是什么? 好处有哪些?
“SSR 的核心原理就是在服务端执行原本属于客户端的组件渲染逻辑,将动态组件转化为静态 HTML 字符串下发给客户端。”
1. SSR(服务器端渲染)有利于 seo 的搜索
的,而有了 SSR 以后,这些抓取工具就可以立刻得到完整的 HTML 结构化数据,从而被纳入搜索引擎。
2. 更短的白屏时间:服务端渲染并不需要加载和执行大量的 js 脚本, 直接渲染服务端给出的 html 字符串, 从而缩短首屏加载时间
不好的地方: 前后端分工搭配复杂, 原本一个页面, 同时由前后端绘制填充
# 14. Vue 的路由 hash 模式 和 history 模式的区别?
Hash 模式是通过切换#号后面的哈希地址来进行页面切换的,hash 的兼容性好但 URL 不美观,
不利于 SEO。History 模式利用 HTML5 的 HistoryAPI 来修改浏览器的历史记录实现界面的切换,
URL 更美观且利于 SEO,但兼容性较差。
# 15. 计算属性和 watch 的区别?
computed 计算属性,依赖其他的属性值,并且 computed 的属性值有缓存属性,当属性值变化的时候,下一次获取 computed 属性的时候才会重新计算 computed 的值。
watch 是一种观察的作用,用于监听某些数据的回调。每当所监听的数据发生变化时才能执行回调处理后续操作计算属性可以一对多,而 watch 是一对一
# 16. v-show 和 v-if 指令的共同点和不同点
v-show 指令是通过修改元素的 display 的 CSS 属性让其显示或隐藏
v-if 指令是直接销毁和重建 DOM 节点,达到让元素显示和隐藏的效果
# 17. <keep-alive></keep-alive>的作用是什么?
keep-alive 标签包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染
# 18. 为什么避免 v-if 和 v-for 用在一起?
v-for 的优先级比 v-if 高,这会导致每次循环时都要进行条件判断,造成不必要的性能开销。
# 19. vue 生命周期
生命总共分为 8 个阶段创建前/后、载入前/后、更新前/后、销毁前/后
创建前/后 :
在 beforeCreate 阶段,vue 实例的挂载元素 el 和数据对象 data 都为 undefined,还未初始化。
在 created 阶段,vue 实例的数据 data 有了,el 还没有
载入前/后:
在 beforeMount 阶段,vue 实例的$el 和 data 都初始化了,单还没有挂载之前都是虚拟的 demo 阶段,data.message 还未替换.
在 mounted 阶段,vue 实例挂载完后,data.message 成功渲染.
更新前/后:当 data 变化时,户触发 beforeUpdate 和 update d方法。
销毁前/后:beforeDestroy,destroyed
在执行 destroy ed方法后,对 data 的改变不会再触发周期函数,说明此时 vue 实例已经结束了事件监听以及和 dom 的绑定,但是 dom 结构依然存在。
# 20. Vuex 的五大属性:
Vue 有五个核心概念:state、getters、mutations、actions、modules
state => 基本数据
getters => 从 state 中派生出一些状态(类似计算属性)
mutations => 同步地修改 state 的唯一途径
actions => 提交 mutation 来修改 state,可以包含异步操作
modules => 模块化 Vuex,将 store 分割成模块,每个模块拥有自己的 state、mutation、action、getter
# 21. 页面导入样式时,使用 link 和@import 有什么区别?
1、link 属于 XHTML 标签,除了加载 CSS 之外还能用于定义 RSS,@import 是 CSS 提供的,只能用于加载 CSS
2、link 加载的文件,在页面加载的时候,link 文件会同时加载,而@import 引入的 CSS 文件,是页面在加载完成后再加载的
3、@import 有兼容性问题,IE5 以下的浏览器是无法识别的,而 link 无兼容性问题
# 22. Iframe 有哪些缺点?
Iframe 会阻碍页面的 onload 事件
浏览器的搜索引擎一般读无法解读 iframe 页面,不利于 SEO 的搜索
# 23. 浏览器盒模型?
盒模型分为两种: IE 盒模型和 W3C 盒模型
W3C: 宽度/padding/border/margin 都是单独分开的
IE 盒模型: 宽度 = 内容宽度+padding+border+margin 是一起的
# 24. http 请求方式有哪些?
HTTP1.0 定义了三种请求方法: get, post 和 head 方法。
HTTP1.1 新增了五种请求方法:options, put, delete, trace 和 connect 方法。
# 25. 什么是 css hack
CSS Hack 是指为了解决不同浏览器对 CSS 解析和渲染的差异,而编写的一些特殊的 CSS 代码。
这些代码能够被特定浏览器识别,从而实现对不同浏览器的兼容。
# 26. src 和 href 的区别
src 和 href 都是 HTML 中用于引入外部资源的属性
href 用于建立当前页面与引用资源之间的链接,而 src 引入资源则会替换当前标签内容。
href会并行加载后续内容,而 src 则不同,浏览器需要加载完毕 src 的内容才会执行后续内容。
# 27. 如何解释 this 在 js 中起的作用?
Js 中的 this,一般取决于调用这个函数的方法
1/如果函数被实例化(new 构造函数名())的情况下,this 指向全新的对象
2/如果是某标签触发什么事件,调用了这个函数,this 指向标签(整个 DOM 节点,包含它的子元素);
3/如果函数使用了 call/apply,this 是作为参数传入对象
4/有时候 this 指向不明确的话,this 会指向 window,ES6 中的箭头函数修改了 this 指向,永远指向作用域
# 28. 什么是原型
原型是 JavaScript 实现继承的基础机制,用来实现属性和方法的共享。
# 29. 什么是原型链
原型链是 JavaScript 中每个对象通过 __proto__ 连接起来形成的链式结构,用来规定属性或方法的查询路径,
当我们访问一个对象的属性时,如果对象本身没有,JS 引擎会沿着 __proto__ 逐级向上查找,
直到找到目标属性或到达链的终点 null。
# 30. 继承的方法有哪些?
原型链继承、构造继承、实例继承、拷贝继承、组合继承、寄生组合继承
# 31. 什么是闭包?闭包有什么作用?
闭包是指一个函数能够记住并访问它被创建时的词法作用域,即使这个函数在其词法作用域之外执行。
作用: 1.闭包可以创建私有变量 2.闭包可以实现模块化,避免全局变量污染
# 32. new 操作符在创建实例的时候经历了哪几个阶段
new 创建了一个对象,共经历了 4 个阶段:
1.创建一个空对象
2.设置其原型链
3.让实例化对象中的 this 指向对象,并执行函数体
4.判断实例化对象的返回值类型
# 33. forEach 和 map 的区别在哪里
forEach 无返回值,map 返回一个新数组。
forEach无法进行链式调用,map可以进行链式调用
forEach无法等待异步操作,map可以使用promise.call或者promise.callsettled等待异步任务
forEach无法进行链式调用,map可以进行链式调用
forEach无法等待异步操作,map可以使用promise.call或者promise.callsettled等待异步任务
# 34. ==与===的区别?
===为等同符,当左边与右边的值与类型都完全相等时,会返回 true;
==为等值符,用来判断值是否相同,不会判断类型是否相同
# 35. addEventListener 监听点击事件与 click 事件有什么区别?
addEventListener 可为同一元素绑定多个点击事件处理器,click 只能绑定一个点击事件处理器
addEventListener可控制事件流 可通过第三个参数控制事件处于捕获阶段还是冒泡阶段
click 仅支持冒泡阶段,无法控制事件流。
# 36. null 和 undefined 的区别?
数据类型不同:
undefined的类型是 'undefined'
null的类型是 'object'
语义不同:
undefined表示变量已声明但为初始化,也表示属性不存在或者函数没有返回值
undefined的类型是 'undefined'
null的类型是 'object'
语义不同:
undefined表示变量已声明但为初始化,也表示属性不存在或者函数没有返回值
null表示人为将变量设置为空
# 37. TCP 三次握手四次挥手
第一次握手:客服端向服务器发送 syn 包请求建立连接,然后等待服务器的确认。
第二次握手:服务器收到客服端的 syn 包,必须确认客服端的 syn 包,同时自己也发送一个 syn+ack 包,
第三次握手:客服端收到服务器的 syn+ack 包,向服务器发送确认包(ack),次包发送完毕,(TCP 连接成功),完成三次握手。
第一次挥手:客服端向服务器发送连接释放报文,并且停止向服务器发送数据
第二次挥手:服务器收到了连接释放报文,并发出确认报文。
第三次挥手:客服端收到服务器的确认报文后,就进入(终止等待)状态,等待服务器发送连接释放报文
第四次挥手:服务器将最后的数据发送完毕后,就向客服端发送连接释放报文,客服端收到服务器的连接释放报文后,
并进行确认,然后必须经过(最长报文段寿命)的时间后,才结束这次的 TCP 连接
# 38. 为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为服务器可能存在未发送完的数据,因此服务器不会立即关闭,
只能先回复一个 ack 报文,告诉客服端,你发送的释放连接请求我收到了,
只有等服务器所有的报文都发送完了,
服务器才能发送连接释放报文,故需要四步。
# 39. 为什么 TIME_WAIT 状态需要经过 2MSL(最大报文段生存时间)才能返回到 CLOSE 状态?
因为网络是不可靠的,有可能最后一个 ack 丢失,所以 hime_walt 状态是用来重发可能丢失的 ack 报文,
客服端会设置一个计时器,等待 2MSL 的时间,如果在该时间客服端收到了 FIN 报文,
客服端会重发 ack 并再次等待 2MSL 的时间,如果直到 2MSL,客服端都没有再次收到 FIN,那么客服端就会推测 ack 已经被成功接收,则结束 TCP 连接
# 40. TCP 与 UDP 的区别
1、TCP 面向连接;UDP 是无连接的,即发送数据之前不需要建立连接
2、TCP 提供可靠的服务,通过 TCP 连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即,不保证可靠交付
3、TCP 面向字节流;UDP 是面向报文的 UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低
4、TCP 连接只能是点到点的;UDP 支持一对一,一对多,多对一和多对多的交互通信
5、TCP 的逻辑通信信道是全双工的可靠信道,UDP 则是不可靠信道
# 41. git 和 post 的本质区别是什么
git 产生一个 TCP 数据包,POST 产生两个数据包。
对于 git 方式的请求,浏览器会把 http,header,data 一并发送出去,服务器响应 200,
post 方式的请求,浏览器会先发送 header,服务器响应 100,后,浏览器在发送 data,服务器响应 200.
# 42. 网页从输入网址到渲染完成经历了哪些过程?
大致可以分为如下 7 步:
输入网址;
服务器解析域名获取对应的 ip 地址;
浏览器与服务器建立 TCP 连接;
浏览器向服务器发送 http 请求;
服务器响应请求,并返回指定 url 的数据;
浏览器下载 web 服务器返回的数据及解析 html 源文件;
生成 DOM 树,解析 css 和 js,渲染页面,直至显示完成
# 43. Vue 路由跳转和 location.href 的区别?
Vue 路由跳转和 location.href 的区别主要在于它们的实现方式和对页面的刷新行为。
1. 实现方式:
Vue 路由跳转:Vue 使用前端路由机制,通过改变 URL 的 hash 或使用 HTML5 的
history API 来实现页面之间的切换,而不需要进行完整的页面刷新。Vue 路由可以通过
<router-link> 或编程式导航(例如 this.$router.push() )来实现页面的跳转。
location.href :是浏览器提供的原生 JavaScript 属性,用于获取或设置当前页面的
URL 地址。直接修改 location.href 可以触发浏览器的页面刷新,跳转到新的 URL。
2. 页面刷新行为:
Vue 路由跳转:在 Vue 路由中,页面的切换通常是在同一个页面中进行的,只是动态地
加载不同的组件内容,因此不会触发完整的页面刷新。这样可以提高用户体验,避免重
新加载整个页面。
location.href :通过修改 location.href 来进行页面跳转会触发浏览器的完整刷
新,重新加载整个页面。这会导致之前的页面状态丢失,并且对服务器产生额外的请求
负担。
# 44. vue 创建组件的时候 data 中为什么会要 return 出一个对象?
用 return 返回对象可以保证每个组件实例都有自己独立的数据,不会互相影响.
# 45. 什么是防抖和节流
防抖:防抖的主要目的是延迟函数的执行,直到事件停止触发一段时间后才执行。
节流: 节流的核心思想是在一定时间内限制函数的执行频率,保证在一定时间内最多执行一次。
# 46. 简述 promise
Promise 对象是 CommonJS 提出的一种规范,目的是为异步编程提供的一种解决方案。每
一个异步任务返回一个 Promise 对象,该对象有一个 then 方法,允许指定回调函数。
一个 promise 有三种状态:等待(pending)、已完成(resolved,又称 fulfilled)、
已拒绝(rejected)。一旦状态改变(从 pending 变成 fulfilled 或从 pending 变成 rejected),就不会在变,任何时候都可以得到这个结果
# 47. VUE 响应式的原理?
采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter, getter
默认 Vue 在初始化数据时,会给 data 中的属性使用 Object.defineProperty 重新定义所有属性,当页面到应用到属性时,
会进行依赖收集,如果属性发生变化会通知相关依赖进行更新操作;
# 48. 为什么 Vue 采用异步渲染?
是为了性能考虑,异步渲染的核心目的是将多次数据变化合并为一次 DOM 更新,避免不必要的重复渲染。
# 49. Proxy 与 Object.defineProperty() 对比
Proxy 的优点:
·可以代理整个对象,无需递归遍历;
·解决了Vue2响应式系统的局限性;
·提供了更全面的拦截能力;
.能自动态监听对象属性
Proxy 的缺点:
·Proxy 是 es6 提供的新特性,兼容性不好无法在IE浏览器使用
Object.defineProperty() 的优点:
·兼容性好,支持 IE9
·IE9 以下的版本不兼容
Object.defineProperty() 的缺点:
·无法监听数组索引赋值和length变化,无法监听新增属性/删除属性
·只能劫持对象的属性,我们需要对每个对象的每个属性进行遍历;
# 50. 为什么使用 key?
使用 key 来给每个节点做一个唯一标识,这样 Diff 算法就可以快速准确的识别此节点。
主要作用是为了高效的更新虚拟 DOM。
# 51. JS 数据类型有哪些?
栈: (原始数据) string/number/boolean/null/undefined/symbol
堆: (引用数据类型)object(array 和函数属于 object)
数据类型一共 7(6 种基本类型+1 种引用类型)
# 52. 什么是作用域
每一个变量、函数都有其作用的范围,超出范围不得使用,这个叫做作用域
# 53. 作用域链
查找变量的过程。先找自己局部环境内部有没有声明或者是函数,如果有,则查看声明有无赋值或者是函数的内容,如果没有,则向上一级查找。
# 54. 变量声明提升
在预编译阶段,编译器会把所有定义的变量全部提升到最顶部.
# 55. 堆和栈的区别?
堆和栈的储存位置不同;
原始数据是储存在栈中简单数据段,体积小,大小固定,属于频繁使用的数据.
引用数据类型是储存在堆中的对象,占据的空间大,如果储存在栈中会影响运行性能,
引用数据类型在栈中指明了自己的所在地.当代码解析时,
会先从栈中获取地址,然后再从堆中获取实体;
# 56. 伪类和伪元素的区别
伪类:选中元素的某种状态或特定位置的元素,不会改变页面的 DOM 结构,作用于现有元素的状态
伪元素: 选中元素的某部分或添加虚拟元素,可以创建虚拟元素在元素前后插入内容
# 57. 深拷贝和浅拷贝的区别
浅拷贝: 仅复制对象的引用而不复制引用的对象本身,因此原始对象和拷贝对象会引用同一个对象。
深拷贝: 则是对对象内部的所有元素进行拷贝,因此原始对象和拷贝对象是完全独立的。
# 58. transition 和 animation 的区别是什么
transition: 过渡属性,只能用于制作简单的动画效果,
animation: 动画属性,可以用来制作类似 flash 动画,可以制作跟复杂的动画
# 59. 怎么判断数据类型
typeof 快速判断基本类型(string、number、boolean 等),无法区分对象具体类型
object.prototype.toString.call()
# 60. 数组常用方法有哪些?
push(),pop(),shift(),unshift(),splice() 屎铺赖 s ,sort() 锁特 ,reverse() 类握屎,map(),forEach()等
# 61. 前端性能优化有哪些
1)、前端优化的目的 1.从用户角度而言,优化能够让页面加载得更快、对用户的操作响应得更及时,能够给用户提供更为友好的体验。 2.从服务器角度而言,优化能够减少页面请求数、或者减小请求所占带宽,能够节省可观的资源。
2)、一、页面级优化 1.减少 HTTP 请求数 2.资源合并与压缩
3.CSS Sprites(雪碧图) 4. 减少不必要的 HTTP 跳转 5.慎用 with 6.减少重定向 7.使用缓存 8.使用 CDN
# 62. apply, call , bind 三者的区别
apply、call 和 bind 都是 JavaScript 中用于改变函数执行时 this 上下文的方法。它们的主要区别在于执行时机和参数传递方式。
执行时机: apply, call 都是立即执行, bind 不会立即执行,返回一个绑定 this 的新函数
参数传递: bind, call 参数以逐个列出的方式传递, apply 参数以数组形式传递
# 63. js 微任务和宏任务有哪些:
微任务:Promise.then、Promise.catch、promise.finally, Object.observe(已废弃)、MutationObserver。
宏任务:setTimeout、setInterval、I / O 操作, UI 渲染
# 64. event loop / js 事件循环机制:
事件循环(Event Loop)是实现异步编程的核心机制。由于 js 是单线程的, 为了不阻塞线程,
js 在设计之初将任务分为同步任务和异步任务, 异步任务被分为宏任务和微任务,
同步任务在主线程中执行, 而异步任务者被放到任务队列中等待,
待主线程执行完同步任务后, 依次执行所有微任务(直到微任务队列为空),再执行宏任务
每执行完一个宏任务都会检查微任务队列,如果有先执行微任务
如此循环往复
# 65. 浏览器渲染原理 / 浏览器渲染机制:
浏览器会将 html 使用 html 解析器解析为 htmldom 树, 将 css 使用 css 解析器解析为 cssom,
然后将htmldom树和cssom树进行样式计算, 构建成一个渲染树。
在构建完渲染树之后, 浏览器会将每一个渲染对象就行布局计算, 确定他们的位置和大小,
待布局完成后, 浏览器将渲染对象转化为像素信息并绘制到屏幕上。
# 66. 什么是重绘和重排?怎么减少浏览器重绘和重排?
重排是指当 DOM 的位置或尺寸发生变化时,浏览器需要重新计算元素的布局,以确保它们正确地显示在页面上。
重绘则是指元素外观发生变化时,浏览器重新绘制元素的外观,但不需要重新布局。
如何减少浏览器重绘和重排: 1.样式集中改变,避免逐个修改 2.使用 absolute 或 fixed 定位 3.减少 DOM 操作 4.使用 CSS3 动画和过渡效果,而不是 JavaScript 来改变元素的位置和尺寸
# 67. nextTick 的原理和作用 ?
原理 : nextTick 的实现依赖于 JavaScript 的事件循环和微任务队列。Vue 在内部会根据当前环境采用不同的异步实现策略:
如果当前环境支持 Promise,则使用 Promise.then 和 Promise.resolve 来实现,将回调函数包装在 Promise 的 then 方法中,
并在当前任务执行完毕后放入微任务队列中。如果不支持 Promise,
则会使用 MutationObserver 或其他宏任务如 setTimeout 作为备选方案。
作用: 确保在 DOM 更新完成后执行操作,从而获取最新的 DOM 状态
# 68. diff 了解过吗
Diff 算法是虚拟 DOM 的核心优化机制,它通过『同级比较、Key 复用、类型判断』三大策略,
降低树对比的复杂度,配合双端交叉对比和最长递增子序列等技巧,实现最小化的 DOM 更新,极大提升了前端框架的渲染性能。
# 69. 虚拟 dom 是什么? 原理? 优缺点?
虚拟 DOM 是一种通过 JS 对象模拟真实 DOM 树结构的技术,用于提高页面渲染的效率,减少浏览器 DOM 操作的频繁性 。
原理: 应用在首次加载的时候,框架会根据组件的模版生成虚拟 dom 树,包含了所有的 dom 元素及其属性.当组件状态或数据发生变化的时候,
框架会重新生成一颗新的虚拟 dom 树,然后框架会对对比新旧虚拟 dom 树的差异,通过 diff 算法的对比结果,框架只会更新需要改变的部分,避免对整个 dom 树的重绘.
优缺点: 提高了性能和渲染效率, 可以在不同的前端框架和环境中使用,有更大的灵活性和可复用性
缺点: 相比直接操作 dom 会占用更多内存, 初次渲染可能比直接操作真是 dom 慢一些
# 70. $set 原理
由于 vue2 使用的是 object.defineProperty, 实现响应式, 导致无法检测对象的属性新增和删除
使用$set 内部会判断目标是否为数组, 如果是就用 splice 触发更新, 如果是对象, 者调用 defineReactive 让属性变成响应式,
并手动 notify 通知依赖更新
# 71. 浏览器垃圾回收机制:
浏览器的垃圾回收机制是一种自动管理内存的机制,它通过标记 - 清除算法来识别和回收不再使用的内存。
具体来说,垃圾回收器会定期从根对象(如全局变量、活动函数的作用域)出发,标记所有可达的对象,
然后清除那些未被标记的不可达对象。为了提升效率,现代浏览器采用分代收集策略,将内存分为新生代(频繁回收短期对象)
和老生代(较少回收长期存活对象),并通过增量回收方式拆分任务,减少页面卡顿。开发者的核心任务是避免内存泄漏,
确保不再需要的对象及时脱离引用关系。
# 72. vue3 和 vue2 区别,做了哪些性能优化:
Vue 3 相较于 Vue 2 是一次全方位的架构升级。vue3 采用 Proxy 重构了响应式系统,解决了 Vue 2 中
Object.defineProperty 无法检测对象属性增删等限制,性能显著提升。vue3 引入了 Composition API,
允许基于逻辑功能组织代码,解决了 Vue 2 的 Options API 在复杂组件中逻辑分散的问题。
Vue 3 支持多个根节点的 Fragment 模板、提供 Teleport 等内置组件、并通过更好的 Tree - shaking 机制减小了打包体积。
# 73. webpack 和 vite 的区别:
Webpack 的构建理念是「打包构建」,Vite 是「按需编译」。
Webpack 会先打包所有模块生成 Bundle,再启动开发服务器,项目越大启动越慢;
Vite 则利用浏览器原生 ES 模块支持,在开发时直接按需编译源文件,启动速度极快。
Vite 开发更轻量,Webpack 生态成熟、功能全面,更适合复杂定制场景。
# 74. 冒泡排序:
function sort(array = [])
{
if (array != null && array.Length > 0) {
for (int i = 0; i < array.Length - 1; i++) {
for (int j = 0; j < array.Length - i - 1; j++) {
if (array[j] > array[j + 1]) {
int tem = array[j + 1];
array[j + 1] = array[j];
array[j] = tem;
}
}
}
}
}
# 75. 手写防抖函数
function debounce(func, delay = 2000) {
let timeout;
return function (...args) {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(this, args);
}, delay);
}
}
# 76. 手写节流函数
function throttle(func, delay = 2000) {
let flag = true;
return function (...args) {
if (!flag) return;
flag = false;
setTimeout(() => {
func.apply(this, args);
flag = true;
}, delay);
}
}
# 77. 手写事件总线
class EventBus {
constructor() {
this.events = {}
}
on(name, callback) {
if (!this.events[name])
this.events[name] = []
this.events[name].push(callback)
}
emit(name, ...arge) {
if (this.events[name])
this.events[name].forEach(callback => callback(...arge))
}
off(name, callback) {
if (this.events[name])
this.events[name] = this.events[name].filter(r => r != callback)
}
}

浙公网安备 33010602011771号