2026前端面试真题易错(实战版)


一、手写代码(别背,得能跑)

1. 实现一个防抖/节流(必考)

javascript 复制代码
// 防抖:用户停止操作后再执行

function debounce(fn, delay) {

  let timer = null;

  return function(...args) {

    if (timer) clearTimeout(timer);

    timer = setTimeout(() => fn.apply(this, args), delay);

  };

}



// 节流:固定时间执行一次(滚动、拖拽)

function throttle(fn, delay) {

  let last = 0;

  return function(...args) {

    const now = Date.now();

    if (now - last >= delay) {

      last = now;

      fn.apply(this, args);

    }

  };

}

面试官常问:如果用户一直点,最后一次必须执行吗?防抖的立即执行版本怎么改?节流最后一次漏掉怎么办?(用时间戳+定时器双保险)


2. 模拟实现 Promise.all

javascript 复制代码
function myPromiseAll(promises) {

  return new Promise((resolve, reject) => {

    if (!Array.isArray(promises)) {

      return reject(new TypeError('Argument is not iterable'));

    }

    let results = [];

    let completed = 0;

    if (promises.length === 0) return resolve(results);

    promises.forEach((p, idx) => {

      Promise.resolve(p).then(val => {

        results[idx] = val;

        completed++;

        if (completed === promises.length) resolve(results);

      }).catch(err => reject(err));

    });

  });

}

实战坑:遇到非 Promise 值直接包裹;空数组立即返回;捕获错误时 reject。


  1. 深拷贝(考虑循环引用、特殊类型)
javascript 复制代码
function deepClone(obj, hash = new WeakMap()) {

  if (obj === null || typeof obj !== 'object') return obj;

  if (hash.has(obj)) return hash.get(obj);

  let clone = Array.isArray(obj) ? [] : {};

  hash.set(obj, clone);

  for (let key in obj) {

    if (obj.hasOwnProperty(key)) {

      clone[key] = deepClone(obj[key], hash);

    }

  }

  return clone;

}

面试官追问:Date/RegExp/函数怎么处理?怎么支持 Symbol 键?------增加类型判断分支。


二、实战场景题(都是血泪史)

  1. 一个后台管理页面,列表数据多,每次点查询都卡死,怎么办?

真实原因:你后端返回了全量数据,前端直接渲染,页面 DOM 节点上万。

实战方案:

· 先找后端加 page size 参数,换分页(最简单)

· 如果必须前端分页,用虚拟列表(只渲染可视区)

· 如果只是数据量大、渲染慢,用 requestAnimationFrame 分帧渲染,避免主线程长时间阻塞


  1. 用户反馈:手机 H5 页面点了没反应,咋排查?

真实场景:移动端 300ms 延迟?或者页面有透明层挡住了?

排查步骤:

  1. 手机连接电脑,打开 Chrome DevTools → Remote Devices 查看元素是否被覆盖

  2. 检查 touch 和 click 是否混用,是否忘记 preventDefault

  3. 检查 CSS pointer-events: none 有没有误设

  4. 如果用了 FastClick 库,确认版本兼容


  1. 上线后,发现某个 JS 文件报错,但本地无法复现,怎么快速定位?

实战流程:

  1. 查看错误监控平台(Sentry/自己写的)报错堆栈,定位到文件行号

  2. 去线上 CDN 下载对应版本的 sourcemap(上线时一定要上传),通过 sourcemap 映射回源码

  3. 如果没 sourcemap,用 console 埋点 + 用户设备信息(浏览器、系统、网络环境)猜测复现场景

  4. 实在不行,加 debug 日志,灰度发布给一小部分用户,看日志输出


  1. 某个 React 组件频繁重渲染,怎么定位?

真实案例:父组件状态更新,所有子组件都跟着重绘,页面卡。

定位:

· 安装 React DevTools → 勾选 Highlight updates,看哪些组件变黄

· 检查子组件是否用 React.memo 包裹

· 父组件传 props 时,是否每次都新创建对象/函数,用 useCallback 缓存

· 如果用了 Redux,确认 selector 是否每次返回新对象(用 reselect 做缓存)


三、性能优化(不只是压缩图片)

  1. 首屏时间从 3s 优化到 1s 的实操

真实优化项(按优先级):

· 代码分割:路由懒加载,React.lazy + Suspense

· 预加载: 关键资源提前加载

· 图片:WebP + 响应式图片 + 懒加载

· 字体:用 font-display: swap 避免白屏

· 服务端渲染:如果是内容型网站,上 SSR 或静态生成(Next.js)

· CDN 预热:将核心资源提前推到边缘节点


  1. 首屏出现大面积白屏,怎么抢救?

真实场景:移动端弱网下,JS 没加载完,页面啥也没有。

方案:

· 内联关键 CSS(首屏样式)

· 加骨架屏(Skeleton),用户看到占位,心理上觉得快了

· 把首屏需要的数据请求提前,放在 head 里 数据接口

· 用 async/defer 控制 JS 加载顺序,不让它阻塞渲染


四、工程化与构建(Webpack/Rspack)

  1. 线上代码压缩后,报错如何还原?

必备技能:

· 确保构建时生成 .map 文件,但不要部署到线上(防止源码泄露)

· 上传到错误监控平台(Sentry/自建),平台会自动用 sourcemap 解析

· 手动还原:用 source-map 包或 Chrome 的 "Add Source Map" 功能


  1. Webpack 构建慢,从哪里下手?

实战排查:

· 用 speed-measure-webpack-plugin 看哪个 loader/plugin 耗时

· 排除不必要文件的解析(exclude: /node_modules/)

· 用 thread-loader 多进程

· 缓存:cache: { type: 'filesystem' }

· 换 Rspack,兼容 Webpack 大部分配置,速度能快 5-10 倍


五、算法(面试必考)

  1. 翻转二叉树(考察递归/迭代)
javascript 复制代码
function invertTree(root) {

  if (!root) return null;

  [root.left, root.right] = [invertTree(root.right), invertTree(root.left)];

  return root;

}

  1. 实现一个 URL 解析函数
javascript 复制代码
function parseQuery(url) {

  const search = url.split('?')[1];

  if (!search) return {};

  const params = new URLSearchParams(search);

  const result = {};

  for (let [key, val] of params.entries()) {

    if (result[key]) {

      result[key] = Array.isArray(result[key]) ? [...result[key], val] : [result[key], val];

    } else {

      result[key] = val;

    }

  }

  return result;

}

注意:处理重复参数(?a=1&a=2)和中文编码(decodeURIComponent)


六、综合大厂真题(场景)

  1. 设计一个多端适配的登录弹窗组件

考察点:组件封装、样式适配、状态管理

思路:

· 用 Portal 渲染到 body

· 支持函数式调用:Modal.confirm({ title, content, onOk })

· 移动端和 PC 端样式不同(通过媒体查询或 React 检测 UA 切换)

· 关闭时销毁 DOM,避免内存泄露


  1. 扫码登录的原理与前端实现

回答框架:

· 生成唯一二维码(包含 ticket/token)

· 前端轮询后端接口,询问该 ticket 是否已扫码确认

· 移动端扫码后,调用后端确认接口,后端标记 ticket 已使用

· 前端轮询到确认,获取登录态 token,跳转

· 优化:用 WebSocket 代替轮询,但长连接开销大,看场景


七、最后的面试技巧(真实经验)

· 手写题:先写注释说明思路,再写代码,如果卡壳,讲清楚你卡在哪一步,比硬写要好。

· 项目细节:面试官必问"这个项目最难的点是什么?"------不要说"技术难点",要说"业务与技术的结合点",比如"数据量大导致前端卡,我用了虚拟列表 + 分帧渲染,解决了体验问题"。

· 反问环节:不要问"加班多吗""贵司做什么业务",可以问"这个岗位目前最大的挑战是什么""团队在微前端方面有什么实践"


  1. 项目结构设计与模块化

题目:请分析本项目(辰驭汽车官网)的文件组织方式。你认为这样的结构有哪些优点?如果项目规模扩大,你会如何改进?

参考答案

· 优点:将 index.html 放在根目录,css/、js/ 分别存放样式与脚本,models/

下按车型独立存储详情页,结构清晰,便于维护和定位。 · 改进点: · 当车型增多时,models/ 下文件会急剧膨胀,可引入构建工具(如

Vite)将详情页模板化,通过路由动态加载配置数据,避免重复 HTML。 · 将车型配置数据抽离为单独的 JSON 文件或

API,前端统一渲染,降低维护成本。 · 添加 components/ 目录存放可复用的头部、底部、卡片等组件,减少重复代码。


  1. 粒子背景的实现与性能考量

题目:首页使用了粒子背景(代码中提及 #jsi-particle-container),请说明粒子动画的一般实现原理。如果粒子数量过多(例如超过 500 个),如何保证页面流畅?

参考答案

· 实现原理:通常使用 Canvas 或 WebGL,通过 requestAnimationFrame 循环更新粒子位置并绘制。粒子位置变化、边界碰撞检测、鼠标交互等都是常见需求。

· 性能优化:

· 使用 requestAnimationFrame 代替 setInterval,与屏幕刷新率同步。

· 减少粒子数量,或根据设备性能动态调整数量(如检测帧率)。

· 离屏 Canvas 缓存静态背景。

· 使用 will-change 提示浏览器优化。

· 若使用第三方库(如 three.js),注意避免每帧创建新对象。

· 本项目中可进一步将粒子脚本独立为单独文件,避免阻塞首屏渲染。


  1. 车型列表的动态渲染

题目:主页的车型卡片是通过 JavaScript 动态生成的,请说明这种做法的好处和潜在问题。如果你来重构,会采用什么方式保证数据和视图的同步?

参考答案

· 好处:

· 便于维护车型数据,新增车型只需修改数据数组,无需改动 HTML。

· 可轻松实现按类别(轿车/SUV/MPV)分组渲染。

· 潜在问题:

· SEO 不友好(爬虫可能无法执行 JS 获取内容)。

· 首次加载时可能出现短暂白屏或内容闪烁。

· 若数据量极大,一次性渲染大量 DOM 可能卡顿。

· 改进建议:

· 对于 SEO 关键页面,采用服务端渲染或预渲染(如 SSG)。

· 可使用前端框架(Vue/React)配合虚拟 DOM 优化渲染性能,并支持数据响应式更新。

· 将车型数据从内嵌改为异步请求(fetch),利于后续与后台对接。


  1. 详情页配置切换(Tabs)的实现

题目:车型详情页(如 sagitta.html)中通过 JavaScript 动态生成配置选项卡并切换内容。请解释实现思路,并说明如何确保不同配置的数据准确对应。

参考答案

· 实现思路:

· 定义 configs 数组,每个元素代表一个配置版本(含名称、动力、价格、选装项等)。

· 页面加载时,遍历 configs 生成选项卡按钮,并为每个按钮绑定点击事件。

· 点击某个按钮时,高亮当前按钮,并调用 renderDetail 函数,根据该配置数据刷新右侧详情区域。

· 数据对应准确性:

· 通过数组索引或唯一 ID 绑定,确保渲染时使用的是正确的配置对象。

· 在 renderDetail 中直接传入对应的配置对象,避免通过 DOM 属性传递数据(减少字符串解析错误)。

· 扩展性:若配置数据来自后端,可设计统一的 API 返回结构,前端只需根据 configId 请求详情并渲染。


  1. 响应式布局与适配

题目:项目使用了媒体查询实现移动端适配(如 @media (max-width: 800px))。请简述响应式设计的核心原则,并指出该项目在移动端可能存在的改进点。

参考答案

· 核心原则:

· 使用相对单位(rem/em/vw/vh)而非固定像素。

· 设置视口 meta 标签 。

· 通过媒体查询针对不同断点调整布局(如列数、字体大小、边距)。

· 项目改进点:

· 当前媒体查询只调整了容器内边距和卡片列数,可进一步优化:

复制代码
· 导航栏改为汉堡菜单,折叠项。

· 详情页的选项卡改为横向滚动,避免换行。

· 价格和配置信息用更紧凑的布局展示。

· 触摸目标(按钮)大小应不小于 44×44 像素,提升易用性。

  1. 代码复用与组件化

题目:详情页模板中,每个车型都需要单独编写一份 HTML,并嵌入对应的配置数据。如何优化这种重复劳动?如果让你用现代前端框架(如 React)重写,你会如何设计组件?

参考答案

· 优化思路:

· 将详情页结构抽象为模板,通过构建工具(如 webpack、Vite)在编译时注入不同车型数据,生成静态文件。

· 或将配置数据存储为 JSON,前端动态请求并渲染,这样只需一个 detail.html 页面,通过 URL 参数 ?car=sagitta 加载对应数据。

· React 组件设计:

· 创建 CarDetail 组件,接收 carId 作为 prop,内部使用 useEffect 获取配置数据,渲染选项卡和详情。

· 将配置选项卡拆分为独立子组件 ConfigTabs,详情区域为 ConfigDetail,实现关注点分离。

· 数据层可使用 Context 或状态管理库(如 Zustand)缓存车型数据,避免重复请求。


  1. 交互与用户体验优化

题目:卡片悬停时有轻微上浮和边框颜色变化的效果。请说明这类交互动效的意义,并列举其他可提升用户体验的交互细节。

参考答案

· 意义:

· 提供即时视觉反馈,让用户感知元素是可交互的,提升操作确定感。

· 轻微动效增加高级感,符合汽车品牌调性。

· 其他优化细节:

· 为按钮添加 :active 状态,模拟按压效果。

· 图片懒加载(详情页车型图片),减少首屏加载。

· 骨架屏(Skeleton)替代加载时的白屏。

· 页面切换时添加过渡动画,避免生硬跳转。

· 键盘可访问性(Tab 键导航焦点样式)。


  1. 性能优化建议

题目:假设网站上线后,发现首屏加载速度较慢,请基于当前代码给出至少三条优化建议。

参考答案

  1. 图片优化:项目中未包含车型图片,但实际应使用 WebP 格式、响应式图片(srcset),并懒加载非首屏图片。

  2. CSS/JS 优化:

    · 将关键 CSS 内联到 ,非关键样式异步加载。

    · 使用 defer 或 async 加载非核心 JavaScript。

    · 压缩和合并静态资源。

  3. 减少渲染阻塞:

    · 粒子背景脚本(Canvas 绘制)可延迟初始化,或仅在用户交互后才启动。

    · 避免使用昂贵的 CSS 属性(如 box-shadow 大量使用)导致重绘。

  4. 利用缓存:设置合理的 HTTP 缓存头,对字体、框架库等静态资源长期缓存。

  5. 预加载关键资源:使用 预加载首屏必需的字体或图片。


  1. 数据管理与可维护性

题目:当前车型配置数据散落在各详情页的 JavaScript 中,修改价格或配置需要改动多个文件。请提出一种集中管理数据的方案。

参考答案

· 集中管理方案:

· 创建 data/cars.json 文件,定义所有车型的配置信息(包括每种配置的详细参数)。

· 在主页和详情页中统一通过 fetch 加载该 JSON,动态生成内容。

· 优点:

· 一处修改,全局生效。

· 便于接入后台 CMS 系统,实现数据与视图分离。

· 减少重复代码,降低维护出错概率。

· 实现细节:

· 主页动态加载 JSON 后渲染卡片。

· 详情页通过 URL 参数(如 ?car=sagitta)筛选对应车型数据,动态渲染配置选项卡。

· 利用浏览器缓存或 Service Worker 缓存 JSON,减少网络请求。


  1. 跨浏览器兼容性

题目:项目使用了 backdrop-filter: blur() 和 CSS Grid 等现代特性,如何确保在不支持这些特性的浏览器(如旧版 IE)上正常显示?

参考答案

· 渐进增强/优雅降级:

· 对于不支持 backdrop-filter 的浏览器,可提供纯色背景备选方案(通过 @supports 检测)。

· 使用 Autoprefixer 自动添加浏览器前缀。

· 对于 CSS Grid,可准备 Flexbox 回退布局(例如使用 @supports not (display: grid) 定义备用样式)。

· polyfill:对于 JS 新特性(如 Promise、fetch),可引入 polyfill 库(如 core-js)或使用 Babel 转换。

· 测试:通过 BrowserStack 或真实设备进行兼容性测试,确保核心功能(车型查看、配置切换)在主流浏览器上可用。


  1. 安全考虑

题目:项目中使用了内联脚本和动态生成 HTML,是否存在 XSS 风险?如何防范?

参考答案

· 风险分析:

· 车型数据由前端数组直接渲染,若数据源被篡改(或用户输入被注入恶意脚本),使用 innerHTML 或 insertAdjacentHTML 可能导致 XSS。

· 防范措施:

· 使用 textContent 或 innerText 替代 innerHTML 插入用户可控内容。

· 若必须插入 HTML,先对数据进行转义(如替换 < 为 <)。

· 利用现代框架(如 React 的 JSX)默认转义,降低风险。

· 避免在 URL 参数中直接拼接到 innerHTML,使用 encodeURIComponent 处理。

· 额外建议:

· 设置 CSP(内容安全策略)头,限制脚本来源。

· 依赖第三方库(如 jQuery)时确保版本无已知漏洞。


  1. 版本控制与协作

题目:如果你将该项目提交到 Git 仓库,你会如何编写 .gitignore 文件?请列举至少三个应忽略的条目。

参考答案

· 忽略条目:

· node_modules/(若使用 npm 包管理)

· .DS_Store(macOS 系统文件)

· dist/ 或 build/(构建输出目录)

· .env(环境变量文件)

· *.log(日志文件)

· 补充:

· 忽略 IDE 配置文件(如 .vscode/)可根据团队约定决定是否提交。

· 若项目依赖本地配置,应提供示例文件(如 .env.example)供协作者复制。


13. 自动化构建与部署

题目:如果需要将该项目部署到生产环境,你会选择怎样的构建工具和部署流程?请简述关键步骤。

参考答案

· 构建工具:

· 使用 Vite 或 Parcel 快速构建,支持开发热更新和生产打包。

· 配置 CSS 压缩(如 cssnano)、JS 压缩(terser)、图片优化(imagemin)。

· 部署流程:

  1. 运行构建命令(npm run build),生成 dist 目录。

  2. 将 dist 目录上传至 CDN 或静态托管服务(如 Vercel、Netlify、阿里云 OSS)。

  3. 配置域名 DNS 解析。

  4. 设置 HTTP/2、Gzip 压缩、缓存策略。

  5. 利用 CI/CD(如 GitHub Actions)实现自动部署:代码推送后自动测试、构建、部署至生产环境。


  1. 页面 SEO 优化

题目:作为一个汽车品牌官网,SEO 至关重要。请基于当前项目结构,提出至少三条 SEO 改进措施。

参考答案

  1. 语义化 HTML:使用 header main>

    等标签,而非全用

  2. Meta 标签:

    · 添加 description 和 keywords meta 标签,描述品牌和车型。

    · 设置 og:title、og:image 等开放图谱标签,提升社交分享效果。

  3. 结构化数据:使用 JSON-LD 标注车型信息(价格、品牌、型号等),帮助搜索引擎生成富摘要。

  4. 可访问性:为图片添加 alt 属性,使用 aria-label 改善屏幕阅读器体验,间接提升 SEO 评价。

  5. URL 优化:车型详情页 URL 应包含车型名称(如 /models/sagitta)而非无意义 ID,且保持静态化。

  6. 移动端适配:响应式设计已被搜索引擎列为排名因素,需确保移动端体验良好。


  1. 异常处理与用户提示

题目:假设在加载车型数据时网络请求失败,应如何优雅地告知用户并提供重试机会?请写出核心代码思路。

参考答案

· 方案:

· 使用 fetch 请求数据,并用 try...catch 捕获网络错误。

· 在容器中展示错误提示和重试按钮。

· 重试时重新请求数据。

· 示例代码:

javascript 复制代码
async function loadCars() {

    try {

      const res = await fetch('/data/cars.json');

      if (!res.ok) throw new Error('HTTP error');

      const data = await res.json();

      renderCards(data);

    } catch (err) {

      const container = document.querySelector('.car-grid');

      container.innerHTML = `

        <div style="text-align:center; padding:40px;">

          <p>加载失败,请检查网络。</p>

          <button id="retry-btn">重新加载</button>

        </div>`;

      document.getElementById('retry-btn').onclick = loadCars;

    }

  }

``


比如这个代码

html 复制代码
  <!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>清爽简单的HTML5音乐播放器演示_郭wes代码</title>
    <link rel="stylesheet" href="css/solid.css">
    <link rel="stylesheet" href="css/fontawesome.css">
    <link rel="stylesheet" href="css/style.css">
    <link rel="icon" href="img/favicon.ico">
</head>

<body>
    <div id="dowebok">
        <div id="bg-artwork"></div>
        <div id="bg-layer"></div>
        <div id="player">
            <div id="player-track">
                <div id="album-name"></div>
                <div id="track-name"></div>
                <div id="track-time">
                    <div id="current-time"></div>
                    <div id="track-length"></div>
                </div>
                <div id="s-area">
                    <div id="ins-time"></div>
                    <div id="s-hover"></div>
                    <div id="seek-bar"></div>
                </div>
            </div>
            <div id="player-content">
                <div id="album-art">
                    <img src="images/1.jpg" class="active" id="_1">
                    <img src="images/2.jpg" id="_2">
                    <img src="images/3.jpg" id="_3">
                    <img src="images/4.jpg" id="_4">
                    <img src="images/5.jpg" id="_5">
                    <img src="images/6.jpg" id="_6">
                    <img src="images/7.jpg" id="_7">
                    <img src="images/8.jpg" id="_8">
                    <img src="images/9.jpg" id="_9">
                    <div id="buffer-box">加载中...</div>
                </div>
                <div id="player-controls">
                    <div class="control">
                        <div class="button" id="play-previous">
                            <i class="fas fa-backward"></i>
                        </div>
                    </div>
                    <div class="control">
                        <div class="button" id="play-pause-button">
                            <i class="fas fa-play"></i>
                        </div>
                    </div>
                    <div class="control">
                        <div class="button" id="play-next">
                            <i class="fas fa-forward"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="js/jquery.min.js"></script>
    <script src="js/index.js"></script>
</body>

</html>
相关推荐
会编程的土豆2 小时前
【leetcode hot 100】 二叉树2
算法·leetcode·职场和发展
斌味代码2 小时前
Vue3源码解读(一):响应式系统 reactive/ref 核心原理图解(2026最新版)
前端·javascript·vue.js
星辰_mya2 小时前
MVCC 与事务隔离:MySQL 如何实现“读不阻塞写”?
java·数据库·mysql·面试·架构
yhole2 小时前
Nginx解决前端跨域问题
运维·前端·nginx
我爱学习好爱好爱2 小时前
Ansible 常用模块详解:hostname、selinux 、file实战
前端·chrome·ansible
爱丽_2 小时前
AQS 的 `state`:volatile + CAS 如何撑起原子性与可见性
java·前端·算法
羊小猪~~2 小时前
算法/力扣--字符串经典题目
c++·考研·算法·leetcode·职场和发展·哈希算法
Zik----2 小时前
Windows安装cuda
前端·ui·xhtml
王杨游戏养站系统2 小时前
3分钟搭建1个游戏下载站网站教程!SEO站长养站系统!
开发语言·前端·游戏·游戏下载站养站系统·游戏养站系统
是上好佳佳佳呀2 小时前
【前端(三)】CSS 属性梳理:从字体文本到背景表格
前端·css