前端面试场景题

发布于:2025-05-01 ⋅ 阅读:(39) ⋅ 点赞:(0)

目录

1.项目第一次加载太慢优化 / vue 首屏加载过慢如何优化

2.如何解决页面请求接口大规模并发问题

3.说说了解的es6-es10的东西有哪些

ES6(ES2015)之后,JavaScript 新增了许多实用的数组和对象方法,下面为你详细介绍:

4.常见前端安全性问题

XSS:攻击者通过注入恶意脚本,在用户浏览器中执行,窃取 Cookie、会话令牌等敏感信息

跨站请求伪造(CSRF)

跨域资源共享(CORS)与安全

前端如何处理密码安全?需要

如何避免 URL 中的敏感信息泄露?   

其他常见安全问题

总结:前端安全核心原则

5.vite和webpack在热更新上有啥区别 

6.在项目中,webpack使用过哪些常见的plugin(插件)和loader(加载器)

 Loader(加载器)

Plugin(插件)

常用loader

常用plugin

7.vite常见面试题

Vite 的 Bundleless 工作流程(Bundleless(无打包模式) 是一种 不需要预先进行代码打包,直接利用 浏览器 ESM 机制 进行模块加载的开发模式。)

8.大文件上传

9.JS执行100万个任务,如何保证浏览器不卡顿

10.事件循环机制概述


1.项目第一次加载太慢优化 / vue 首屏加载过慢如何优化

        首屏加载慢的常见原因,比如有打包后的文件过大、资源加载顺序不合理,素材资源一次性加载过多等等。

  • 首先从代码层面优化,路由懒加载,分模块加载文件,合理使用路由懒加载可使首屏 JS 体积减少 40%-60%然后对于工具库,尽量采用按需引入的方式。然后合理使用v-if和v-show合理使用watch和computed,使用v-for必须添加key
  • 然后从资源层面优化,图片压缩(Squoosh)+ WebP 格式 + 懒加载(Intersection Observer),优先使用字体图标,大文件放在cdn上,比如阿里云七牛云
  •  然后构建配置优化,使用骨架屏,开启Brotli 、gzip压缩代码,减少代码包的大小,使用Tree Shaking移除 JavaScript 上下文中未被引用代码(它通过分析代码中的导入(import)和导出(export)语句,判断哪些代码是 “活的”(被引用),哪些是 “死的”(未被引用),从而在打包时剔除 “死代码”。作用:大幅减少打包后的代码体积,提升应用加载速度,尤其对使用大型第三方库的项目优化效果显著。)
  • 2.如何解决页面请求接口大规模并发问题

            如何解决页面请求接口大规模并发问题,不仅仅包含了接口并发,还有前端资源下载的请求并发。个人认为可以从以下几个方面来考虑如何解决这个问题:

  • 合并请求,将所有首屏需要依赖的接口,聚合为一个接口
  • 后端优化,可以对接口进行优化,采用缓存技术,对数据进行预处理,减少数据库操作等。另外可以使用反向代理,负载均衡等技术,分担服务器压力。
  • cdn加速,使用cdn缓存技术减少服务器请求压力,提高网站访问速度。(CDN 服务器采用缓存技术,当用户首次请求某个资源时,CDN 会从源服务器获取该资源,并将其缓存到本地。后续再有其他用户请求相同资源时,CDN 会直接从本地缓存中提供该资源,而无需再向源服务器发起请求。)
  • 使用websocket建立一个持久连接,避免反复连接请求。
  • 使用浏览器缓存技术:强缓存,协商缓存,离线缓存,Service Worker 等(Service Worker 是一种运行在浏览器后台的脚本,它可以拦截网络请求,实现离线缓存、消息推送等功能)
  • 聚合一定量的静态资源,比如提取公共代码,对图片进行雪碧图处理,多张图只下载一张图片

3.说说了解的es6-es10的东西有哪些

        块级作用域:let/const 解决 var 的变量提升和闭包问题

        箭头函数(Arrow Functions)绑定外层 this,简化回调

        类(Class)语法糖:基于原型链的面向对象封装

        模块(ES Module)标准化导入导出

        解构赋值(Destructuring)、扩展运算符

ES6(ES2015)之后,JavaScript 新增了许多实用的数组和对象方法,下面为你详细介绍:
  1. Array.from():可将类数组对象或可迭代对象转换为真正的数组。
  2. Array.find():返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined。
  3. Array.findIndex():返回数组中满足提供的测试函数的第一个元素的索引,若没有找到则返回 -1。
  4. Object.assign():用于将一个或多个源对象的所有可枚举属性复制到目标对象,返回目标对象。
  5. Object.keys():返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致。
  6. Object.values():返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用 for...in 循环的顺序相同。

4.常见前端安全性问题

        前端安全的主要领域,比如 XSS、CSRF、SQL 注入(虽然更多是后端,但前端也可能涉及)、点击劫持、跨域问题、密码安全、文件上传安全等等。然后,每个领域下有哪些常见的问题,比如 XSS 的类型、预防措施,CSRF 的原理和防护方法,这些都是面试中常问的。

XSS攻击者通过注入恶意脚本,在用户浏览器中执行,窃取 Cookie、会话令牌等敏感信息

        预防措施:1.输入输出转码对用户输入(如表单、URL 参数)和输出(如 HTML、URL、JavaScript)进行编码(如使用textContent代替innerHTML 2.Cookie 安全属性:设置HttpOnly(防止 JS 读取 Cookie)、Secure(仅 HTTPS 传输)

跨站请求伪造(CSRF)

        攻击者诱导用户执行非自愿的操作(如转账、修改密码),利用用户已登录的会话凭证。
攻击原理:用户登录 A 网站后,浏览器携带 Cookie 访问恶意网站 B,B 向 A 发送伪造请求(如隐藏的表单提交或自动发送的 GET 请求)。

        防御措施Token 验证:提交时校验 Token 与用户会话是否匹配。设置CookieSameSite=Strict/Lax,限制跨站请求携带 Cookie(Strict完全禁止,Lax允许部分安全场景)。

跨域资源共享(CORS)与安全

        限制允许的源:使用Access-Control-Allow-Origin指定单一可信域名(如https://api.example.com),避免使用*(通配符)。

        预检请求(Preflight):对复杂请求(如含Content-Type: application/json的 POST 请求),浏览器先发送 OPTIONS 请求验证权限,需确保服务端正确响应。

前端如何处理密码安全?需要
  •  输入强度校验:通过正则表达式检查密码复杂度(如大小写、数字、特殊字符,长度限制)。
  • 掩码显示:使用input type="password"隐藏输入内容,避免明文泄露。
  • 避免本地存储:绝不将密码明文存储在localStorage/sessionStorage或 Cookie 中(应通过 HTTPS 传输,由后端加密处理)。
  • 防暴力破解:前端配合后端限制登录尝试次数,或添加验证码。
如何避免 URL 中的敏感信息泄露?   
  • 避免明文参数:绝不通过 URL 传递密码、Token 等敏感信息(如https://api.com/login?token=xxx),应通过 POST 请求体或 Header 传输。
  • URL 编码:对用户输入的参数进行编码(如encodeURIComponent),防止特殊字符导致的注入攻击(如路径遍历../)。
  • 路由参数校验:对动态路由参数(如/user/123)进行合法性校验,防止越权访问(如篡改 ID 访问他人数据)。 

其他常见安全问题

  • 如何理解 Web 安全中的 “同源策略”?它的作用是什么?答:浏览器限制不同源(协议、域名、端口均相同)的页面之间交互,防止恶意网站窃取数据,作用是:阻止跨域读取 Cookie、DOM、AJAX 请求,是浏览器的核心安全机制。

  • 什么是依赖项安全?如何防范 npm 包的漏洞?答:避免使用未维护的库,选择下载量高、社区活跃的包。使用package-lock.jsonyarn.lock锁定依赖版本,防止版本劫持。

  • 简述 HTTPS 的作用及前端相关配置 :作用:加密传输数据,防止中间人攻击、数据篡改和窃听。确保证书有效(非自签名),使用 HSTS(HTTP Strict Transport Security)头强制浏览器仅通过 HTTPS 连接。

总结:前端安全核心原则

  1. 输入输出校验:永远不信任用户输入,对所有输入进行严格过滤和转义。
  2. 最小权限原则:限制资源访问范围(如 CORS、CSP),避免过度开放权限。
  3. 关注最新漏洞:定期学习 XSS、CSRF、依赖漏洞等最新攻击手段及防御方案(如 2023 年的 CORS 漏洞confusion attacks)。

5.vite和webpack在热更新上有啥区别 

        1.实现机制,vite使用浏览器原生的ES模块导入功能,可以实现模块级别的热更新,即只更新修改的模块,而不需要刷新整个页面。这样可以提供更快的开发迭代速度。而在webpack中,热更新是基于文件级别的,Webpack 会对整个项目进行打包,需要重新构建并刷新整个页面。(Webpack 的热更新(HMR,Hot Module Replacement)机制不依赖特定的模块导入规范,而是通过 HotModuleReplacementPlugin 插件和 开发服务器(如 webpack-dev-server)实现,其核心原理是在模块更新时,通过注入运行时代码来替换旧模块)

        2.热更新速度,由于 Vite 在开发环境下不需要打包,所以热更新速度非常快。当修改一个模块时,Vite 只需要重新编译该模块,并将更新后的模块发送给浏览器,几乎可以实现即时更新。而webpack 需要重新编译整个模块或部分相关模块,然后再将更新后的代码推送给浏览器。尤其是在项目规模较大、依赖关系复杂时,重新编译的时间会明显增加。

        综上所述,Vite 在热更新方面具有速度快、配置简单等优势,更适合现代前端开发的快速迭代需求;而 Webpack 虽然热更新配置相对复杂,但它的生态系统成熟,对于复杂项目的热更新也能提供有效的支持。

6.在项目中,webpack使用过哪些常见的plugin(插件)和loader(加载器)

 Loader 主要专注于文件的转换,将不同类型的文件转换为 Webpack 可处理的模块;而 Plugin 的功能更广泛,可在 Webpack 构建过程的各个阶段执行各种任务。       

 Loader(加载器)

  • 作用:Loader 的功能就是对不同类型的文件(如 CSS、图片、字体等)进行转换,让 Webpack 能够理解并处理这些文件。简单来说,Loader 就是将非 JavaScript 文件转化成 Webpack 可处理的模块。
  • 使用方式:在 Webpack 配置文件里,借助module.rules属性来配置 Loader。每个规则包含testuse两个关键属性,test用于匹配文件类型,use用于指定要使用的 Loader。
  • 示例:处理 CSS 文件时,一般会用到style-loadercss-loadercss-loader的作用是解析 CSS 文件里的@importurl()语句,style-loader则把 CSS 代码注入到 HTML 文件的<style>标签中。
module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    }
};

 

Plugin(插件)

  • 作用:Plugin 能够在 Webpack 构建过程的各个阶段执行特定的任务,它的功能更为广泛,可用于优化打包结果、管理资源、注入环境变量等。
  • 使用方式:在 Webpack 配置文件里,通过plugins属性来配置 Plugin。首先要引入 Plugin,接着在plugins数组里创建 Plugin 实例。
  • 示例HtmlWebpackPlugin可自动生成 HTML 文件,并把打包后的 JavaScript 文件注入其中。
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ]
};

常用loader

  • css-loader:解析 CSS 文件里的@importurl()语句,把 CSS 文件转化为 JavaScript 模块。
  • less-loader:将 Less 文件编译成 CSS 文件,同样常与css-loaderstyle-loader配合。
  • file-loader:处理文件资源,像图片、字体等,将文件复制到输出目录,并返回文件的公共 URL
  • babel-loader:借助 Babel 将 ES6 + 代码转换为向后兼容的 JavaScript 代码,以确保在旧版本浏览器中也能正常运行。

常用plugin

  • HtmlWebpackPlugin:自动生成 HTML 文件,并且把打包后的 JavaScript 和 CSS 文件注入到 HTML 文件中。
  • TerserPlugin:压缩和混淆 JavaScript 代码,减少文件大小,提高加载速度。
  • CopyWebpackPlugin:将指定的文件或目录复制到输出目录,适用于处理静态资源。
  • MiniCssExtractPlugin:将 CSS 提取到单独的文件中,而非将其注入到 JavaScript 文件里,从而提升性能。

7.vite常见面试题

Vite 核心特性

  1. 原生 ES 模块(基于浏览器 import)
  2. HMR 超快(只更新变化部分)
  3. 按需加载(不需要打包)
  4. 生产模式使用 Rollup
  5. 内置 TypeScript、PostCSS、Vue、React 支持

如何指定 vite 插件 的执行顺序?  

        可以使用 enforce 修饰符来强制插件的位置:

  • pre:在 Vite 核心插件之前调用该插件
  • 默认:在 Vite 核心插件之后调用该插件
  • post:在 Vite 构建插件之后调用该插件

Vite 的 Bundleless 工作流程(Bundleless(无打包模式) 是一种 不需要预先进行代码打包,直接利用 浏览器 ESM 机制 进行模块加载的开发模式。

  1. 解析 index.html
    • Vite 直接以 HTML 作为入口文件,解析其中的 <script type="module">
  2. 按需加载 ES Modules
    • 浏览器遇到 import 语句时,Vite 直接返回相应的模块,而不是像 Webpack 那样打包整个项目。
  3. ESBuild 预编译
    • .ts.jsx.vue 等文件被 Vite 即时转换,只处理被请求的文件,不影响其他部分。
  4. HMR 热更新
    • 代码改动后,Vite 只更新受影响的模块,而不是整个页面。

8.大文件上传

        流程:

        1.获取文件元数据->2.文件切片->3.计算分片Hash与文件hash->4.检查文件是否已经上传过->5.检查需要上传的文件分片->6.上传需要上传的分片->7.待全部分片上传完成后校验分片->8.合并分片

       文件切片 :

        切片核心是利用Blob.prototype.slice方法,和数组slice方法类似,文件的slice方法可以返回原文件的切片,同时利用webwork结合spark-md5去计算文件hash值

        断点上传:

        所谓断点上传(又名恢复上传)就是某个文件已经把部分切片上传到后端且保存,但是在上传过程中出现了一些不可预知问题:例如网络中断、超时、不小心刷新了页面等等,会导致上传中断,但是我们又不想再一次把所有切片又上传一次,只要把未上传的切片上传给后端即可 

        暂停上传:

        其实就是把还在请求中的接口直接中断。这时候我们就可以用到axiosAbortController方法去取消接口请求,(原生XMLHttpRequest 使用 abort 方法)

        并发上传:

        设定一个并发数限制,代表同时可执行的上传任务数量。例如,设置并发数为 3,表示同一时间最多有 3 个切片在上传。利用一个变量来记录当前正在执行的上传任务数量,每次启动一个新的上传任务时,该变量加 1;任务完成(成功或失败)后,该变量减 1。

9.JS执行100万个任务,如何保证浏览器不卡顿

        JavaScript 是单线程的,这意味着同一时间只能执行一个任务。在浏览器环境下,这个单线程要负责处理多种事务,如执行 JavaScript 代码、处理用户交互以及更新 DOM 等。

        当你一次性执行 100 万个任务时,这 100 万个任务会依次在主线程中排队等待执行。在这些任务执行期间,主线程会被完全占用,无法去处理其他事务。例如,当用户点击按钮时,由于主线程正在忙于执行那 100 万个任务,无法响应这个点击事件,从而让用户感觉浏览器卡顿甚至失去响应。

        为了避免这种情况,就需要采用一些技术手段,如使用 Web Workers、requestAnimationFrame 或定时器等,将任务分割成小任务,在不阻塞主线程的情况下逐步执行。

  1. Web Workers将任务移到单独的线程中执行,避免阻塞主线程。
  2. requestIdleCallback 是浏览器的API,可以在主线程空闲时执行非紧急任务。能高效利用主线程的空闲时间,而不会影响页面卡顿
  3. requestAnimationFrame:会在浏览器下次重绘之前执行回调函数。浏览器的重绘频率通常是每秒 60 帧(FPS),也就是大约每 16.67 毫秒重绘一次。因此,使用 requestAnimationFrame 能保证回调函数以稳定的帧率执行,适合处理与动画、渲染相关的任务。

10.事件循环机制概述

        JavaScript 是单线程的,它通过事件循环(Event Loop)来处理异步操作。事件循环主要负责协调调用栈(Call Stack)、宏任务队列(Macrotask Queue)和微任务队列(Microtask Queue)的工作。执行顺序一般是:先执行调用栈里的同步代码,同步代码执行完后,检查微任务队列,将微任务队列中的任务依次取出执行,直到微任务队列为空;接着从宏任务队列中取出一个宏任务执行,执行完这个宏任务后,再次检查微任务队列,如此循环往复。

  • 微任务:微任务会在当前调用栈清空后、下一个宏任务执行之前被执行。也就是说,只要微任务队列中存在任务,JavaScript 引擎就会持续从队列里取出任务并执行,直至微任务队列为空。
  • 宏任务:宏任务在事件循环的特定阶段执行。每次事件循环开始时,会从宏任务队列中取出一个宏任务来执行,执行完毕后,会检查微任务队列,将微任务队列中的任务全部执行完,再接着处理下一个宏任务。
  • 微任务:常见的微任务来源有 Promise 的 thencatchfinally 回调,async/await(本质基于 Promise 实现)中 await 之后的代码,MutationObserver(浏览器环境),process.nextTick(Node.js 环境)等。
  • 宏任务:常见的宏任务来源有 setTimeoutsetIntervalsetImmediate(Node.js 环境)、I/O 操作、UI rendering(浏览器环境)等
  • 微任务:适用于需要在当前操作完成后立即执行的异步操作,例如对 Promise 结果的处理,这样可以保证在当前同步代码执行完后马上处理异步结果,避免不必要的延迟。
  • 宏任务:常用于需要延迟执行或者周期性执行的操作,比如定时器用于实现定时提醒、动画效果中的周期性更新等。