(1)Vue2和Vue3的主要区别?

响应式系统重构(核心变化)

  • Vue 2: 使用 Object.defineProperty 来劫持数据的 getter 和 setter。它对对象的属性进行监听,但无法直接监听数组索引长度的变化(需要通过重写数组方法实现),也无法监听对象属性的添加或删除(需要使用 Vue.setVue.delete)。
  • Vue 3: 使用 Proxy 重写了响应式系统。
    • 性能更好: 可以拦截对象的各种操作,包括属性的添加、删除等,无需特殊 API。
    • 支持更好的数据结构: 原生支持 MapSetWeakMapWeakSet
    • 惰性递归: 只有在真正访问到的嵌套属性才会被代理,提升了初始化性能。

组合式 API (Composition API)

这是对开发者影响最大、最直观的变化。

  • Vue 2 (Options API):
    将代码按照选项(data, methods, computed, watch, 生命周期等)进行组织。当组件逻辑复杂时,同一个功能的代码会被拆分到不同选项中,导致阅读和维护困难。
  • Vue 3 (Composition API):
    引入了 setup 函数,允许你根据逻辑功能来组织代码,而不是根据选项类型。所有相关的逻辑(状态、方法、计算属性、生命周期等)都可以放在一起,使得代码更内聚、更易于复用(通过自定义组合式函数)。

生命周期

  • 大部分生命周期钩子都被重新命名,以对应组合式 API 中的函数。
  • beforeDestroydestroyed 被更名为 beforeUnmountunmounted,更符合其语义。
  • Vue 3 组合式 API 中,生命周期钩子都以 onXxx 的形式存在,如 onMounted, onUpdated 等。

(2)computed和watch的区别,分别主要运用场所?

特性

Computed (计算属性)

Watch (侦听器)

定义

基于它们的响应式依赖进行缓存的派生值。

监听一个或多个响应式数据源,并在其变化时执行副作用

返回值

必须返回一个值。

没有返回值,通常执行异步或开销较大的操作。

缓存

有缓存。依赖不变时,直接返回缓存结果。

无缓存。每次变化都会执行函数。

异步操作

不允许在计算函数内进行异步操作。

允许并常用于异步操作(如API请求)。

依赖追踪

自动追踪所有在内部使用的响应式依赖。

显式指定要侦听的一个或多个数据源。

初始执行

默认在首次访问时就会计算。

默认情况下,组件初始化时不会执行。可通过immediate: true

强制立即执行。

语法

作为属性使用(在模板中直接当做数据属性)。

是一个函数或对象配置,需要在watch选项中定义。

  • 当你想要基于现有数据计算出一个新的数据,并且这个新数据要在模板中展示时,使用 computed 它高效、简洁,且是声明式的。
  • 当需要在数据变化时执行异步请求、复杂的业务逻辑或“副作用”操作时,使用 watch 它更强大、更灵活,但性能开销相对较大。

一个简单的判断法则:
问自己一个问题:“我是在计算一个值,还是在响应一个变化?”

(3)session和localstorge、cookie的异同?

核心异同概览表

特性

Cookie

LocalStorage

SessionStorage

生命周期

可设置过期时间,未设置则随浏览器关闭失效

永久存储,除非手动清除

会话级,页面关闭即清除

数据大小

~4KB

~5MB 或更多

~5MB 或更多

与服务端通信

会自动在每次请求的 HTTP Header 中携带

不参与

不参与

可访问性

同源窗口均可访问

同源窗口均可访问

仅同一浏览器标签页可访问

API 易用性

原生 API 不友好,通常使用库

简单的键值对 API

简单的键值对 API

存储位置

浏览器和服务器

仅浏览器

仅浏览器

Cookie 是为服务端识别用户状态而设计的,因此它的设计核心是与服务端通信

特点:

  • 容量小: 每个域名下的 Cookie 大小限制约为 4KB,数量也有限制(约 20-50 个,因浏览器而异)。
  • 自动携带: 浏览器会自动在同源的 HTTP 请求头(Cookie 头)中携带 Cookie 信息,这会影响请求性能(尤其是未使用 HTTP/2 时)。
  • 生命周期可控: 通过 ExpiresMax-Age 设置过期时间。没有设置则成为 Session Cookie,浏览器关闭即失效。
  • 安全性: 可以设置 HttpOnly 属性来防止 JavaScript 读取,增强安全性(常用于存储身份认证令牌)。也可以设置 Secure 属性要求仅在 HTTPS 下传输。

主要运用场所:

  1. 用户身份认证 (Authentication): 存储 Session ID 或 Token,这是其最核心的用途。
  2. 个性化设置: 如用户的语言偏好、主题设置。
  3. 跟踪用户行为: 与分析工具(如 Google Analytics)结合使用。
2. LocalStorage

LocalStorage 是 Web Storage API 的一部分,用于纯粹的客户端存储

特点:

  • 容量大: 通常为 5MB 或更多,远大于 Cookie。
  • 永久存储: 数据永久保存在浏览器中,除非用户手动清除或通过 JavaScript 删除。
  • 不参与服务端通信: 数据不会自动发送到服务器,减少了不必要的数据传输。
  • 同源共享: 同一协议、域名、端口下的所有页面和标签页都可以访问相同的数据。

主要运用场所:

  1. 缓存静态资源: 缓存不常变化的 API 数据、HTML 模板等,提升应用性能。
  2. 保存用户偏好: 如编辑器的内容草稿、网站的 UI 配置(如侧边栏是否收起)。
  3. 离线数据存储: 在 PWA 或离线应用中存储关键数据。
3. SessionStorage

SessionStorage 与 LocalStorage 接口完全相同,但生命周期不同

特点:

  • 会话级生命周期: 数据仅在当前浏览器标签页有效。关闭标签页,数据即被清除。
  • 标签页隔离: 即使是同一个页面,在不同标签页中打开,它们的 SessionStorage 也是完全隔离的。
  • 刷新页面数据保留: 刷新当前标签页,SessionStorage 数据不会丢失。

主要运用场所:

  1. 单次会话的敏感信息: 存储一次性令牌或表单数据,关闭页面后自动清除,更安全。
  2. 页面间临时传递数据: 在单页应用(SPA)或同源的多页面间,在同一标签页内跳转时传递复杂参数。
  3. 表单内容暂存: 防止用户意外刷新页面导致表单内容丢失。

(4)ES6有哪些常用的语法?

  1. 变量声明:let和const
  2. 箭头函数
  3. 模板字符串,通过``来创建字符串,支持嵌入变量与多行文本
  4. 解构赋值:从数组或对象中提取值,并赋值给变量
  5. 默认参数:运行为函数参数提供默认值
  6. 扩展运算符(...),将可迭代对象(如数组、对象)展开
  7. 剩余参数(...):将不定数量的参数表示为一个数组
  8. Promise:用于处理异步操作,解决“回调地域”的问题
  9. 支持模块化:通过export和import将代码拆分到不同的文件中
  10. for...of 循环: 遍历可迭代对象(如数组、字符串)的值。

(5)forEach和map的区别与使用场景?

特性

forEach

map

返回值

undefined

一个新的数组

目的

遍历并执行副作用

遍历并转换数据

是否改变原数组

不会(但回调函数可以改变)

绝对不会

链式调用

不支持(因为返回 undefined

支持(因为返回数组)

性能

轻微优势(仅遍历,不创建新数组)

轻微开销(需要创建和返回新数组)

使用场景

执行操作,如打印、DOM 操作、修改外部变量

数据转换,如格式化、提取属性、计算新值

1. forEach

forEach 方法用于遍历数组的每个元素并对每个元素执行一个函数。这个函数的目的通常是产生"副作用",比如修改外部变量、操作 DOM、调用 API 等。

语法:

array.forEach(function(currentValue, index, arr) {
  // 执行某些操作
}, thisValue);

特点:

  • 返回值: undefined
  • 不改变原数组: 它本身不会改变原数组,但你在回调函数里可以对原数组进行修改。
  • 无法中途停止: 不像 for 循环可以使用 breakforEach 会遍历所有元素。
  • 使用场景:执行副作用操作(最常用);修改外部变量;操作 DOM 元素。
2. map

map 方法用于遍历数组的每个元素,并对每个元素执行一个函数,然后收集所有函数的返回值,组成一个新的数组。它的核心思想是"映射"或"转换"。

语法:

const newArray = array.map(function(currentValue, index, arr) {
  // 返回一个新的值
}, thisValue);

特点:

  • 返回值: 一个新的数组,长度与原数组相同。
  • 纯函数理念: 理想情况下,map 的回调函数应该是纯函数,即不修改原数组或任何外部状态,只依赖于输入参数返回一个新值。
  • 链式调用: 因为它返回一个数组,所以可以继续调用其他数组方法。
  • 使用场景:数据转换/格式化(最常用);渲染列表;数学运算。
一个简单的决策法则:

问自己:"我需要从这次遍历中得到一个新数组吗?"

  • 需要 -> 使用 map
    • 例如:将对象数组转换为字符串数组、为每个元素计算新值。
  • 不需要,我只是想对每个元素做点事情 -> 使用 forEach
    • 例如:打印每个元素、将元素保存到数据库、为 DOM 元素添加事件

(6)Vue2与Vue3的生命周期?

下面这个表格汇总了 Vue 3 生命周期函数的主要信息,你可以快速了解其与 Vue 2 的对比和基本用途:

生命周期阶段

Vue 2 (Options API)

Vue 3 (Composition API)

说明与用途

创建阶段

beforeCreate

❌ 被 setup()

替代

组件实例开始创建,data

methods

未初始化

created

❌ 被 setup()

替代

组件实例创建完成,可访问 data

methods

,模板未挂载

挂载阶段

beforeMount

onBeforeMount

模板编译完成,尚未挂载到 DOM

mounted

onMounted

模板已挂载到 DOM,可操作 DOM、发起 API 请求

更新阶段

beforeUpdate

onBeforeUpdate

数据变化,虚拟 DOM 重新渲染前

updated

onUpdated

数据变化,虚拟 DOM 重新渲染后

卸载阶段

beforeDestroy

onBeforeUnmount

实例销毁前,清理定时器、事件监听

destroyed

onUnmounted

实例销毁后,所有绑定已解除

KeepAlive 组件

onActivated

被缓存的组件激活时

onDeactivated

被缓存的组件停用时

(7)onUnmounted一般用于什么场景,处理什么事情?

onUnmounted 在组件实例被完全卸载(销毁)之后调用。此时,组件所有的指令都已解绑、事件监听器被移除、子组件实例也都被销毁。

它的主要用途是执行清理工作,防止内存泄漏和意外的行为。

主要运用场景与处理事项

onUnmounted 就像一个“保洁员”,在组件“离开”(销毁)时,负责打扫干净它留下的“痕迹”。

1. 清除定时器 (最常用)

这是 onUnmounted 最经典的应用场景。如果你在组件中设置了 setIntervalsetTimeout,必须在组件销毁时清除它们,否则即使组件不存在了,定时器仍然会在后台执行,导致内存泄漏和不可预知的错误。

2. 移除事件监听器

如果你在组件中添加了全局或第三方库的事件监听器(如 addEventListener),也需要在组件销毁时移除它们。

3. 取消异步操作(如 API 请求)

对于已经发送但尚未完成的异步请求(如 Axios 请求),可以使用 CancelToken(Axios)或 AbortController(Fetch API)来取消它们,避免在组件已销毁后还去更新已经不存在的组件状态。

4. 清理第三方库的实例

如果你在组件中初始化了第三方库(如图表库、地图库、富文本编辑器等),通常需要在组件销毁时手动清理它们。

5. 手动清理响应式订阅

如果你手动创建了一些响应式订阅(例如使用 watchwatchEffect),它们通常会自动停止。但在某些边缘情况下,你可能需要手动停止。

(8)介绍一下Promise.all?

Promise.all 是一个非常重要的 Promise 并发处理工具,它用于管理多个异步操作,并在所有操作都成功完成后统一处理结果。

Promise.all(iterable) 方法接收一个可迭代对象(通常是一个 Promise 数组),并返回一个新的 Promise。

它的行为特点是:

  • 全部成功: 当所有输入的 Promise 都成功完成(fulfilled)时,返回的 Promise 才会成功,结果是一个包含所有 Promise 结果的数组,顺序与输入顺序一致
  • 一个失败即失败: 如果其中任何一个 Promise 被拒绝(rejected),返回的 Promise 会立即拒绝,并返回第一个拒绝的 Promise 的原因。

(9)暂时性死区什么意思?

"暂时性死区"(Temporal Dead Zone,简称 TDZ)是 ES6 中与 letconst 变量声明相关的一个重要概念。

暂时性死区 指的是:在代码块内,从块开始变量声明语句执行前的这段区域,在这段区域中访问该变量会抛出 ReferenceError

换句话说,变量在声明之前是"不可用"的,不像 var 那样会返回 undefined

(10)是如何学习前端的?

它考察的是你的学习能力、主动性和成长潜力。公司希望招聘的是一个能持续进化、跟上前端日新月异发展的“学习型”人才。

我的回答会围绕一个核心策略展开:“建立体系、多管齐下、实践驱动、融入社区”

学习方法分为以下四个层次,由基础到进阶:

层次一:打好基础,建立知识体系(系统性学习)

这是构建我前端知识树的“主干”。

  1. 官方文档:我的第一选择
    • 途径: MDN Web Docs、Vue.js 官方文档、React 官方文档、Node.js 官方文档。
    • 为什么: 官方文档是最准确、最及时、最权威的信息来源。任何新技术,我的第一步永远是通读其官方文档的核心概念。它能帮我建立最正确的认知,避免被二手资料误导。
  1. 经典书籍与系统课程:构建深度
    • 书籍: 《JavaScript高级程序设计》(红宝书)、《你不知道的JavaScript》系列。书籍能提供系统、深入的知识体系,帮助我理解“为什么”。
    • 课程: 国内外优秀的大学公开课(如CS61A)或体系化的在线课程(如freeCodeCamp),用于夯实计算机基础。
层次二:保持敏锐,追踪技术动态(碎片化输入)

这是为我的知识树添砖加瓦的“枝叶”。

  1. 技术社区与资讯平台:保持前沿
    • 途径: GitHub、掘金、Stack Overflow、V2EX。
    • 怎么做:
      • GitHub: 每天会看 Trending 榜单,了解有什么新库、好项目诞生。我会 Star 优秀的项目,并阅读其源码学习设计思想。
      • 掘金: 浏览高质量的技术文章,关注官方账号和业界大佬,了解最佳实践和行业动态。
  1. 优质 Newsletter 与技术博客:信息过滤
    • 途径: JavaScript Weekly、Node Weekly、阮一峰的网络日志、以及一些国外团队(如React, Vite核心团队)的博客。
    • 为什么: 信息过载的时代,这些渠道帮我做了高质量的信息筛选,让我能用最少的时间获取最精华的内容。
层次三:动手实践,从输入到输出(核心关键)

这是将知识内化的最重要一环。

  1. “做”项目:从模仿到创造
    • 个人项目: 我不会只停留在看教程。当我学到一个新特性(比如 Vue 3 的 Composition API),我会立即创建一个小的 Demo 项目来亲手实践。
    • 复盘与重构: 对于做过的项目,我时常会回顾,思考“如果现在重写,我会如何优化?”(例如:能否用 TypeScript 重构?能否用更好的状态管理?)这个过程让我进步飞快。
  1. 贡献开源与阅读源码:向高手学习
    • 途径: GitHub。
    • 怎么做: 我会从修复一些知名开源库的简单 typo 或文档错误开始,逐步尝试去解决一些 good first issue。更重要的是,我会选择一些我日常使用的、代码优雅的库(如 Vueuse)去阅读其源码,学习其架构设计和代码规范。
层次四:交流分享,巩固与反馈

这是检验和提升学习成果的最终环节。

  1. 写作与分享:费曼学习法
    • 途径: 写技术博客、在团队内做技术分享。
    • 为什么: “教是最好的学”。当我尝试把一个问题清晰地讲给别人听时,我必须彻底理解它。写作和分享的过程能暴露我的知识盲点,促使我进一步查漏补缺。
  1. 与人交流:融入圈子
    • 途径: 参加线下技术沙龙、与公司的前辈和同事交流、在技术群里讨论问题。
    • 为什么: 交流能帮我打破信息茧房,获得不同的视角和思路。

总结

以官方文档和经典书籍为根基,以动手实践为核心驱动,并通过技术社区和写作分享来保持敏锐和巩固知识的立体化模式。在这个快速发展的领域,持续学习的能力比当前掌握的知识更重要。”

(11)开发过程中遇到的坑,怎么解决的?

面试官想考察的不是你从不犯错,而是你的问题解决能力、复盘总结能力和抗压能力。回答这个问题的关键在于:将一个“坑”转变为一个展示你能力的“故事”

下面我将为你提供一个结构化的回答框架、一个高价值的示例,以及一些备选的“坑”和回答要点。

回答框架(STAR 原则)

用 STAR 原则来组织你的回答,让故事清晰有力:

  1. Situation: 简要描述项目背景和你的角色。
  2. Task: 你当时要完成的具体任务是什么?
  3. Action:具体做了什么来排查和解决问题?(这是重点,要体现你的思考过程)
  4. Result: 问题最终如何解决?你从中学到了什么?后续如何预防?

注意事项

  • 诚实,但要有策略: 不要说自己没踩过坑。选择一个真实的、你已经解决的、并且能体现你学习能力的问题。
  • 强调过程和成长: 重点不是你掉进了坑里,而是你如何爬出来的,以及你如何在坑边立了警示牌。
  • 技术深度: 尽量选择一个有技术含量的坑,能展示你对原理的理解。
  • 规避“低级错误”和“态度问题”: 不要讲因为粗心大意(如单词拼写错误)导致的坑,也不要讲因为和同事吵架导致的坑。
  • 积极收尾: 故事的结尾一定要落在“我学到了什么”和“我如何做得更好”上。
Logo

分享最新、最前沿的AI大模型技术,吸纳国内前几批AI大模型开发者

更多推荐