引言
春招来袭,面对面试中的难题,不少人都感到头疼。本文将分享一些常见的面试问题及应对策略,希望能帮助你在准备过程中更加得心应手,顺利通过面试。让我们一起加油,向着理想offer冲刺吧!🚀
vue3 生命周期
Vue 3 的生命周期钩子函数与 Vue 2 类似,但有一些细微的变化和新增的组合式 API(Composition API)钩子。以下是 Vue 3 的生命周期钩子及其执行顺序:
1. beforeCreate
- 触发时机:在实例初始化之后,数据观测 (data observer) 和事件/侦听器配置之前被调用。
 - 用途 :此时组件的 
data和methods还未初始化,通常用于执行一些初始化操作 
2. created
- 触发时机 :在实例创建完成后被立即调用。此时,数据观测 (data observer)、属性和方法的运算、
watch/event事件回调已经设置完成。 - 用途 :可以访问 
data和methods,但 DOM 还未生成,通常用于发起异步请求。 
3. beforeMount
- 触发时机 :在挂载开始之前被调用,相关的 
render函数首次被调用。 - 用途:此时模板已经编译完成,但尚未将模板渲染到 DOM 中。
 
4. mounted
- 触发时机:在实例挂载到 DOM 后被调用。此时,组件已经出现在页面中,DOM 已经生成。
 - 用途:可以访问 DOM 元素,通常用于操作 DOM 或发起依赖于 DOM 的请求。
 
5. beforeUpdate
- 触发时机:在数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
 - 用途:可以在更新之前访问现有的 DOM,例如手动移除事件监听器。
 
6. updated
- 触发时机:在数据更改导致的虚拟 DOM 重新渲染和打补丁之后调用。
 - 用途:可以执行依赖于 DOM 更新的操作,但要注意避免无限循环的更新。
 
7. beforeUnmount (Vue 2 中的 beforeDestroy)
- 触发时机:在实例卸载之前调用。
 - 用途:此时实例仍然完全可用,通常用于清理工作,如取消定时器、移除事件监听器等。
 
8. unmounted (Vue 2 中的 destroyed)
- 触发时机:在实例卸载之后调用。
 - 用途:此时所有的指令和事件监听器都已被移除,子实例也都被销毁。
 
9. errorCaptured
- 触发时机:当捕获一个来自子孙组件的错误时被调用。
 - 用途 :可以用于处理组件树中的错误,返回 
false可以阻止错误继续向上传播。 
10. renderTracked (开发模式)
- 触发时机:在渲染过程中跟踪到响应式依赖时调用。
 - 用途:用于调试,了解哪些依赖被跟踪。
 
11. renderTriggered (开发模式)
- 触发时机:在响应式依赖触发重新渲染时调用。
 - 用途:用于调试,了解哪些依赖触发了重新渲染。
 
生命周期图示
            
            
              plaintext
              
              
            
          
          beforeCreate -> created -> beforeMount -> mounted -> beforeUpdate -> updated -> beforeUnmount -> unmounted
        总结
Vue 3 的生命周期钩子函数与 Vue 2 类似,但在组合式 API (setup 函数) 中,生命周期钩子是通过 onXXX 函数来使用的。
ref 与 reactive 的区别
ref 和 reactive 都是用来创建响应式数据的方法,但它们的使用场景和工作方式有所不同。
ref
- 用途 :
ref主要用于创建一个包含值的响应式引用对象。它可以用来包裹基本类型(如字符串、数字等)或对象类型的数据。 - 访问与修改 :由于 
ref创建的是一个对象,因此在模板中可以直接使用,但在 JS 代码中访问其值时需要通过.value属性来获取或设置值。 - 解构 :当你解构 
ref或者将它传递给函数参数时,你得到的是它的原始值而非响应式的引用。如果需要保持响应性,可以考虑使用toRefs方法。 
reactive
- 用途 :
reactive是用来创建一个响应式的对象。它使得对象的所有嵌套层次都具有响应性,非常适合用于处理复杂状态管理。 - 访问与修改 :直接通过属性名进行访问和修改即可,不需要像 
ref那样使用.value。 - 限制:只能对对象(包括数组和普通 JavaScript 对象)进行代理,不能直接作用于基本数据类型。
 
总结
- 使用 
ref可以更灵活地处理基本类型数据,并且在某些情况下(比如在组合式 API 函数之间共享状态)可能更加方便。 reactive则提供了一种更为直观的方式来处理对象类型的响应式状态,特别是对于那些拥有多个相关联状态属性的情况。
vue3 组件
在 Vue 3 中,为了提升用户体验和优化应用性能,引入了几个关键组件和特性。以下是这些特性的优化介绍:
- 
Transition :
<Transition>组件用于包裹元素或组件,为它们的进入和离开添加动画效果。Vue 自动检测元素或组件的添加或移除,并应用相应的过渡类名,允许通过 CSS 或 JavaScript 钩子自定义进入和离开时的动画。 - 
TransitionGroup : 类似于
<Transition>,但<TransitionGroup>适用于一组需要过渡效果的元素或组件。它不仅处理单个元素的进入和离开,还处理列表中元素的变化,如添加、删除或重新排序。使用<TransitionGroup>包裹的元素必须拥有唯一的key属性。 - 
KeepAlive : 抽象组件
<KeepAlive>缓存动态组件或路由视图,避免切换时销毁和重建组件,有助于维持组件状态,提高用户体验。可通过include和exclude属性指定哪些组件应被缓存。 - 
Teleport :
<Teleport>(之前版本称为 Portal)允许将子组件渲染至 DOM 中的不同位置。不同于常规组件渲染于父组件的内容分发处,<Teleport>可指定一个目标元素作为挂载点,即使该位置位于组件层次结构之外,也能将内容挂载于此。 - 
Suspense : 新增的实验性特性
<Suspense>,在等待异步依赖(例如异步组件)加载完成前显示备用内容。当组件树的一部分正在等待异步操作完成时,<Suspense>能展示加载状态或其他占位符内容,直至所有数据准备就绪。 
vue-router 中的 router和route
在 Vue.js 中,vue-router 是用于实现单页面应用(SPA)路由管理的官方库router 和 route 是 vue-router 中两个非常重要的概念,它们分别代表不同的对象和用途。
1.router 是什么?
router 是 vue-router 的核心实例,负责管理整个应用的路由。你可以把它想象成一个"路由器",它决定了当你点击一个链接或者改变浏览器地址时,应用应该加载哪个组件。
router 的主要职责:
- 路由配置 :你需要在 
router中定义路由规则,比如/home对应Home组件,/about对应About组件。 - 导航控制 :
router提供了导航方法,比如push、replace、go等,用于在代码中跳转到不同的路由。 - 全局钩子 :
router还支持全局的路由守卫(如beforeEach、afterEach),可以在路由跳转前后执行一些逻辑,比如权限校验、页面加载动画等。 
router 的常见用法:
- 在项目中,你会先创建一个 
router实例,并配置路由规则。 - 然后将这个 
router实例挂载到 Vue 的根实例中,这样整个应用就具备了路由功能。 - 在组件中,你可以通过 
this.$router访问router实例,调用它的方法进行导航。 
2.route 是什么?
route 是当前激活的路由对象,它包含了当前路由的详细信息。你可以把它理解为一个"快照",记录了当前路由的状态。
route 的主要职责:
- 提供路由信息 :
route包含了当前路由的路径(path)、参数(params)、查询字符串(query)、哈希值(hash)等信息。 - 动态路由匹配 :如果你的路由是动态的(比如 
/user/:id),route会解析出动态参数(如id),方便你在组件中使用。 - 嵌套路由信息 :
route还包含了嵌套路由的匹配记录(matched),方便你处理复杂的路由结构。 
route 的常见用法:
- 在组件中,你可以通过 
this.$route访问当前的路由对象。 - 比如,你可以通过 
this.$route.params.id获取动态路由参数,或者通过this.$route.query.search获取查询字符串。 
3. router 和 route 的关系
router是管理者,route是被管理者 :router负责管理路由的跳转和全局配置,而route是router跳转后的结果,记录了当前路由的状态。router改变route:当你调用router.push或router.replace时,router会根据配置的路由规则,找到匹配的组件,并更新route对象。route是只读的 :route对象是只读的,你不能直接修改它。如果你想改变路由,必须通过router的方法(如push、replace)来实现。
4. 总结
router是路由的管理者,负责路由的跳转、配置和全局守卫。route是当前路由的状态对象,提供了当前路由的详细信息。- 它们的关系是:
router控制路由的跳转,跳转后生成新的route对象,route则记录了当前路由的状态。 
js 的基本数据类型和引用数据类型
在 JavaScript 中,数据类型可以分为两大类:基本数据类型(原始类型)和引用数据类型(对象类型) 。它们的核心区别在于 存储方式 和 操作方式。
1. 基本数据类型(Primitive Types)
基本数据类型是 JavaScript 中最基础的数据类型,它们的值直接存储在变量中,占用固定的内存空间。基本数据类型是不可变的(immutable),也就是说,一旦创建,它们的值就不能被修改。
JavaScript 中的基本数据类型有以下 7 种: number、string、boolean、null、undefined、symbol、bigint。
2. 引用数据类型(Reference Types)
引用数据类型是复杂的数据类型,它们的值存储在堆内存中,变量中存储的是指向堆内存中对象的引用(地址)。引用数据类型是可变的(mutable),也就是说,它们的值可以被修改。
JavaScript 中的引用数据类型主要包括: object、array、function 等。
3. 基本数据类型 vs 引用数据类型
| 特性 | 基本数据类型 | 引用数据类型 | 
|---|---|---|
| 存储方式 | 值直接存储在栈内存中 | 值存储在堆内存中,变量存储的是引用(地址) | 
| 可变性 | 不可变(immutable) | 可变(mutable) | 
| 比较方式 | 比较的是值 | 比较的是引用(地址) | 
| 复制行为 | 复制的是值 | 复制的是引用 | 
| 内存占用 | 占用固定大小的内存 | 占用不固定的内存,动态分配 | 
| 示例 | let a = 10; | 
let obj = { name: "Alice" }; | 
4. 注意事项
- 
浅拷贝和深拷贝 :
对于引用数据类型,直接赋值只是复制了引用,如果需要复制值,需要使用浅拷贝或深拷贝。
- 浅拷贝:
Object.assign()或扩展运算符...。 - 深拷贝:
JSON.parse(JSON.stringify(obj))或使用工具库(如 Lodash)。 
 - 浅拷贝:
 - 
类型检测 :
使用
typeof可以检测基本数据类型,但对于引用数据类型(如null、array),typeof的结果可能不准确。可以使用instanceof或Object.prototype.toString.call()进行更准确的检测。 
5. 总结
- 基本数据类型 :
number、string、boolean、null、undefined、symbol、bigint。 - 引用数据类型 :
object、array、function等。 - 核心区别:基本数据类型存储的是值,引用数据类型存储的是引用。
 
ts 的基本数据类型
TypeScript 是 JavaScript 的超集,它在 JavaScript 的基础上增加了静态类型系统。TypeScript 的基本数据类型几乎包含了 JavaScript 的所有基本数据类型,并在此基础上增加了一些额外的类型。以下是 TypeScript 中的基本数据类型:
- JavaScript 的原始类型:
number、string、boolean、null、undefined、symbol、bigint。 - TypeScript 特有的类型:
void:表示没有任何返回值的类型,通常用于函数返回值。any:表示任意类型,关闭类型检查。unknown:表示未知类型,比any更安全,需要进行类型检查后才能使用。never:表示永远不会发生的类型,通常用于抛出异常或无限循环的函数。object:表示非原始类型的对象类型。array:表示数组类型,可以用两种方式定义:使用类型[]语法;使用泛型Array<类型>语法。tuple:表示元组类型,用于表示固定长度和类型的数组。enum:表示枚举类型,用于定义一组命名的常量。
 - 其他高级类型:
- 联合类型('|'):表示一个值可以是多种类型之一。
 - 交叉类型('&'):表示一个值必须同时满足多种类型。
 - 字面量类型、类型别名、函数类型
 
 
TypeScript 类型 vs JavaScript 类型
- TypeScript 的类型是静态的,在编译时进行类型检查。
 - JavaScript 的类型是动态的,在运行时确定。
 - TypeScript 的类型系统增强了代码的可读性和可维护性,同时减少了运行时错误。
 
ts 的泛型和接口
1. 泛型(Generics)
泛型是一种创建可重用组件的方式,它允许我们在定义函数、类或接口时使用类型参数,而不是直接指定具体类型。泛型的核心思想是 参数化类型。
2. 接口(Interfaces)
接口是 TypeScript 中用于定义对象结构的工具。它描述了对象的属性、方法以及它们的类型。接口的核心思想是 定义契约,确保对象符合特定的结构。
tcp 与 udp 的区别
| 特性 | TCP | UDP | 
|---|---|---|
| 全称 | Transmission Control Protocol | User Datagram Protocol | 
| 连接方式 | 面向连接(通过三次握手建立连接) | 无连接 | 
| 可靠性 | 可靠传输(确认、重传、流量控制) | 不可靠传输 | 
| 数据传输方式 | 面向字节流 | 面向报文 | 
| 性能 | 开销大,传输效率较低 | 开销小,传输效率较高 | 
| 头部大小 | 较大(通常 20 字节) | 较小(固定 8 字节) | 
| 顺序保证 | 数据按序到达 | 数据可能乱序到达 | 
| 流量控制 | 支持(滑动窗口机制) | 不支持 | 
| 拥塞控制 | 支持(慢启动、拥塞避免等) | 不支持 | 
| 适用场景 | 文件传输、网页浏览、电子邮件 | 视频流、在线游戏、语音通话 | 
总结
- TCP:适合对可靠性要求高的场景,如文件传输、网页浏览等。
 - UDP:适合对实时性要求高的场景,如视频流、在线游戏等。
 
udp 如何实现稳定传输
UDP(User Datagram Protocol)本身是一个无连接、不可靠的传输协议,它不提供数据包的确认、重传、排序和拥塞控制等机制。然而,在某些应用场景中,我们可能需要在 UDP 的基础上实现一定程度的稳定传输。以下是几种常见的实现方式:
- 
应用层实现确认和重传机制 在应用层模拟 TCP 的确认(ACK)和重传机制,确保数据包的可靠传输。
 - 
实现数据包排序 UDP 不保证数据包的顺序,因此需要在应用层实现数据包的排序。
 - 
实现流量控制 UDP 本身没有流量控制机制,但可以通过应用层实现简单的流量控制。
 - 
实现拥塞控制 UDP 本身没有拥塞控制机制,但可以通过应用层实现简单的拥塞控制。
 - 
使用可靠传输协议(如 RUDP、QUIC) 如果应用场景对可靠性要求较高,可以直接使用基于 UDP 的可靠传输协议,如 RUDP(Reliable UDP)或 QUIC(Quick UDP Internet Connections)。
 - 
结合前向纠错(FEC) 前向纠错(Forward Error Correction,FEC)是一种通过添加冗余数据来纠正传输错误的技术。
 
介绍 vuex和pinia 的核心结构
1. Vuex 的核心结构
Vuex 是 Vue.js 官方推荐的状态管理库,采用集中式存储管理应用的所有组件的状态。它的核心结构包括以下几个部分:
- 
State
- 作用 :存储应用的状态数据,类似于组件的 
data。 - 特点:状态是响应式的,状态变化会自动更新视图。
 
 - 作用 :存储应用的状态数据,类似于组件的 
 - 
Getters
- 作用 :从 
state中派生出一些状态,类似于组件的computed。 - 特点 :可以对 
state进行计算或过滤,避免重复代码。 
 - 作用 :从 
 - 
Mutations
- 作用 :用于同步修改 
state的唯一方式。 - 特点 :必须是同步函数,通过 
commit方法调用。 
 - 作用 :用于同步修改 
 - 
Actions
- 作用 :用于处理异步操作,提交 
mutation来修改state。 - 特点 :可以包含任意异步操作,通过 
dispatch方法调用。 
 - 作用 :用于处理异步操作,提交 
 - 
Modules
- 作用 :将 
store分割成模块,每个模块拥有自己的state、getters、mutations和actions。 - 特点 :适合大型应用,避免 
store过于臃肿。 
 - 作用 :将 
 
2. Pinia 的核心结构
Pinia 是 Vue.js 的下一代状态管理库,相比于 Vuex,它更轻量、更简单,同时保留了 Vuex 的核心功能。Pinia 的核心结构包括以下几个部分:
- 
(1)State
- 作用 :存储应用的状态数据,类似于 Vuex 的 
state。 - 特点:状态是响应式的,可以直接修改。
 
 - 作用 :存储应用的状态数据,类似于 Vuex 的 
 - 
(2)Getters
- 作用 :从 
state中派生出一些状态,类似于 Vuex 的getters。 - 特点:支持缓存,计算结果会被缓存直到依赖的状态发生变化。
 
 - 作用 :从 
 - 
(3)Actions
- 作用 :用于修改 
state,可以包含同步或异步操作。 - 特点 :没有 
mutations,直接通过actions修改state。 
 - 作用 :用于修改 
 
3. Vuex 和 Pinia 的对比
| 特性 | Vuex | Pinia | 
|---|---|---|
| 核心结构 | State、Getters、Mutations、Actions | State、Getters、Actions | 
| 异步操作 | 通过 Actions 处理 | 直接通过 Actions 处理 | 
| 模块化 | 通过 Modules 实现 | 每个 Store 独立,天然模块化 | 
| TypeScript 支持 | 需要额外配置 | 原生支持 TypeScript | 
| API 设计 | 较复杂,学习成本较高 | 更简单直观,学习成本低 | 
| 体积 | 较大 | 更轻量 | 
| 适用场景 | 大型复杂应用 | 中小型应用或需要轻量状态管理的场景 | 
如果vuex 刷新后数据消失了怎么办
- 
手动持久化状态 : 通过手动将状态保存到
localStorage或sessionStorage,并在页面加载时恢复状态。 - 
使用插件自动持久化状态 : 可以使用第三方插件(如
vuex-persistedstate)来自动实现状态的持久化。vuex-persist是另一个流行的 Vuex 持久化插件,支持更灵活的配置。 - 
结合 Cookie 持久化状态 : 如果需要将状态持久化到 Cookie 中,可以使用
js-cookie库。 
node.js 处理多个异步
1. 回调函数(Callback)
回调函数是 Node.js 中最基础的异步处理方式,但容易导致"回调地狱"(Callback Hell)。
缺点:
- 嵌套层级深,代码难以维护。
 - 错误处理复杂。
 
2. Promise
Promise 是 ES6 引入的异步编程解决方案,可以避免回调地狱。
优点:
- 链式调用,代码更清晰。
 - 支持统一的错误处理。
 
3. Async/Await
async/await 是 ES7 引入的语法糖,基于 Promise,使异步代码看起来像同步代码。
优点:
- 代码更简洁,易读性高。
 - 错误处理更直观。
 
4. 并行处理多个异步操作
如果需要并行处理多个异步操作,可以使用以下方法:
(1)Promise.all
Promise.all 可以并行执行多个 Promise,并在所有 Promise 完成后返回结果。
特点:
- 如果其中一个 Promise 失败,整个 
Promise.all会立即失败。 
(2)Promise.allSettled
Promise.allSettled 会等待所有 Promise 完成,无论成功或失败。
特点:
- 不会因为某个 Promise 失败而中断。
 
(3)Promise.race
Promise.race 返回最先完成的 Promise 的结果(无论成功或失败)。
特点:
- 适合超时控制或竞速场景。
 
5. 事件驱动(EventEmitter)
Node.js 的 EventEmitter 可以用于处理异步事件。
6. 第三方库
可以使用第三方库(如 async)来简化异步操作。
请求拦截器 响应拦截器 干了什么
在前端开发中,请求拦截器 和响应拦截器 是用于在发送请求和接收响应时进行统一处理的机制。它们通常用于封装 HTTP 请求库(如 axios 或 fetch),以便在请求发出前或响应返回后执行一些通用的逻辑。
1. 请求拦截器(Request Interceptor)
请求拦截器用于在请求发出之前对请求进行统一处理。常见的用途包括:
- 添加请求头(如 
Authorization令牌)。 - 修改请求数据(如格式化参数)。
 - 显示加载状态(如显示 Loading 动画)。
 - 取消请求(如根据条件中断请求)。
 
常见场景:
- 
添加认证信息:
javascriptconfig.headers['Authorization'] = 'Bearer token'; - 
格式化请求数据:
javascriptif (config.data) { config.data = JSON.stringify(config.data); } - 
取消请求:
javascriptif (shouldCancelRequest(config)) { return Promise.reject({ message: '请求被取消' }); } 
2. 响应拦截器(Response Interceptor)
响应拦截器用于在接收到响应之后对响应进行统一处理。常见的用途包括:
- 统一处理错误(如 HTTP 状态码非 200 的情况)。
 - 格式化响应数据(如提取 
data字段)。 - 隐藏加载状态(如隐藏 Loading 动画)。
 - 缓存响应数据。
 
常见场景:
- 
统一处理错误:
javascriptif (error.response.status === 401) { redirectToLogin(); } - 
格式化响应数据:
javascriptreturn response.data; - 
缓存响应数据:
javascriptif (shouldCache(response)) { cache.set(response.config.url, response.data); } 
3. 请求拦截器和响应拦截器的工作流程
以下是请求拦截器和响应拦截器的工作流程:
- 
请求发出前:
- 请求拦截器对请求配置进行处理。
 - 如果请求拦截器返回 
config,请求会继续发出。 - 如果请求拦截器返回 
Promise.reject,请求会被中断。 
 - 
请求发出后:
- 服务器返回响应。
 - 响应拦截器对响应数据进行处理。
 - 如果响应拦截器返回 
response,响应数据会传递给业务代码。 - 如果响应拦截器返回 
Promise.reject,错误会传递给业务代码。 
 
4. 总结
- 请求拦截器:用于在请求发出前对请求进行统一处理,如添加请求头、显示 Loading 状态等。
 - 响应拦截器:用于在接收到响应后对响应进行统一处理,如格式化数据、隐藏 Loading 状态、统一处理错误等。
 
tailwindcss 是什么?
Tailwind CSS 是一个功能优先的 CSS 框架,提供了大量低级别的实用类,允许开发者直接在 HTML 中通过组合这些类来构建用户界面。与传统的 CSS 框架不同,Tailwind 不提供预定义的组件,而是通过实用类实现高度定制化的设计,同时支持响应式布局、状态变体和 JIT 模式,大幅提升开发效率和性能。
Tailwind CSS 的核心优势在于其灵活性和一致性。开发者可以通过配置文件自定义设计系统,确保项目样式统一,同时避免编写重复的 CSS 代码。尽管学习曲线较陡,且可能导致 HTML 代码臃肿,但 Tailwind CSS 特别适合快速原型开发、定制化设计以及中小型项目。
数组常用的方法?
1. 修改数组的方法
这些方法会直接修改原数组。
- 
(1)
push():在数组末尾添加一个或多个元素。 - 
(2)
pop():删除数组的最后一个元素。 - 
(3)
unshift():在数组开头添加一个或多个元素。 - 
(4)
shift():删除数组的第一个元素。 - 
(5)
splice():在指定位置添加或删除元素。javascriptconst arr = [1, 2, 3]; arr.splice(1, 1, 4); // 从索引 1 开始删除 1 个元素并插入 4,arr 变为 [1, 4, 3] - 
(6)
reverse():反转数组的顺序。 - 
(7)
sort():对数组元素进行排序。javascriptconst arr = [3, 1, 2]; arr.sort(); // arr 变为 [1, 2, 3] 
2. 不修改原数组的方法
这些方法不会修改原数组,而是返回一个新数组或值。
- 
(1)
concat():合并两个或多个数组。 - 
(2)
slice():提取数组的一部分。javascriptconst arr = [1, 2, 3, 4]; const newArr = arr.slice(1, 3); // newArr 为 [2, 3] - 
(3)
join():将数组元素连接成一个字符串。 - 
(4)
indexOf():查找指定元素的第一个索引。javascriptconst arr = [1, 2, 3]; const index = arr.indexOf(2); // index 为 1 - 
(5)
lastIndexOf():查找指定元素的最后一个索引。javascriptconst arr = [1, 2, 3, 2]; const index = arr.lastIndexOf(2); // index 为 3 - 
(6)
includes():判断数组是否包含某个元素。 
3. 遍历数组的方法
这些方法用于遍历数组元素。
- 
(1)
forEach():对数组的每个元素执行一次函数。javascriptconst arr = [1, 2, 3]; arr.forEach(item => console.log(item)); // 依次输出 1, 2, 3 - 
(2)
map():对数组的每个元素执行一次函数,并返回新数组。javascriptconst arr = [1, 2, 3]; const newArr = arr.map(item => item * 2); // newArr 为 [2, 4, 6] - 
(3)
filter():过滤数组,返回满足条件的元素组成的新数组。javascriptconst arr = [1, 2, 3]; const newArr = arr.filter(item => item > 1); // newArr 为 [2, 3] - 
(4)
reduce():对数组元素执行累加器函数,返回一个累加结果。javascriptconst arr = [1, 2, 3]; const sum = arr.reduce((acc, item) => acc + item, 0); // sum 为 6 - 
(5)
some():判断数组中是否有元素满足条件。javascriptconst arr = [1, 2, 3]; const hasEven = arr.some(item => item % 2 === 0); // hasEven 为 true - 
(6)
every():判断数组中的所有元素是否都满足条件。javascriptconst arr = [1, 2, 3]; const allEven = arr.every(item => item % 2 === 0); // allEven 为 false 
4. 其他常用方法
- 
(1)
find():查找数组中第一个满足条件的元素。javascriptconst arr = [1, 2, 3]; const result = arr.find(item => item > 1); // result 为 2 - 
(2)
findIndex():查找数组中第一个满足条件的元素的索引。 - 
(3)
flat():将嵌套数组扁平化。javascriptconst arr = [1, [2, [3]]]; const newArr = arr.flat(2); // newArr 为 [1, 2, 3] - 
(4)
flatMap():先对数组元素执行map(),然后对结果执行flat(1)。javascriptconst arr = [1, 2, 3]; const newArr = arr.flatMap(item => [item, item * 2]); // newArr 为 [1, 2, 2, 4, 3, 6] 
字符串上有什么方法?
1. 查找和截取字符串
- 
(1)
charAt():返回指定索引位置的字符。javascriptconst str = "Hello"; console.log(str.charAt(1)); // 'e' - 
(2)
charCodeAt():返回指定索引位置字符的 Unicode 编码。 - 
(3)
indexOf():返回指定字符串第一次出现的索引。javascriptconst str = "Hello"; console.log(str.indexOf('l')); // 2 - 
(4)
lastIndexOf():返回指定字符串最后一次出现的索引。 - 
(5)
includes():判断字符串是否包含指定子字符串。 - 
(6)
startsWith():判断字符串是否以指定子字符串开头。 - 
(7)
endsWith():判断字符串是否以指定子字符串结尾。 - 
(8)
slice():提取字符串的一部分。javascriptconst str = "Hello"; console.log(str.slice(1, 3)); // 'el' - 
(9)
substring():提取字符串的一部分(与slice()类似,但不支持负数索引)。javascriptconst str = "Hello"; console.log(str.substring(1, 3)); // 'el' 
2. 修改字符串
- 
(1)
toUpperCase():将字符串转换为大写。javascriptconst str = "Hello"; console.log(str.toUpperCase()); // 'HELLO' - 
(2)
toLowerCase():将字符串转换为小写。 - 
(3)
trim():去除字符串两端的空白字符。javascriptconst str = " Hello "; console.log(str.trim()); // 'Hello' - 
(4)
trimStart()/trimLeft():去除字符串开头的空白字符。 - 
(5)
trimEnd()/trimRight():去除字符串结尾的空白字符。 - 
(6)
replace():替换字符串中的指定子字符串。javascriptconst str = "Hello"; console.log(str.replace('He', 'Ha')); // 'Hallo' - 
(7)
replaceAll():替换字符串中所有匹配的子字符串。 
3. 分割和连接字符串
- 
(1)
split():将字符串按指定分隔符分割成数组。javascriptconst str = "Hello,World"; console.log(str.split(',')); // ['Hello', 'World'] - 
(2)
concat():连接多个字符串。 
4. 其他常用方法
- 
(1)
repeat():将字符串重复指定次数。javascriptconst str = "Hello"; console.log(str.repeat(2)); // 'HelloHello' - 
(2)
padStart():在字符串开头填充指定字符,直到字符串达到指定长度。javascriptconst str = "Hello"; console.log(str.padStart(10, '*')); // '*****Hello' - 
(3)
padEnd():在字符串结尾填充指定字符,直到字符串达到指定长度。 - 
(4)
match():返回字符串中匹配正则表达式的结果。javascriptconst str = "Hello"; console.log(str.match(/l/g)); // ['l', 'l'] - 
(5)
search():返回字符串中匹配正则表达式的第一个索引。javascriptconst str = "Hello"; console.log(str.search(/l/)); // 2 ```** 
结语
通过这次分享,希望能让你对春招面试有了更清晰的认识和准备。