面试高频问题总结

CSS

  • 不定宽高的div水平垂直居中
css 复制代码
   1、父元素添加 position: relative
		div{
			position:absolute;
			top: 50%;
             left: 50%;
             transform: translate(-50%, -50%);
		}
	2、div {
	   display: flex;
       justify-content:center; //子元素水平居中
       align-items:center; //子元素垂直居中
	 }
      
    3、#box {
        width: 100px;
        height: 100px;
        position: relative;
    }

    #content {
        width: 50px;
        height: 50px;
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        margin: auto;
    }

css选择器的优先级

text 复制代码
 !important>行内样式>id选择器>类/属性/伪类选择器>伪元素/标签选择器>通配符选择器*

什么是重绘和回流

复制代码
答:
	回流: 当DOM元素的变化影响了元素的几何属性(例如宽和高),浏览器需要重新计算元素的几何属性,同样其它元素的几何属性也会和位置也会因此受到影响。浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为"回流"。
	重绘: 完成回流后,浏览器会重新绘制受影响的部分到屏幕上中,该过程称为"重绘"。
	
	当我们改变DOM的大小,增加删除都会导致回流,当给DOM元素改变颜色的时候,会导致重绘,回流一定会重绘,重绘不会回流。回流会影响性能,所以我们尽快能的减少回流的操作

flex常用的容器属性

复制代码
   答:
   1. flex-direction: 设置容器中的主轴方向
   2. flex-wrap: 项目在主轴方向上是否换行显示
   3. justify-content: 设置容器中的项目在主轴上的对齐方式
   4. align-items: 单行项目在侧轴上的排列方式
   5. align-content: 多行项目侧轴上的对齐方式
   6. flex-flow: 是flex-direction和flex-wrap的合写, 默认值为row nowrap

JS & TS

  • ES6提供哪些新特性
    • 核心特性:let/const、箭头函数、解构赋值、Promise、Class、模块化(import/export)。
    • 高级特性:Proxy/Reflect、Generator、Map/Set

普通函数和箭头函数的区别?能不能用call/bind/apply?

  • 箭头函数

  • 无自己的 this(继承外层作用域),不可用 new 调用。

  • 不能用 call/apply/bind 改变 this

  • arguments 对象,需用剩余参数(...args)。

  • 普通函数
    • 动态 this(由调用方式决定),支持构造函数调用。

let/const/var的区别

  • var:函数作用域,变量提升(可重复声明)。

  • let/const:块级作用域,存在 TDZ(暂时性死区),不可重复声明。

  • const:声明常量(内存地址不可变,但对象属性可修改)。

深拷贝和浅拷贝的区别是什么?

  • 浅拷贝:仅复制对象的顶层属性(如Object.assign() 或扩展运算符

  • 深拷贝:递归复制所有层级,生成完全独立的对象。

  • 深拷贝实现:

    js 复制代码
    // 方法1:JSON(不支持函数和循环引用)
    const deepCopy = JSON.parse(JSON.stringify(obj));
    // 方法2:lodash.cloneDeep
    import { cloneDeep } from "lodash";
    const deepCopy = cloneDeep(obj);

Object 的遍历对象有几种方式?

  • for...in :遍历对象自身及原型链的可枚举属性;
  • Object.keys(obj) :返回对象自身可枚举属性的数组;
  • Object.getOwnPropertyNames(obj) :返回包括不可枚举属性的数组;
  • Reflect.ownKeys(obj) :返回所有键(包括 Symbol)。

如何判断一个对象是空对象?

  • Object.keys()方法
  • JSON.stringify()方法
  • for...in循环方法
  • Object.getOwnPropertyNames()方法
  • 推荐使用Object.keys(obj).length === 0方法,因为它简洁且性能良好。如果需要检测不可枚举属性,可以使用Object.getOwnPropertyNames()方法。

对this的理解

复制代码
答: this是个关键字,它的指向和函数的调用方式有关
1. 函数调用模式, this指向window
2. 构造函数调用模式, this指向新创建的实例对象
3. 方法调用模式, this指向调用方法的对象
4. 上下文调用模式, call和apply方法中, this指向方法内的第一个参数
                  bind方法中, bind创建的新函数的this绑定为bind方法中新的函数
5. 在事件处理函数中,this指向触发事件的当前元素
6. 定时器中,this指向window
7. 箭头函数中没有this指向问题,它的this和外层作用域的this保持一致
8. 匿名函数中的this总是指向window

new操作符做了什么

复制代码
   1. 创建一个新对象
   2. 函数内部的this指向这个对象
   3. 执行函数体
   4. 自动返回这个函数

对闭包的理解?并能举出闭包的例子

js 复制代码
答: 闭包 函数和声明该函数的词法环境的组合(两个嵌套关系的函数,内部函数可以访问外部函数定义的变量)
    闭包的优点:1、形成私有空间,避免全局变量的污染
               2、持久化内存,保存数据
    闭包的缺点:1、持久化内存,导致内存泄露
    解决:1、尽快避免函数的嵌套,以及变量的引用
          2、执行完的变量,可以赋值null,让垃圾回收机制,进行回收释放内存(当不在引用的变量,垃圾回收机制就会回收)
例1: 点击li获取当前下标
    <ul>
      <li>111</li>
      <li>222</li>
      <li>333</li>
      <li>444</li>
      <li>555</li>
    </ul>
      var lis = document.querySelectorAll('li')
      for (var i = 0; i < lis.length; i++) {
        (function (j) {
          lis[j].onclick = function () {
            console.log(j)
          }
        })(i)
      }
2.防抖函数

什么是原型和原型链?

复制代码
答: 原型: 函数都有prototype属性,这个属性的值是个对象,称之为原型
   原型链: 对象都有__proto__属性,这个属性指向它的原型对象,原型对象也是对象,也有__proto__属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链.

call、apply和bind的区别?

js 复制代码
答: 1. call和apply方法都可以调用函数,方法内的第一个参数可以修改this的指向
	2. call方法可以有多个参数,除了第一个参数,其他参数作为实参传递给函数
			 apply方法最多有2个参数,第二个参数是个数组或伪数组,数组里面的每一项作为实参传递给函数
	3. bind方法不能调用函数,它会创建一个副本函数,并且绑定新函数的this指向bind返回的新的函数

怎么理解函数的防抖和节流?

js 复制代码
答:
1、定义:
防抖: 就是指触发事件后在n秒内函数只能执行一次,如果在n秒内又触发了事件,则会重新计算函数执行时间。
     例如:设定1000毫秒执行,当你触发事件了,他会1000毫秒后执行,但是在还剩500毫秒的时候你又触发了事件,那就会重新开始1000毫秒之后再执行
     示例:search远程搜索框:防止用户不断输入过程中,不断请求资源,n秒内只发送1次,用防抖来节约资源

节流: 就是指连续触发事件但是在设定的一段时间内中只执行一次函数。
     例如:设定1000毫秒执行,那你在1000毫秒触发在多次,也只在1000毫秒后执行一次
     
2、防抖和节流的实现:
    <body>
    <input type="text" class="ipt" />
    <script>
      var timerId = null
      document.querySelector('.ipt').onkeyup = function () {
        // 防抖
        if (timerId !== null) {
          clearTimeout(timerId)
        }
        timerId = setTimeout(() => {
          console.log('我是防抖')
        }, 1000)
      }

      document.querySelector('.ipt').onkeyup = function () {
        // 节流
        console.log(2)
        if (timerId !== null) {
          return
        }

        timerId = setTimeout(() => {
          console.log('我是节流')
          timerId = null
        }, 1000)
      }

    </script>
  </body>

什么是事件流?

复制代码
答: 事件流是指事件传播的顺序,由事件捕获 => 目标事件 => 事件冒泡

Vue & React & Angular

vue中的生命周期有哪些?常用的生命周期在哪些场景下使用?(⭐)

vue 中的父子组件如何通信?

  • 父→子:通过props传递数据。
  • 子→父:通过$emit触发事件,父组件监听。
  • 其他方式:parent/parent/parent/children(不推荐)、Vuex/Pinia、Event Bus。

vue 的跨组件的数据传递方式有哪些?

  • 父子组件:props(父传子) + $emit(子传父);
  • 跨级组件:provide/inject(祖先提供数据,后代注入);
  • 全局状态管理:Vuex/Pinia 存储共享状态;
  • 事件总线:Vue3 使用mitt库实现跨组件通信;
  • URL 参数:通过路由传参(如router.push({ query }))

普通的组件和函数组件有什么区别?

  • 普通组件适用于需要管理状态、拥有复杂逻辑和生命周期处理的场景;而函数组件则更适合简单的、无状态的、对性能要求较高的场景。

vue 中 watch 和 computer 的区别

  • computed :
    • 依赖响应式数据生成新值,具有缓存(依赖不变时不会重新计算);
    • 适用于同步计算(如 fullName = firstName + lastName)。
  • watch :
    • 监听数据变化执行异步或复杂操作;
    • 无缓存,适合数据变化后需要副作用(如请求接口)。

vue 中的 v-if 和 v-show 的区别?分别说下它们的使用场景。

  • 区别:
    • v-if:动态添加/移除DOM元素,切换时触发组件生命周期钩子(如created/destroyed)。
    • v-show:通过CSS的display: none控制显隐,DOM元素始终存在。
  • 使用场景:
    • v-if:条件很少改变(如权限控制),或需要频繁切换开销较大的组件(如复杂表单)。
    • v-show:频繁切换显隐(如Tab栏),避免重复渲染的开销。

如何理解 vue 中的 diff 算法?

  • 核心思想:通过对比新旧虚拟 DOM 树,找到最小更新路径;
  • 优化策略:
    • 同层比较,不跨层级;
    • 通过key标识节点,减少不必要的重新渲染。

vue中的路由管理及路由的注入

  • 组件内使用:useRoute()(当前路由)、useRouter()(路由实例)。

    js 复制代码
    import { createRouter, createWebHistory } from 'vue-router';
    const router = createRouter({ history: createWebHistory(), routes });
    const app = createApp(App);
    app.use(router); // 注入路由

优化 & 打包 & 适配 & 配置项

浏览器的事件循环机制是什么?

  • 宏任务:setTimeout、setInterval、DOM 事件;
  • 微任务:Promise.then、MutationObserver;
  • 执行顺序:
    1. 执行当前宏任务;
    2. 执行所有微任务;
    3. 渲染页面;
    4. 取下一个宏任务执行。

在地址栏输入网址,到数据返回的过程是什么?

js 复制代码
答:  1. 输入url地址后,首先进行DNS解析,将相应的域名解析为IP地址。
     2. 根据IP地址去寻找相应的服务器。
     3. 与服务器进行TCP的三次握手,建立连接。
     4. 客户端发送请求,找到相应的资源库。
     5. 客户端拿到数据,进行相应的渲染。

什么叫跨域?常见的解决方案有哪些?

  • CORS:后端设置响应头(如 Access-Control-Allow-Origin: * );
  • 代理服务器:前端通过 Nginx 或 Webpack DevServer 代理请求;
  • JSONP:通过 script 标签发送 GET 请求(仅支持 GET)*;
  • WebSocket:不受同源策略限制。

重点讲解 项目中的Nginx的配置项

前端性能优化有哪些?例如在:配置层面,打包编译层面,有哪些优化?

  • 构建层:
    • Vite/Webpack:Tree-shaking、代码分割(splitChunks)、压缩资源。
    • 图片优化:转 WebP、使用 SVG 图标、懒加载。
  • 运行时:
    • 组件懒加载:defineAsyncComponent(Vue)或 React.lazy。
    • 虚拟滚动、防抖节流、CDN 加速静态资源。
  • 配置层:
    • HTTP/2、Gzip/Brotli 压缩、缓存策略(Cache-Control)。

打包编译的框架和流程有了解过么?

  • 典型流程: 源代码-> 依赖分析 -> Loader转换资源 -> 插件优化/压缩 ->打包输出Bundle
  • 关键工具:Webpack(基于 JS 模块)、Vite(基于原生 ES Modules)、Rollup(库打包)。

在项目中token过期,前后端的处理方式?

  • 前端
    • 拦截响应(如 Axios 的 interceptors),检测 401 状态码 → 跳转登录页。
    • 无感刷新:用 Refresh Token 换新 Access Token。
  • 后端 :返回标准的 401 Unauthorized 或自定义过期状态码。

微前端和低代码具体是怎么做的?有应用场景么?

  • 微前端:
    • 场景:大型应用拆分为独立子应用(如电商平台包含商品、订单模块);
    • 技术:使用qiankun框架实现子应用隔离与通信。
  • 低代码:
    • 场景:快速生成表单、报表等标准化页面;
    • 工具:阿里宜搭、腾讯微搭。

大屏有没有做过适配?不同的屏幕是如何实现兼容的?

  • CSS3 缩放(Scale)配合视口单位(vw/vh)
    • 首先设定一个基准的屏幕尺寸(例如 1920px * 1080px)作为设计稿尺寸。
    • 然后通过 JavaScript 监听 window.resize 事件,计算当前窗口与基准窗口的缩放比例。
    • 最后将整个页面的容器元素使用 transform: scale(scaleRatio) 进行缩放。
    • 同时,页面内的所有尺寸(宽、高、字体大小)都使用 vw 和 vh 单位,这样可以确保所有元素都能随着视口大小进行自适应。
  • Rem 布局:
    • 类似于移动端的 Rem 方案,将 HTML 的 font-size 设置为基于屏幕宽度或高度的函数。
    • 页面内所有元素的尺寸使用 rem 单位。当屏幕尺寸变化时,动态改变根元素的 font-size,所有元素就会等比例缩放。
  • 使用成熟的库:@amov/ps-plugin 或 fit-screen 这类专门为大屏适配开发的库,它们封装了缩放逻辑,使用起来更加方便。

有没有碰到过不同的手机的适配问题?如何处理手机适配问题?

  • 通常采用柔性布局和弹性布局相结合的策略

  • Viewport 设置

    html 复制代码
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  • VW / VH(现代且推荐的方式)

    • 直接使用 CSS 的视口单位 vw 和 vh。通过 PostCSS 插件(如 postcss-px-to-viewport)将设计稿中的 px 单位自动转换为 vw,非常高效。
  • Flexbox 和 Grid 布局

    对于页面整体的模块排列,大量使用 Flex 弹性布局和 CSS Grid 网格布局,它们能很好地处理不同尺寸屏幕下的元素排列和对齐问题。

  • 媒体查询(Media Queries):用于处理断点式的布局变化。当屏幕尺寸到达某个临界点时,改变布局结构(例如将多列布局变成单列布局)或隐藏/显示某些元素。

  • 总结:适配策略是 "Rem/VW + Flex布局 + 媒体查询" 的组合拳。Rem/VW 解决尺寸缩放问题,Flex/Grid 解决布局问题,媒体查询解决特定场景下的特殊样式问题。

如何配合后端设计页面权限控制,动态路由,以及按钮的权限控制?

  • 后端配合:

    • 用户登录后,后端会返回一个用户角色(role) 或一个权限码列表(permission codes)。
    • 后端提供的API接口本身也要做好权限验证。
  • 前端实现

    • 路由层面:

      • 动态路由:前端先定义好所有可能的路由,但根据用户角色/权限,动态生成可访问的路由配置。使用 router.addRoute() 方法(在Vue Router中)动态添加到路由实例中。
      • 路由守卫:在全局路由守卫(router.beforeEach)中,判断用户是否有权限进入目标路由。如果没有,则跳转到404或登录页。
    • 页面/组件层面:

      • 编写一个全局的自定义指令,例如 v-permission="'user:add'"。
      • 指令的逻辑是:判断当前用户的权限列表是否包含指令所传的值。如果不包含,则直接 el.parentNode.removeChild(el) 将该DOM元素移除。
    • 按钮层面:

      • 同样使用上面的自定义指令 v-permission 来控制按钮的显示与隐藏。
      • 或者封装一个权限判断的函数或组件,在按钮的父组件中调用,通过 v-if 来决定是否渲染按钮。

了解Promise么?Promise有哪些常用的方法? async await有什么作用?

  • Promise 是用于解决 JavaScript 异步编程回调地狱(Callback Hell) 的一种方案,它代表一个最终可能完成(成功)或失败(拒绝)的操作及其结果值。

  • 常用的静态方法

    • Promise.all(iterable):等待所有 promise 成功,或者任何一个失败。全部成功才成功,一个失败就立即失败。
    • Promise.allSettled(iterable):等待所有 promise 都已敲定(无论是成功还是失败)。ES2020引入。
    • Promise.race(iterable):等待任何一个 promise 敲定(成功或失败)。谁快就用谁的结果。
    • Promise.any(iterable):等待任何一个 promise 成功。如果全部失败,则抛出一个聚合错误。ES2021引入。
    • Promise.resolve(value) / Promise.reject(reason):创建一个立即成功或失败的 promise。
  • 常用的实例方法

    • .then():用于注册当 promise 成功时的回调函数。
    • .catch():用于注册当 promise 失败时的回调函数。
    • .finally():无论 promise 最终状态如何,都会执行的操作。
  • async/await 的作用

    • async 关键字用于声明一个函数是异步的,这个函数会返回一个 Promise。
    • await 关键字只能在 async 函数内部使用,用于"等待"一个 Promise 对象 resolved(成功),并取出它的结果值。如果等待的 Promise 被 rejected(失败),则会抛出异常,需要用 try...catch 来捕获处理。

对后端RESTful API了解么?有哪些命名规范?

  • 广泛使用的 API 设计风格,核心思想是用 HTTP 动词(Method)表示操作,用 URL 表示资源
  • 它的主要命名规范和实践包括
    • URL 指向资源(名词),而不是动作(动词)。资源应该使用复数名词
    • 使用 HTTP Method 表示操作类型(动词)
      • GET:获取/查询资源(安全且幂等)。
      • POST:创建新资源。
      • PUT:完整更新/替换资源(幂等)。
      • PATCH:部分更新资源。
      • DELETE:删除资源(幂等)。
    • URL 层级表示资源关系
      • 例如,获取id为123的用户的所有订单:GET /api/users/123/orders
      • 获取这个订单中的某个具体商品:GET /api/users/123/orders/456/products/789
    • 使用合适的HTTP状态码
      • 200 OK:请求成功。
      • 201 Created:创建成功。
      • 301 Moved Permanently,永久性重定向
      • 302 Found(临时重定向)。
      • 400 Bad Request:客户端请求错误。
      • 401 Unauthorized:未认证。
      • 403 Forbidden:无权限(已认证但权限不足)。
      • 404 Not Found:资源不存在。
      • 500 Internal Server Error:服务器内部错误。

组件的性能优化的方案有哪些?

  • 减少不必要的渲染
    • 使用 computed 属性:computed 属性具备缓存功能,仅在其依赖项改变时才会重新计算。这在需要多次计算同一值时,能避免不必要的重复计算,从而提升性能。
    • 使用 watch 监听特定数据变化:借助 watch 可以监听特定数据的变动,仅在数据变化时执行相应操作,避免不必要的渲染。
    • 使用 v-once 指令:v-once 指令能让元素和组件只渲染一次,后续数据变更时不会重新渲染。适用于那些数据不会改变的场景。
  • 优化 DOM 操作
    • 批量更新数据:Vue 的数据更新是异步的,频繁更新数据会触发多次 DOM 重绘和回流。可以利用 this.$nextTick 批量更新数据,减少 DOM 操作次数。
    • 使用事件委托:把事件监听器添加到父元素上,而非每个子元素,这样能减少事件监听器的数量,提高性能。
  • 懒加载组件
    • 异步组件:Vue 支持异步组件,这能让组件在需要渲染时才加载,减少初始加载时间。
  • 优化样式
    • 减少 CSS 选择器的复杂度:复杂的 CSS 选择器会增加浏览器的计算时间,尽量使用简单的选择器。
    • 避免内联样式:内联样式会增加 DOM 的大小,且难以维护和复用。尽量把样式写在 CSS 文件中。
  • 优化图片资源
    • 压缩图片:使用图片压缩工具对图片进行压缩,减小图片文件大小,提高加载速度。
    • 使用响应式图片:依据设备的屏幕尺寸和分辨率,提供不同大小的图片,避免加载过大的图片。
    • 使用函数式组件
    • 函数式组件是无状态、无实例的纯函数,渲染开销小,适合用于简单的、频繁渲染的场景。
相关推荐
yinke小琪9 小时前
分库分表后,主键 ID 如何优雅生成?
java·后端·面试
Q741_14711 小时前
C++ 面试高频考点 力扣 153. 寻找旋转排序数组中的最小值 二分查找 题解 每日一题
c++·算法·leetcode·面试·二分查找
小高00711 小时前
🚄 前端人必收:5 分钟掌握 ES2025 超实用语法
前端·javascript·面试
麦格芬23012 小时前
LeetCode 994 腐烂的橘子
算法·leetcode·职场和发展
Java中文社群13 小时前
面试官:如何提升项目并发性能?
java·后端·面试
前端缘梦14 小时前
深入浅出 Vue 的 Diff 算法:最小化 DOM 操作的魔法
前端·vue.js·面试
BUG收容所所长14 小时前
JavaScript并发控制:如何优雅地管理异步任务执行?
前端·javascript·面试
Mintopia14 小时前
每个国家的核安全是怎么保证的,都不怕在自己的领土爆炸吗?
前端·后端·面试
BUG收容所所长14 小时前
大文件上传的终极指南:如何优雅处理GB级文件传输?
前端·javascript·面试
在未来等你14 小时前
Elasticsearch面试精讲 Day 8:聚合分析与统计查询
大数据·分布式·elasticsearch·搜索引擎·面试