前端题总集

251 阅读18分钟

面试一

1、怎么让一个div水平垂直居中

<div class="a">
    <div class="b"></div>
</div>

//第一种flex 方法
.a{
   width:100%;
   height:100vh;
   display:flex;
   justify-content:center; //水平居中
   align-items:centerl;//垂直居中
   
}
.b{
    width:100px;
    height:100px;
}
• 方法二:Grid (同样推荐)
.a {
 width:100%;
   height:100vh;
    display:grid;
    place-items:center; /* 同时实现水平和垂直居中 */
}

.a {
  position: relative;
  height: 100vh;
}
.b {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%); /* 使用自身宽高的一半进行反向偏移 */
}

2、HTTP的几种请求方法用途

GET: 请求资源,获取资源
POST:提交数据,用于创建新资源或处理数据
PUT: 替换、更新指定资源所有的内容
DELETE:删除指定资源
PATCH:部分更新指定资源
HEAD:类似GET,但只获取响应头

3、Javascript 怎样添加、移除、移动、复制、创建和查找节点

创建:document.createElement('div')
添加 parent.appendChild(child), parent.insertBefore(newNode, referenceNode)
移除: parent.removeChild(child) 或 child.remove()
• 移动:本质上就是先移除旧位置的节点,再添加到新位置。

• 复制:node.cloneNode(true) // true 为深拷贝,包括子节点

• 查找:

  ◦ document.getElementById(‘id‘)

  ◦ document.querySelector(‘.class‘) / document.querySelectorAll(‘p‘)

  ◦ parent.getElementsByClassName(‘class‘)

4.Js中使用typeof能得到哪些类型,===和==分别在何时使用

typeof 返回的字符串:"number", "string", "boolean", "undefined", "object" (注意:null 和数组也会返回 "object",这是历史遗留问题), "function", "symbol" (ES6)。

• == (宽松相等) 和 === (严格相等):

  ◦ ===:推荐使用。首先比较类型,如果类型不同,直接返回 false。类型相同再比较值。

  ◦ ==:如果类型不同,会先进行类型转换,然后再比较值。规则复杂,容易产生意料之外的结果(如 0 == falsetrue)。

5. 闭包的写法、作用、缺点

for(var i=0;i<5;i++){ 
    ((j)=>{ 
        setTimeout(()=>{ 
            console.log(j) 
         },10) })(i) 
}

作用:使函数外部可以操作函数内部的变量。
 缺点:

  1. 内存泄漏:因为闭包会长期驻留内存,如果使用不当(例如在不需要的DOM元素上绑定事件处理程序),可能导致内存无法被回收。

6. 描述 Vue 组件生命周期 (以 Vue 2 为主

• 创建阶段:

◦ beforeCreate:实例刚创建,data 和 methods 未初始化。

◦ created:实例创建完成,data 和 methods 已可用,但DOM未生成。

• 挂载阶段:

◦ beforeMount:模板编译完成,但尚未挂载到页面。

◦ mounted:实例已挂载到DOM,可以操作DOM。

• 更新阶段:

◦ beforeUpdate:数据更新时,虚拟DOM重新渲染和打补丁之前。

◦ updated:数据更新后,虚拟DOM重新渲染和打补丁完成。

• 销毁阶段:

◦ beforeDestroy:实例销毁之前,此时实例仍完全可用。适合清除定时器、解绑事件。

◦ destroyed:实例销毁后,所有绑定和监听器被移除

7. computed 有啥特点?computed和watch, methods的区别

• computed (计算属性) 特点:

  1. 缓存性:最大的特点。只有当其依赖的响应式数据发生改变时,才会重新计算,否则直接返回缓存的结果。

  2. 声明式:像普通属性一样在模板中声明使用,逻辑清晰。

  3. 同步操作:必须是同步操作,无法处理异步逻辑。

• 三者的区别:

特性	computed	watch	methods
缓存	有缓存	无缓存	无缓存
使用场景	当一个值依赖于其他一个或多个响应式数据时	当需要在数据变化时执行副作用(如异步请求、复杂逻辑)时	用于绑定事件或需要每次渲染都重新执行的逻辑
异步支持	不支持	支持	支持(但在模板中直接调用异步方法可能不按预期工作)
返回值	必须返回一个值	不返回值,通常用于执行操作	可以返回任何值,也可以不返回
调用方式	在模板中作为属性调用:{{ computedValue }}	在选项中声明,自动监听	在模板中作为方法调用:@click="methodName"

8. Vuex 中 action 和 mutation 有何区别?

• Mutation (变更):

◦ 职责:是修改 Vuex state 的唯一途径。

◦ 特性:必须是同步函数。这样 Devtools 可以准确地跟踪状态变化,方便调试。

◦ 调用:通过 commit('mutationName', payload) 调用。

• Action (动作):

◦ 职责:处理业务逻辑,可以包含任意异步操作(如 API 请求)。

◦ 特性:不直接修改 state,而是通过提交 mutation 来修改。

◦ 调用:通过 dispatch('actionName', payload) 调用。

简单比喻: Mutation 像是会计,只负责记账(修改state);Action 像是业务员,可以出去跑业务(异步请求),然后拿回单据让会计记账。

9. ES6 操作数组方法区别: map, filter, reduce, find

• map:遍历数组的每个元素,对其执行提供的函数,并返回一个由函数结果组成的新数组。原数组不变。用于“映射”或“转换”数组。

  ◦ const doubled = [1, 2, 3].map(x => x * 2); // [2, 4, 6]

• filter:遍历数组,返回一个由满足条件(函数返回true)的元素组成的新数组。用于“过滤”。

  ◦ const evens = [1, 2, 3, 4].filter(x => x % 2 === 0); // [2, 4]

• reduce:遍历数组,将每个元素执行一个“缩减器”函数,结果汇总为单个返回值。用于“累加”、“扁平化”或任何需要将数组转换为单一值的操作。

  ◦ const sum = [1, 2, 3].reduce((acc, cur) => acc + cur, 0); // 6

• find:返回数组中第一个满足所提供测试函数的元素的值。如果没找到,则返回 undefined。

  ◦ const found = [5, 12, 8, 130].find(num => num > 10); // 12

10. cookies、sessionStorage、localStorage 的区别

特性	cookies	sessionStorage	localStorage
生命周期	可设置过期时间,否则随浏览器关闭失效	仅限当前会话,关闭标签页或浏览器即失效	永久存储,除非手动清除
存储大小	~4KB	~5MB	~5MB
与服务器通信	会在每次HTTP请求中自动携带在请求头中,增加流量	不参与服务器通信	不参与服务器通信
API 易用性	原生API较复杂,常用库操作	简单的键值对API(setItem, getItem, removeItem)	同sessionStorage
作用域	在所有同源窗口和标签页中共享	仅在当前浏览器标签页内共享	在所有同源窗口和标签页中共享

面试二

一、选择题(每题10分,共60分,多选题)

1. 关于JavaScript中闭包(Closure)的说法,正确的是

正确答案:A、B、D

  • A:闭包可以访问其所在作用域的局部变量 (闭包本质是函数+其词法环境,能访问定义时的外部作用域变量)
  • B:闭包会增加内存消耗,因为会持有外部作用域的引用 (被闭包引用的变量不会被垃圾回收,长期存在会占用内存)
  • C:闭包只能在函数内部创建,外部无法使用 (闭包可以通过返回函数等方式暴露给外部使用)
  • D:闭包常用于实现数据的封装与私有化 (比如模块模式,通过闭包隐藏内部变量,只暴露接口)

2. 下面代码执行后,正确的执行顺序是

console.log(1);
setTimeout(() => { console.log(2); }, 0);
const p = new Promise((resolve) => {
  console.log(3);
  setTimeout(() => { console.log(4); resolve(); }, 100);
});
p.then(() => { console.log(5); setTimeout(() => { console.log(6); }, 0); });
console.log(7);

正确答案:C(1 3 7 5 2 4 6) 执行逻辑:

  1. 同步任务:console.log(1) → 输出 1
  2. 宏任务:setTimeout(...,0) 放入宏任务队列
  3. 同步任务:new Promiseconsole.log(3) → 输出 3
  4. 宏任务:setTimeout(...,100) 放入宏任务队列
  5. 同步任务:console.log(7) → 输出 7
  6. 微任务:Promise.then 回调执行 → 输出 5,并将 setTimeout(...,0) 放入宏任务队列
  7. 宏任务队列按顺序执行:先执行 setTimeout(...,0) → 输出 2;再执行 setTimeout(...,100) → 输出 4;最后执行 p.then 里的 setTimeout(...,0) → 输出 6

3. 关于JavaScript基础类型,以下说法正确的是

正确答案:A、B、C

  • A:基本类型一共有6种:String、Number、Boolean、Null、Undefined、Symbol (ES6 标准下的6种原始类型)
  • B:BigInt 是 ES2020 新增的第7种基本类型 (用于表示任意精度整数)
  • Ctypeof null === 'object' 是一个历史遗留问题 (JS 最初实现的 bug,一直保留至今)
  • D:数组(Array)是 JavaScript 的基本类型之一 (数组是引用类型,属于 Object 子类)

4. 以下关于 Vue 计算属性(computed)和侦听器(watch)的说法正确的是

正确答案:A、B、D

  • A:computed 有缓存,只有依赖变化才重新计算 (依赖不变时,多次访问会直接返回缓存结果)
  • B:watch 适合监听数据变化并执行异步或开销较大的操作 (computed 不适合异步操作,watch 更灵活)
  • C:computed 可以实现与 watch 完全相同的功能,性能更高 (computed 是计算值,watch 是监听变化,场景不同,无法完全替代)
  • D:watch 可以监听对象的深层属性变化 (配置 deep: true 即可深度监听对象内部属性)

5. 关于 this 关键字,下列说法正确的是

正确答案:A、B、D

  • A:箭头函数中的 this 在定义时绑定,取决于外层作用域 (箭头函数没有自己的 this,继承自外层作用域)
  • B:普通函数的 this 取决于调用方式 (谁调用指向谁,如对象方法、全局调用、bind/call/apply 改变指向)
  • C:在严格模式下,未绑定的函数调用中 this 指向 window (严格模式下,未绑定的函数调用中 this 为 undefined
  • D:在构造函数中,this 指向新创建的对象 (new 操作符会创建新对象,并将 this 绑定到该对象)

6. 下面代码执行后,result 的值正确的是

const arr = [1, 2, 3, 4];
const result = arr
  .filter(x => x % 2 === 0)
  .map(x => x * 2)
  .reduce((sum, x) => sum + x, 0);

正确答案:B、C、D

  • A:result 的值是 12 (实际计算:filter[2,4]map[4,8]reduce12?不,4+8=12,这里需要注意:filter 后是 [2,4]map 后是 [4,8]reduce 求和是 12,所以 A 正确?哦,原选项:
    • A. result 的值是 12
    • B. filter 之后的数组是 [2,4]
    • C. map 之后的数组是 [4,8]
    • D. reduce 之后的结果是 14 (实际是 12) 修正:正确答案:A、B、C

二、问答题(每题10分,共40分)

1. 请简述 Vue2 和 Vue3 在响应式系统上的主要区别

维度Vue2Vue3
实现原理基于 Object.defineProperty 对对象属性进行劫持基于 Proxy 对整个对象进行代理
数组监听重写数组原型方法(push/pop 等)实现监听,无法监听数组 length 变化原生支持数组监听,包括索引修改、length 变化
新增/删除属性无法自动监听,需使用 Vue.set()/Vue.delete()自动监听对象新增/删除属性
性能递归遍历所有属性,初始化性能开销大惰性代理,只有访问时才劫持,性能更优
支持类型仅支持对象/数组支持 Map/Set/WeakMap/WeakSet 等更多类型

2. 请比较 Vue2 和 Vue3 的生命周期函数的区别

Vue2 选项式 APIVue3 组合式 API说明
beforeCreatesetup()合并到 setup,setup 是组合式 API 的入口
createdsetup()合并到 setup
beforeMountonBeforeMount挂载前
mountedonMounted挂载完成
beforeUpdateonBeforeUpdate更新前
updatedonUpdated更新完成
beforeDestroyonBeforeUnmount卸载前
destroyedonUnmounted卸载完成
-onErrorCaptured新增,捕获子孙组件错误
-onRenderTracked/onRenderTriggered新增,调试用,追踪响应式依赖

3. 请说明 webpack 和 Vite 在构建上的核心区别

维度webpackVite
开发模式打包所有模块后启动开发服务器,冷启动慢基于 ES Module,按需编译,冷启动极快
热更新重新打包变更模块及依赖,更新速度随项目增大而变慢仅重载变更模块,热更新速度几乎不受项目大小影响
生产构建全量打包,支持复杂代码分割、tree-shaking基于 Rollup 打包,打包速度更快,产物更轻量
依赖处理打包时处理所有依赖预构建依赖(esbuild),将 CommonJS/UMD 转为 ESM
配置复杂度配置繁琐,需处理 loader、plugin 等开箱即用,内置常见功能,配置更简洁

4. 在 Vue 项目中,如何优化首屏加载速度?

  1. 路由懒加载:使用 () => import('@/views/xxx') 拆分路由,按需加载页面代码
  2. 组件懒加载:异步加载非首屏组件(如 defineAsyncComponent
  3. 第三方库 CDN 引入:将 Vue、Element UI 等库改为 CDN 引入,减少打包体积
  4. 代码分割:配置 webpack/Vite 分割 chunk,避免单文件过大
  5. 图片优化:压缩图片、使用 WebP 格式、图片懒加载
  6. 开启 Gzip 压缩:服务器配置 Gzip/Brotli 压缩,减小传输体积
  7. 预加载/预获取:对关键资源使用 <link rel="preload">,对非关键资源使用 <link rel="prefetch">
  8. 减少首屏渲染内容:骨架屏替代空白加载,优先渲染核心内容
  9. Tree Shaking:移除未使用代码,减小打包体积
  10. SSR/SSG:服务端渲染或静态站点生成,直接返回首屏 HTML

5. 怎么让一个 div 水平垂直居中

  • Flex 布局(推荐)
    .parent { display: flex; justify-content: center; align-items: center; }
    
  • 绝对定位 + transform
    .parent { position: relative; }
    .child { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); }
    
  • Grid 布局
    .parent { display: grid; place-items: center; }
    

6. HTTP 的几种请求方法用途

  • GET:获取资源(查询),参数在 URL,幂等、可缓存
  • POST:提交数据(新增),参数在请求体,非幂等
  • PUT:更新资源(完整替换),幂等
  • DELETE:删除资源,幂等
  • PATCH:部分更新资源,非幂等
  • HEAD:获取响应头,与 GET 一致但无响应体
  • OPTIONS:预检请求,用于跨域时询问服务器支持的方法

7. JavaScript 怎样添加、移除、移动、复制、创建和查找节点

  • 创建document.createElement('div')
  • 查找getElementById()/querySelector()/querySelectorAll()
  • 添加parent.appendChild(child)/parent.insertBefore(newNode, refNode)
  • 移除parent.removeChild(child)
  • 复制node.cloneNode(true)(true 为深拷贝)
  • 移动parent.appendChild(node)(将已存在节点从原位置移动到新位置)

8. JS 中使用 typeof 能得到哪些类型,=== 和 == 分别在何时使用

  • typeof 返回值"number"/"string"/"boolean"/"undefined"/"object"/"function"/"symbol"/"bigint"
  • ===:严格相等,比较值和类型,推荐在所有场景使用(避免类型转换问题)
  • ==:宽松相等,会自动类型转换,仅在明确需要类型转换时使用(如判断 null == undefined

9. 闭包的写法,闭包的作用,闭包的缺点

  • 写法
    function createCounter() {
      let count = 0;
      return function() { return ++count; };
    }
    const counter = createCounter();
    
  • 作用
    1. 封装私有变量,实现模块化
    2. 延长变量生命周期
    3. 实现函数柯里化/偏函数
  • 缺点
    1. 内存泄漏:被闭包引用的变量无法被垃圾回收
    2. 性能损耗:额外的作用域链查找开销

10. 描述 Vue 组件生命周期(以 Vue2 为例)

  1. beforeCreate:实例初始化后,数据观测/事件配置前
  2. created:实例创建完成,数据观测/事件配置完成,$el 未生成
  3. beforeMount:挂载开始前,模板编译完成,未渲染到 DOM
  4. mounted:挂载完成,DOM 已渲染,可访问 DOM 元素
  5. beforeUpdate:数据更新前,DOM 未更新
  6. updated:数据更新完成,DOM 已更新
  7. beforeDestroy:实例销毁前,仍可访问实例
  8. destroyed:实例销毁完成,所有事件监听器被移除

11. computed 有啥特点?computed 和 watch、methods 的区别

特性computedwatchmethods
缓存有缓存,依赖不变时直接返回缓存无缓存,数据变化时触发无缓存,每次调用都执行
使用场景计算衍生值(如过滤列表、求和)监听数据变化并执行异步/复杂操作通用业务逻辑,事件处理
调用方式作为属性访问(this.total配置监听,自动触发作为方法调用(this.handleClick()

12. Vuex 中 action 和 mutation 有何区别?

  • mutation
    • 同步操作,直接修改 state
    • 必须是纯函数,不能有异步逻辑
    • 通过 commit() 触发
  • action
    • 异步操作,不能直接修改 state,需提交 mutation
    • 可包含任意异步逻辑(如 API 请求)
    • 通过 dispatch() 触发

13. ES6 操作数组方法区别(map/filter/reduce/find)

  • map:遍历数组,返回新数组,每个元素按规则转换
  • filter:遍历数组,返回新数组,包含满足条件的元素
  • reduce:遍历数组,将元素累积为一个值(求和、求平均等)
  • find:遍历数组,返回第一个满足条件的元素,未找到返回 undefined

14. 描述 cookies、sessionStorage、localStorage 的区别

特性cookiessessionStoragelocalStorage
生命周期可设置过期时间,默认会话结束会话结束(标签页关闭)永久存储,需手动删除
存储容量约 4KB约 5MB约 5MB
与服务器通信随请求自动发送到服务器不发送不发送
作用域同源(可设置 path/domain)同源+标签页同源
API原生 API 繁琐setItem()/getItem()/removeItem()/clear()同 sessionStorage

总结

这些题目覆盖了JS 基础、异步编程、Vue 核心、工程化等前端高频考点,建议你:

  1. 重点掌握闭包、this、Promise/Event Loop 等 JS 核心概念
  2. 熟练 Vue2/Vue3 响应式、生命周期、状态管理
  3. 熟悉构建工具(webpack/Vite)和性能优化思路
  4. 多手写代码验证知识点,避免纸上谈兵

面试三

一、不定项选择题(每题 4 分)

1. 关于 http 的响应码,说法正确的有( )

A. 400: 请求出现错误B. 403: 请求的内容不存在C. 304: 请求的资源并没有被修改过D. 301: 请求成功,但结果有多种选择

答案:A、C解析:

  • A ✅ 400 Bad Request:客户端请求语法错误、参数无效等,属于请求端错误。
  • B ❌ 403 Forbidden:服务器拒绝访问(权限不足),请求内容不存在对应 404 Not Found。
  • C ✅ 304 Not Modified:客户端缓存有效,资源未更新,直接使用本地缓存。
  • D ❌ 301 Moved Permanently:资源永久重定向;“请求成功但结果有多种选择” 对应 300 Multiple Choices。

2. var a = /678/, b = /678/; a == b; a === b; 两者各输出为( )

A. true falseB. false falseC. true trueD. false true

答案:B解析:正则表达式在 JS 中是引用类型,即使字面量内容完全相同,ab也是两个独立的对象,存储在不同内存地址中。=====都会比较引用地址,因此两次结果均为false


3. var a = "40", var b=7, 则执行 a%b 会得到( )

A. 报错B. "40%7"C. 5D. " 5"

答案:C解析:%是取模运算符,JS 会先对字符串"40"进行隐式类型转换为数字40,再执行40 % 7,计算结果为5(数字类型)。


4. Position 什么属性值是绝对定位、相对什么定位( )

A. absolute, 有定位的父元素B. fixed, 窗口C. absolute, 窗口D. relative, 有定位的父元素

答案:A解析:

  • position: absolute(绝对定位):相对于最近的非static定位父元素进行定位;若无任何非static父元素,则相对于根元素(html/viewport)定位。
  • fixed是固定定位,相对于浏览器窗口定位;relative是相对定位,相对于自身原始位置定位。

5. ["1", "2", "3"].map(parseInt)?( )

A. [1, NaN, NaN]B. [1, 2, NaN]C. [1, 2, 3]D. [NaN, NaN, NaN]

答案:A解析:map回调会给parseInt传递两个参数:当前元素、元素索引。

  • parseInt("1", 0):基数 0 时按十进制解析,结果为1
  • parseInt("2", 1):基数需在 2-36 之间,1 为无效值,返回NaN
  • parseInt("3", 2):基数为 2 时,只能解析 0/1,3无效,返回NaN

6. 下面说法正确的有( )

A. substring 仅能用于字符串,slice 仅能用于数组B. substring 仅能用于字符串,slice 仅能用于字符串C. substring 可用于字符串和数组,slice 可用于数组D. substring 可用于字符串,slice 可用于数组

答案:D解析:

  • substring:是字符串专属方法,用于截取字符串的子串,数组无此方法。
  • slice:可同时用于字符串和数组,用于截取子字符串或子数组(不修改原数据)。

二、判断题

4. Cookie 未设置有效期,浏览器关闭后 cookie 还是存在的( )

答案:×(错误)解析:未设置有效期的 Cookie 为会话 Cookie,仅存在于浏览器会话期间,关闭浏览器后会自动删除,不会持久化存储。

5. typeof(null) === 'undefined'( )

**答案:×(错误)**解析:JS 中typeof null的结果为"object"(历史遗留 bug),typeof undefined才是"undefined",因此等式不成立。


6. 说一下 http2 的多路复用

**答案解析:**HTTP/2 的多路复用是核心性能优化,解决了 HTTP/1.1 的队头阻塞问题,核心要点如下:

  1. 单连接多流:在同一个 TCP 连接上,可同时发送多个请求和响应,所有数据被拆分为独立的二进制帧(Frame)传输。
  2. 帧乱序传输 + 流标识重组:每个帧带有流 ID 标识,接收方可根据 ID 将不同流的帧重组为完整的请求 / 响应,无需等待前一个请求完成。
  3. 解决队头阻塞:HTTP/1.1 中同一连接的请求需排队执行,前一个请求阻塞会导致后续请求全部等待;多路复用让请求互不阻塞,大幅提升并发效率。
  4. 头部压缩(HPACK) :配合多路复用,HTTP/2 使用 HPACK 算法压缩请求头,减少重复头字段传输,进一步降低开销。

三、解答题(每题 6 分)

1. 简述 vue2/vue3 源码的了解和运用的区别

答案解析:

表格

对比维度Vue2Vue3
数据响应式Object.defineProperty 劫持对象属性,无法监听数组索引 / 长度变化、对象新增属性Proxy 代理整个对象,支持数组、对象、新增 / 删除属性的完整响应式监听
API 风格选项式 API(Options API),代码按data/methods/computed等选项拆分,大型项目逻辑分散组合式 API(Composition API),按逻辑关注点组织代码,支持setup函数、自定义 Hook 复用逻辑
虚拟 DOM 优化无编译优化,更新时全量 diff 虚拟 DOM编译时标记动态节点(PatchFlag)、静态提升(hoistStatic),仅 diff 动态节点,性能提升
打包与体积完整构建,体积较大模块化重构,支持 Tree-Shaking,按需引入 API,生产包体积减少约 40%
TypeScript 支持支持较弱,类型推断有限原生使用 TypeScript 重构,类型支持完善,组件、Hook 均有完整类型提示
生命周期选项式钩子(beforeCreate/created等)组合式钩子(onMounted/onUpdated等),可在任何逻辑中调用,更灵活

2. 请写出以下执行顺序?如何发起多个请求?

js

console.log('1')
let promise1 = new Promise(function(resolve) {
    console.log('2')
    resolve()
    console.log('3')
}).then(function () {
    console.log('4')
})
setTimeout(function() {
    console.log('5')
})
console.log('6')
(1)执行顺序

**答案:1 → 2 → 3 → 6 → 4 → 5**解析(事件循环机制):

  1. 主线程同步代码执行,输出1
  2. 执行new Promise构造器内部同步代码,输出2;调用resolve()后,Promise 状态变为fulfilled,但then回调属于微任务,暂不执行;继续输出3
  3. 遇到setTimeout,回调属于宏任务,加入宏任务队列。
  4. 主线程同步代码继续执行,输出6
  5. 同步代码执行完毕,处理微任务队列,执行promise.then回调,输出4
  6. 微任务队列清空后,处理宏任务队列,执行setTimeout回调,输出5
(2)如何发起多个请求

答案解析:

  • 并行请求(全部成功才返回):Promise.all([p1, p2, p3]),所有请求成功则返回结果数组,任意一个失败则立即 reject。
  • 竞速请求(谁先完成返回谁):Promise.race([p1, p2]),返回第一个完成(成功 / 失败)的请求结果。
  • 容错并行(所有结果都返回):Promise.allSettled([p1, p2]),无论请求成功 / 失败,都返回每个请求的状态和结果。
  • 顺序请求(按队列执行):使用async/await按顺序执行,或then链式调用,确保前一个请求完成后再执行下一个。

3. 用 js 实现随机选取 10-100 之间的 10 个数字,存入一个数组,并排序

完整代码实现(含去重、升序排序):

js

// 1. 生成 [min, max] 之间的随机整数(包含两端)
function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

// 2. 生成10个不重复的随机数(若允许重复,可去掉includes判断)
let numArr = [];
while (numArr.length < 10) {
    const randomNum = getRandomInt(10, 100);
    // 去重:避免数组中出现重复数字
    if (!numArr.includes(randomNum)) {
        numArr.push(randomNum);
    }
}

// 3. 数组升序排序(降序改为 (a,b) => b - a)
numArr.sort((a, b) => a - b);

console.log(numArr);

说明:

  • Math.random()生成[0,1)的随机数,通过公式转换为[10,100]的整数。
  • sort((a,b) => a - b)为升序排序,符合常规需求;若需降序,改为(a,b) => b - a即可。
  • 代码中加入了去重逻辑,若题目允许数字重复,可直接去掉includes判断,简化为numArr.push(randomNum)

面试四

选择题 10 道

第 1 题

动态改变层内容方法错误的是A、innerHTMLB、innerTextC、隐藏层D、display

答案:无错误 / 全选 ABCD📌解析:

  • innerHTML / innerText:直接修改标签内容 ✅
  • display:none、隐藏层:视觉隐藏,变相控制内容展示 ✅四个都能 “改变层展示内容”,题目设定为全选。

第 2 题

图片模拟提交按钮,写法正确的是A、<img src="" onclick="form.submit()">B、<img src="" onsubmit="form.submit()">C、<img src="" click="form.submit()">D、<img src="" submit="form.submit()">

答案:A📌解析:

  • 图片标签 没有 onsubmit、submit 事件
  • 原生点击事件:onclick
  • 手动调用表单提交:form.submit()

第 3 题

CSS 选择器权重,由高到低排序a. .list .box pb. #list .box div spanc. .list spand. #list #boxe. p:last-childf. 行内 style 样式

A、f>d>b>a>c>eB、f>d>b>a>e>cC、f>d>b>a>c=eD、d>f>b>a>c=e

答案:C📌解析:权重规则:行内样式 (1000) > ID (100) > 类 / 伪类 (10) > 标签 (1)

  • f 行内样式:最高
  • d 双 ID:(2,0,0)
  • b ID + 类 + 标签
  • a 双类 + 标签
  • c 类 + 标签
  • e 标签 + 伪类c 与 e 权重相等最终:f > d > b > a > c = e

第 4 题

数组声明错误的是A、var arr = new Array()B、var arr = []C、var arr[] = new Array(3)(4)D、var arr = new Array(10)

答案:C📌解析:

  • JS 声明数组不能写 var arr[] (Java 语法)
  • new Array (3)(4) 语法完全非法ABD 都是合法数组定义

第 5 题

js

["1","2","3"].map(parseInt)

A、[1,2,3]B、[1,NaN,NaN]C、[1,undefined,3]D、报错

答案:B📌解析:

  1. map((item,index)=>{})
  2. parseInt(值, 进制)
  • parseInt('1', 0) → 1
  • parseInt ('2', 1) → 1 进制无效 → NaN
  • parseInt ('3', 2) → 二进制无 3 → NaN

第 6 题

不属于 document 对象方法的是A、writeB、getElementByIdC、querySelectorD、bgColor

答案:D📌解析:

  • write /getElementById/querySelector 都是 document 标准方法
  • bgColor 是废弃属性,不是方法

第 7 题

不属于 canvas 方法的是A、getContextB、fillC、strokeD、controller

答案:D📌解析:

  • getContext ():获取画布上下文
  • fill ()、stroke ():绘制填充 / 描边
  • controller 不属于 canvas 任何 API

第 8 题

js

var name = 'World';
(function () {
  if (typeof name === 'undefined') {
    var name = 'Jack';
    console.log('Goodbye ' + name);
  } else {
    console.log('Hello ' + name);
  }
})();

A、Goodbye JackB、Hello WorldC、Goodbye WorldD、Hello Jack

答案:A📌解析:

  1. 函数内 var name 发生变量提升
  2. 局部 name 提升,未赋值 → undefined
  3. 进入 if 判断,重新赋值 Jack输出:Goodbye Jack

第 9 题

js

setTimeout("check",10)

说法正确的是A、每隔 10 毫秒执行 checkB、check 执行 10 次C、立即执行 checkD、10 毫秒后执行一次 check

答案:D📌解析:

  • setTimeout延时执行一次
  • setInterval:间隔循环执行
  • 本题:延迟 10ms,单次执行 check

第 10 题

js

var temp = null;
alert(typeof temp);

A、undefinedB、objectC、nullD、number

答案:B📌解析:JS 经典历史 Bug:

js

typeof null  // "object"

null 是基本数据类型,但 typeof 检测结果为 object。


简答题 10 道(犀照科技 原题 + 标准答案 + 解析)

1、同步和异步的区别

✅答案:

  1. 同步:代码自上而下顺序执行,上一段代码没执行完,后面代码阻塞等待,阻塞主线程。
  2. 异步:不会阻塞代码执行,先跳过异步任务,执行同步代码;异步完成后通过回调、Promise、async/await 回调执行。适用:耗时操作(请求、定时器、文件读写)用异步。

2、CSS 动画 和 JS 动画区别

✅答案:

  1. CSS 动画:transition / @keyframes,浏览器 GPU 加速,性能高、代码简单,适合简单过渡、固定动画。
  2. JS 动画:setTimeout /setInterval/requestAnimationFrame,控制粒度更细,可复杂逻辑、动态计算、交互联动,频繁操作 DOM 性能略低。

3、优雅降级 和 渐进增强

✅答案:

  • 渐进增强:先保证基础功能,兼容低端浏览器,再给现代浏览器加样式、动画、高级交互。
  • 优雅降级:先开发高级完整版,再向下兼容低端浏览器,保证核心功能可用。

4、网页字体使用奇数还是偶数?为什么

✅答案:使用偶数解析:浏览器像素渲染对齐机制,偶数字号渲染更清晰、无锯齿、无模糊;奇数字号容易出现像素偏移、文字发虚。


5、虚拟 DOM 实现原理

✅答案:

  1. 用 JS 普通对象结构,模拟真实 DOM 结构(虚拟 DOM)。
  2. 数据变化生成全新虚拟 DOM 树。
  3. 通过 Diff 算法对比新旧虚拟 DOM,找出差异节点。
  4. 只把差异部分更新到真实 DOM,减少重排重绘,提升性能。

6、Vue 路由跳转方式

✅答案:

  1. 声明式:<router-link to="路径">
  2. 编程式
  • this.$router.push() 前进,保留历史
  • this.$router.replace() 替换,不保留历史
  • this.$router.go(n) 前进 / 后退
  • back() / forward()

7、Vue 项目如何解决跨域

✅答案:

  1. 开发环境:vue.config.js 配置 devServer.proxy 代理跨域
  2. 生产环境:
  • 后端配置 CORS 跨域头
  • Nginx 反向代理
  • 少量 GET 请求可用 JSONP

8、Vue 中如何引入 jQuery

✅答案:

  1. 安装:npm install jquery
  2. 全局挂载:main.js 全局引入
  3. 组件内局部引入:import $ from 'jquery'Vue3 需配置全局挂载或按需引入。

9、Vue 动态路由如何使用

✅答案:

  1. 动态路由规则:/user/:id
  2. 获取参数:
  • 选项式:this.$route.params
  • 组合式:useRoute()
  1. 常用于详情页、id 动态页面。

10、Vue3 新特性

✅答案:

  1. 响应式改用 Proxy,解决 Vue2 数组、对象新增属性缺陷
  2. 组合式 API setup,逻辑复用更强
  3. 多根节点 Fragment
  4. Teleport 瞬移组件、Suspense 异步组件
  5. 更好 TS 支持、体积更小、编译优化、Diff 算法升级

总结

这两套题覆盖了**前端基础(JS/CSS/HTTP)、框架核心(Vue2/Vue3)、工程化(跨域/构建/性能)**等高频考点,建议你重点巩固:

  1. JS 类型转换、异步编程、变量提升等核心概念
  2. Vue 响应式原理、路由、状态管理
  3. CSS 选择器权重、布局、动画
  4. 浏览器缓存、跨域、性能优化

面试五

一、JavaScript 部分(10题)

1. 选择题

[1,2,3].map(parseInt)

结果为: A. [1,2,3] B. [1, NaN, NaN] C. [NaN, NaN, NaN] D. [1, 2, NaN] 答案:B

2. 选择题

var a = {n:1};
var b = a;
a.x = a = {n:2};
console.log(a.x);
console.log(b.x);

输出: A. undefined, {n:2} B. {n:2}, {n:2} C. undefined, undefined D. {n:2}, undefined 答案:A

3. 选择关于 Promise 执行顺序,正确顺序是:

setTimeout(()=>console.log(1),0)
Promise.resolve().then(()=>console.log(2))
console.log(3)

A. 1 2 3 B. 3 2 1 C. 2 3 1 D. 3 1 2 答案:B

4. 判断typeof null === 'object' 是 JS 设计错误,null 是基本类型。()

答案:对

5. 选择以下能深拷贝对象的是:

A. Object.assign B. 扩展运算符... C. JSON.parse(JSON.stringify) D. 直接赋值 答案:C

6. 选择题

function test(){
  let a = 1;
  return ()=>{console.log(a)}
}
test()();

涉及的特性是: A. 原型链 B. 闭包 C. 继承 D. 变量提升 答案:B

7. 选择以下哪个方法不会改变原数组:

A. push B. splice C. slice D. sort 答案:C

8. 判断箭头函数没有自己的 this,没有 arguments,不能用作构造函数。()

答案:对

9. 选择题

let arr = [1,,3]; arr.length 结果是: A. 2 B. 3 C. 报错 D. 0 答案:B

10. 手写实现函数:生成 10 个 10~100 随机整数,升序排序并去重。

答案

function getArr() {
  let arr = Array.from({length:10},()=>Math.floor(Math.random()*91)+10)
  arr = [...new Set(arr)].sort((a,b)=>a-b)
  return arr
}

二、Vue2 部分(8题)

1. 选择Vue2 响应式核心 API 是:

A. Proxy B. Object.defineProperty C. Reflect D. Observer 答案:B

2. 选择Vue2 中无法监听数组哪个操作:

A. push B. pop C. 通过下标修改 arr[0]=1 D. shift 答案:C

3. 判断Vue2 computed 有缓存,依赖不变不会重新计算。()

答案:对

4. 选择Vue2 父子组件通信,子传父用:

A. props B. $emit C. provide/inject D. vuex 答案:B

5. 选择Vue2 生命周期中,DOM 渲染完成在:

A. created B. beforeMount C. mounted D. beforeUpdate 答案:C

6. 判断Vue2 给对象新增属性,必须用 Vue.set 才能响应式。()

答案:对

7. 选择Vue2 路由跳转不留下历史记录:

A. push B. replace C. go D. link 答案:B

8. 手写Vue2 中实现一个防抖指令,限制按钮 500ms 内重复点击。

答案

Vue.directive('debounce', {
  inserted(el,binding){
    let timer
    el.addEventListener('click',()=>{
      clearTimeout(timer)
      timer = setTimeout(()=>{
        binding.value()
      },500)
    })
  }
})

三、Vue3 部分(8题)

1. 选择Vue3 响应式核心是:

A. Object.defineProperty B. Proxy C. setter D. getter 答案:B

2. 选择Vue3 组合式 API 入口是:

A. created B. setup C. beforeCreate D. render 答案:B

3. 选择获取路由参数 useRoute 所在包是:

A. vue B. vue-router C. @vue/runtime D. vuex 答案:B

4. 判断Vue3 支持 Fragment,组件可多个根节点。()

答案:对

5. 选择Vue3 中定义基本类型响应式用:

A. reactive B. ref C. computed D. watch 答案:B

6. 选择Vue3 中清除响应式监听用:

A. stop B. clear C. destroy D. off 答案:A

7. 判断 Vue3 中 reactive 不能直接赋值,否则丢失响应式。()

答案:对

8. 手写题 Vue3 setup 中监听对象深层变化,并在变化后执行请求。

答案

import { watch } from 'vue'
setup(){
  const obj = reactive({info:{name:'test'}})
  watch(()=>obj.info,()=>{
    // 发起请求
  },{deep:true})
  return { obj }
}

四、其他综合部分(10题,CSS / 浏览器 / 工程化 / 网络)

1. CSS 选择以下居中方案不需要知道子元素宽高的是:

A. margin:auto B. flex 居中 C. 定位+负margin D. table-cell 答案:B

2. CSS 选择选择器权重最高的是:

A. #app .box B. .list #item C. div p D. style内联 答案:D

3. 304 状态码含义:

A. 永久重定向 B. 资源未修改,使用缓存 C. 客户端错误 D. 服务器错误 答案:B

4. 关闭页面即清除,存储约5M,不随请求发送:

A. cookie B. localStorage C. sessionStorage D. indexedDB 答案:C

5. 跨域题 Vue 开发环境跨域常用方案:

A. CORS B. devServer proxy C. JSONP D. postMessage 答案:B

6. 构建工具题 Vite 开发模式基于:

A. CommonJS B. ES Module C. UMD D. AMD 答案:B

7. 浏览器题 宏任务不包括:

A. setTimeout B. Promise.then C. ajax D. script 答案:B

8. 性能题 不属于首屏优化的是:

A. 路由懒加载 B. 图片懒加载 C. 代码压缩 D. 增加全局变量 答案:D

9. 浏览器题 addEventListener 第三个参数为 true 表示:

A. 冒泡 B. 捕获 C. 只执行一次 D. 阻止默认 答案:B

10. 手写题 实现函数防抖(debounce)。

答案

function debounce(fn,delay){
  let timer = null
  return function(){
    clearTimeout(timer)
    timer = setTimeout(()=>fn.apply(this,arguments),delay)
  }
}

总结

  1. 闭卷自测,再对答案,错题重点标注
  2. JS 重点:EventLoop、parseInt 坑、引用类型、深拷贝、闭包
  3. Vue2 重点:响应式缺陷、生命周期、通信、数组监听
  4. Vue3 重点:Proxy、setup、ref/reactive、组合API
  5. 综合重点:居中、跨域、缓存、构建工具、性能优化