2025年前端面试题
1 HTTP 有哪些请求方法
GET 获取服务器上某一资源
POST 提交新数据
PUT 更新数据
DELETE 删除数据
OPTION 预检数据
HEAD 获取资源的元信息。不返回内容
3 HTTP 状态码的含义
200 表示成功
206 表示只加载了一部分,还在继续加载
301 永久重定向
302 临时重定向
304 使用缓存数据
401 没有权限
404 链接错误
500 服务器错误
503 服务器暂时不能处理,可能处于挂起态
4 块级元素、行内元素、行内块级元素对比
块级元素占满一行,行内元素、行内块级元素不能占满一行
块级元素、行内块级可以设置宽高,行内元素不能设置宽高
块级元素、行内块级元素可以设置上下边距,行内元素只能设置左右边距,不能设置上下边距
5 Canvas 和 SVG 的区别
Canvas 是位图
SVG 是矢量图
6 src 和 href 的区别
src 可以加载到数据
href 只指向数据,不加载数据
7 display:none 和 visibility:hidden 的区别
display 在页面里的没对象
visibility 在页面里还有对象
8 rgba 和 opacity 有什么区别
rgba 只作用于自己的颜色
opacity 作用于整个元素及其子元素
9 什么是闭包
A函数里创建函数B,函数B可以访问函数A里的变量
10 offsetWidth/offsetHeight,clientWidth/clientHeight与
scrollWidth/scrollHeight
略
11 不会冒泡的事件有哪些
focus blur scroll load
12 React 18 有哪些更新
合并更新、transition、suspense
13 React 19 有哪些更新
不再使用 useCallback useMemo memo
14 如何实现页面截图
用 html2Canvas
15 有哪些缓存
DNS 缓存、CDN 缓存、浏览器缓存、服务器缓存
16 闭包的应用场景?如何避免内存泄漏?
数据封装:A函数里有B函数,B函数可以访问A函数里的变量
1 给变量设置 null,手动解除引用
2 移除监听
17 let
、const
、var
的区别?
let const 是块级作用域
var 是函数作用域
18 Promise、async/await 的实现原理?
Promise 用状态机管理异步操作,有三种状态有 pending fullfilled rejected,通过 resolove 和 reject 改变状态,并通过 .then 链式调用。它的回调是微任务,比宏任务优先级高
async/await 是 Promise 的语法糖,让异步代码看起来像同步的。底层通过 generator + 自动执行器来实现
19 手写 Promise.All
const PromiseMyAll = (promises: any[]) => {
return new Promise((resovle, reject) => {
const results: any[] = [];
let count = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise).then(res => {
results[index] = res;
count++;
if (count === promises.length) {
resovle(results)
}
}).catch((error) => {
reject(error)
})
})
})
}
const a = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('aaaa');
}, 1000)
})
}
const b = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('bbb');
}, 2000)
})
}
const c = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('cccc');
}, 3000)
})
}
PromiseMyAll([a(), b(), c()]).then((res) => {
console.log('myAll res=', res);
})
20 手写 Promise.race
const PromiseMyRace = (promises: any[]) => {
return new Promise((resovle, reject) => {
promises.forEach((promise, index) => {
Promise.resolve(promise).then(res => {
resovle(res)
}).catch((error) => {
reject(error)
})
})
})
}
const a = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('aaaa');
}, 1000)
})
}
const b = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('bbb');
}, 2000)
})
}
const c = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('cccc');
}, 3000)
})
}
PromiseMyRace([a(), b(), c()]).then((res) => {
console.log('myAll res=', res);
})
21 箭头函数和普通函数的区别?
箭头函数是ES6的语法糖,它和普通函数的区别在于 this 绑定和写法
第一 this 的绑定
- 箭头函数的 this 就是在它定义时的外层作用域的 this,固定不变
- 普通函数的 this 由调用方式决定,且可以用call/apply改变
第二 写法
箭头函数可以省略 return 和大括号,普通函数不可以
22 Proxy 有什么用
Proxy
包装另一个对象并拦截读取/写入操作,
23 Flex 和 Grid 有什么区别
Grid 是二维的,Flex是一维的
Flexbox是以内容为切入点由内向外工作的,而网格是以布局为切入点从外向内工作的,所以在实践中,这通常意味着网格更适合用于整体的网页布局,而 Flexbox 更适合对网格区域内的特定元素布局
24 水平垂直居中的方法
1 flex
display:flex
justify-content: center
align-items: center
2 position
父元素:
position: relative
子元素
position: absolute
top: 50%
left: 50%
transform: translate( -50%, -50%)
25 transition 的语法
transition: 「property」「duration」「timing-function」「delay」
26 animation 的语法
animation: 「name」「duration」「timing-function」「delay」
27 从输入 URL 到页面渲染的完整流程?
1 DNS解析、2 建立TCP连接、3 发送HTTP请求、4 服务器返回、5 浏览器解析、6 页面布局和绘制、7 执行 JS 和加载异步资源,这步还有可能产生回流 reflow 和重绘 repaint
28 回流(Reflow)重绘(Repaint)和如何优化?
减少回流次数,用 class 代替逐个修改 style
用防抖/节流控制执行频率
29 HTTP/2 和 HTTP/1.1 的区别?
HTTP/2 通过多路复用、头部压缩和二进制协议,显著提升了传输效率
30 强缓存和协商缓存如何配合
用强缓存优先,协商缓存兜底的方式可以既减少不必要的网络请求,又能保证资源的及时更新
“用户首次访问网站时,CSS 文件通过 Cach-Control:max-age=86400
强缓存1天。第二天缓存过期后,浏览器发送请求带ETag
,若文件未变,服务器返回304
,节省带宽。”
31 对跨域有什么了解
因为浏览器有同源策略,所以当请求的协议、域名或端口不同时,浏览器会阻止
在开发环境配置 vite 代理来绕过跨域
在生产环境的应对办法是,让后端配置 CORS Access-Control-Allow-Origin
32 React Fiber 是什么?解决了什么问题?
实现了"可中断渲染"和为"并发模式"打下了基础
33 React 18 有什么更新
transition、suspense
34 虚拟 DOM 和 Diff 算法的工作原理?
"虚拟DOM是真实DOM的JS表示,Diff算法通过同层比较和Key优化,找出最小变更批量更新。核心是避免全量DOM操作,提升性能。"
35 React 中的代码分割
React.lazy + Suspense
36 为什么 Vite 比 Webpack 快?ESM 如何提升开发体验?
vite 使用 esm ,浏览器是直接可以运行的,免打包,所以很快
37 手写防抖
let flag;
const debounce = (fn: Function) => {clearTimeout(flag);flag = setTimeout(() => {fn();}, 2000)
}const fn = () => {console.log('打印')
}debounce(fn);setTimeout(() => {debounce(fn);setTimeout(() => {debounce(fn);setTimeout(() => {debounce(fn);setTimeout(() => {debounce(fn);}, 1000)}, 1000)}, 1000)
}, 1000)
38 手写节流
let on = true;
const throttle = (fn) => {if (!on) return;on = false;setTimeout(() => {fn();on = on;}, 1000)
}
39 如何做XSS ?
检查用户输入
配置 CSP 限制页面只能加载来自自身 (self
) 的脚本和样式
使用 HTTP Only Cookie,这样 JavaScript 就不能访问和修改 cookie
40 如何预防 CSRF 攻击
定义:CSRF 攻击就是利用用户已登录的身份,诱骗其执行攻击者想做的操作
方法一:CSRF Token 表单/请求携带随机Token
方法二:二次验证,比如短信
41 高并发场景下前端如何优化(如抢购页面)
- 减请求:WebSocket、预加载
- 缓数据:dns cdn 浏览器 服务端
- 削峰值:接口防抖
- 保核心:降级策略
42 WebSocket 如何保证消息不丢失?
"编号+确认+存盘"
- 每条消息加唯一ID(服务端记录已收ID,发现缺失就补发)
- 重要消息必须等客户端回复"收到"(没收到回复就重发)
- 断线时把没发完的消息存起来(重连后继续发)
43 大数据量渲染如何优化?
使用虚拟列表,减少实际渲染的DOM元素数
用防抖控制加载新数据渲染UI的频率
44 说一下项目架构
友谊医生胃癌住院部数字人大屏幕项目架构
一、项目背景与核心业务逻辑
该项目部署在友谊医院胃癌住院部的数字人大屏幕上,主要实现以下交互流程:
- 通过麦克风采集用户语音
- 使用腾讯语音识别)服务将用户的语音提问转为文本发送给大模型
- 通过HTTP分块传输返回的答案文字给前端
- 前端发送答案文字给本地后端服务生成视频
- 同步播放视频内容并以打字机效果展示文字回复
二、硬件与操作系统选型
因单个视频10秒的视频大小至少有几百M,所以生成视频的服务只能放到客户面本地,而不能是阿里云上
而本地生成视频非常耗gpu计算资源,因此选择了windows作为客户机,而不是Android
三 后端服务部署
1 大模型推理后端服务阿里云上:基于智谱AI基座模型,使用友谊医院胃病知识库,我司经过训练研发出的
2 本地后端服务:生成视频,生成 electron 设备唯一识别码
3 使用腾讯云的语音识别和语音合成
4 日志服务使用阿里云的
四 客户端技术造型
- 应用框架:Electron(跨平台桌面应用)
- UI框架:React(为了方便以后迁移到用 React Native 开发的移动端)
- UI组件库:AntDesign
- 状态管理:Redux + Saga
- 页面切换:按需加载的路由管理
- 适配各种尺寸的屏幕:使用了 rem 的布局,这样文字大于相对于electron窗口的宽度的比例是固定的
五 开发工具链
1 代码仓库:腾讯 Coding
2 分支策略:
dev:开发分支
master:测试分支
release:生产环境分支
3 CI/CD流程:
每次CI自动递增版本号,生成exe安装包,发布至阿里云存储
4 electron 客户端监测到阿里云上有 exe 新版本,自动下载安装更新
六 质量保证
- 代码规范:
- Husky钩子实现提交前检查,不符合 ESLint + Prettier 规范的代码不许提交
- 测试策略:
- 组件级测试:Vitest
- E2E测试:Playwright(覆盖核心冒烟用例)
- 日志系统
- 本地日志用 eruda ,远端用阿里云日志