前端题总集

227 阅读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. 多手写代码验证知识点,避免纸上谈兵

面试三

一、不定项选择题

1. 关于 HTTP 响应码

正确答案:A、C

  • A. 400:请求出现错误 ✅(客户端请求参数/格式错误)
  • B. 403:请求的内容不存在 ❌(403 是禁止访问,404 才是资源不存在)
  • C. 304:请求的资源并没有被修改过 ✅(协商缓存,服务器告知客户端使用本地缓存)
  • D. 301:请求成功,但结果有多种选择 ❌(301 是永久重定向,300 才是多种选择)

2. 正则与类型判断

var a = /678/, b = /678/;
a == b; // false
a === b; // false

正确答案:B(false false) 解析:正则表达式是对象,==/=== 比较的是引用地址,两个独立正则对象地址不同,故均为 false

3. 取模运算类型转换

var a = "40", var b = 7;
a % b; // 5

正确答案:C(5) 解析:JS 会自动将字符串 "40" 转为数字 40,执行 40 % 7 = 5,结果为数字 5

4. CSS position 定位

正确答案:无完全正确选项,最接近为 B(需修正)

  • 绝对定位:absolute → 相对于最近的有定位的父元素
  • 相对定位:relative → 相对于自身原位置
  • 固定定位:fixed → 相对于浏览器窗口 题目表述存在歧义,若按选项理解:
    • A 选项描述 absolute 正确,但未说明 relative
    • B 选项 fixed 描述正确,但未对应相对定位
    • D 选项 relative 描述正确,但未对应绝对定位

5. map + parseInt 陷阱

["1", "2", "3"].map(parseInt);
// 结果:[1, NaN, NaN]

正确答案:A 解析:parseInt 接收两个参数(值、进制),map 会传入 (item, index, array),实际执行:

  • parseInt("1", 0) → 1
  • parseInt("2", 1) → NaN(进制 1 无效)
  • parseInt("3", 2) → NaN(二进制中 3 无效)

6. substring 与 slice 适用范围

正确答案:D

  • substring:仅可用于字符串
  • slice:可用于字符串和数组

二、判断题

  1. Cookie 未设置有效期,浏览器关闭后 cookie 还是存在的(会话级 Cookie 会在浏览器关闭后删除)
  2. typeof(Null) === 'undefined'typeof null === 'object',且 Null 不是合法标识符,应为 null
  3. HTTP2 多路复用:在一个 TCP 连接中并行传输多个 HTTP 请求/响应,避免了 HTTP1.x 的队头阻塞问题,提升传输效率。

三、解答题

1. Vue2/Vue3 响应式原理区别

维度Vue2Vue3
实现Object.defineProperty 劫持对象属性Proxy 代理整个对象
数组监听重写数组原型方法,无法监听 length/索引变化原生支持数组所有操作监听
新增属性Vue.set() 手动监听自动监听对象新增/删除属性
性能递归遍历所有属性,初始化开销大惰性代理,访问时才劫持,性能更优
支持类型仅对象/数组支持 Map/Set/WeakMap 等更多类型

2. 代码执行顺序 + 多请求方案

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')
}, 0)
console.log('6')

执行顺序:1 → 2 → 3 → 6 → 4 → 5

  • 同步任务:1236
  • 微任务:Promise.then4
  • 宏任务:setTimeout5

发起多个请求的方案

  • Promise.all():所有请求完成后统一处理
  • Promise.race():第一个完成的请求先处理
  • Promise.allSettled():所有请求完成(无论成功/失败)后处理

3. JS 实现 10-100 随机数数组并排序

// 生成 10 个 10~100 之间的随机整数
const arr = Array.from({ length: 10 }, () => 
  Math.floor(Math.random() * 91) + 10
);
// 升序排序
arr.sort((a, b) => a - b);
console.log(arr);

四、选择题

1. 动态改变层内容的方法

正确答案:A、B、C、D(全选)

  • A. innerHTML:直接修改 HTML 内容
  • B. innerText:修改纯文本内容
  • C. 隐藏/显示层:视觉上改变内容展示
  • D. display 属性:控制元素显示/隐藏

2. 图片模拟提交按钮

正确答案:A 解析:图片没有 onSubmit 事件,需在 onClick 中手动调用 form.submit() 提交表单。

3. CSS 选择器权重排序

选择器权重规则:内联样式 > ID 选择器 > 类/属性/伪类选择器 > 元素/伪元素选择器

  • a) .list .box p → 类+类+元素 → (0,2,1)
  • b) #list .box div span → ID+类+元素+元素 → (1,1,2)
  • c) .list span → 类+元素 → (0,1,1)
  • d) #list #box → ID+ID → (2,0,0)
  • e) p:last-child → 元素+伪类 → (0,1,1)
  • f) style(内联样式)→ (1,0,0,0)

排序结果:f > d > b > a > c = e正确答案:C

4. 数组声明错误选项

正确答案:C

  • var arr[]=new Array(3)(4) → 语法错误,数组声明不能写 [] 赋值
  • 其他选项:A/B/D 均为合法数组声明方式

5. map + parseInt 陷阱(同轻喜到家第5题)

正确答案:A([1, NaN, NaN])

6. 不属于 document 对象的方法

正确答案:D

  • bgColor() 不是 document 方法,document.bgColor 是旧版属性,已废弃
  • A/B/C 均为 document 标准方法

7. 不是 canvas 的方法

正确答案:D

  • controller 不是 canvas 方法,getContext()/fill()/stroke() 是 canvas 核心绘图方法

8. 变量提升与作用域

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

正确答案:A 解析:函数内 var name 存在变量提升,if 判断时 nameundefined,进入 if 分支赋值为 Jack

9. setTimeout 用法

setTimeout("check", 10)

正确答案:D 解析:setTimeout 第二个参数是延迟毫秒数,10 毫秒后执行 check 函数一次,不是循环执行。

10. typeof null

var temp = null;
alert(typeof temp); // "object"

正确答案:B 解析:typeof null 返回 "object" 是 JS 历史遗留 bug。


五、问答题

1. 同步和异步的区别

  • 同步:代码按顺序执行,需等待前一个任务完成才执行下一个,会阻塞主线程
  • 异步:不等待前一个任务完成,直接执行后续代码,异步任务完成后通过回调/Promise 处理结果,不阻塞主线程

2. CSS 动画和 JS 动画的区别

维度CSS 动画JS 动画
实现基于 @keyframes/transition,由浏览器 GPU 加速基于 JS 定时器/requestAnimationFrame 操作 DOM
性能性能更优,浏览器优化渲染,避免 JS 主线程阻塞性能相对较低,频繁操作 DOM 可能导致重绘/重排
控制粒度控制粒度较粗,仅能定义关键帧控制粒度精细,可动态调整动画参数
适用场景简单过渡、循环动画复杂交互、动态逻辑动画

3. 优雅降级和渐进增强

  • 优雅降级:先构建完整功能的现代版网站,再针对低版本浏览器做兼容处理,保证核心功能可用
  • 渐进增强:先构建基础功能的核心版网站,再针对现代浏览器逐步增强交互和视觉效果

4. 网页字体使用奇数还是偶数

推荐使用偶数字号

  • 原因:浏览器渲染时,偶数字号在不同设备上更清晰,避免因像素对齐问题导致字体模糊;奇数字号在部分设备(如 Retina 屏)可能出现边缘锯齿。

5. 虚拟 DOM 实现原理

  1. 用 JS 对象模拟真实 DOM 树(虚拟 DOM 树)
  2. 状态变化时,生成新的虚拟 DOM 树
  3. 通过 Diff 算法对比新旧虚拟 DOM 树,找出差异
  4. 将差异批量更新到真实 DOM 树,减少重绘/重排次数,提升性能

6. Vue 路由跳转方式

  1. <router-link to="path"> 标签式跳转
  2. this.$router.push(path) 编程式跳转(保留历史记录)
  3. this.$router.replace(path) 编程式跳转(替换当前历史记录)
  4. this.$router.go(n) 前进/后退 n 步
  5. this.$router.back() 后退一步
  6. this.$router.forward() 前进一步

7. Vue 中实现跨域

  • 开发环境:配置 vue.config.jsdevServer.proxy 代理请求
  • 生产环境
    • Nginx 反向代理
    • JSONP(仅支持 GET 请求)
    • CORS(服务器端配置 Access-Control-Allow-Origin
    • postMessage(跨窗口通信)

8. Vue 中引入 jQuery

  1. 安装:npm install jquery --save
  2. 全局引入:在 main.jsimport $ from 'jquery',并挂载到 Vue 原型 Vue.prototype.$ = $
  3. 组件内引入:import $ from 'jquery' 直接使用

9. Vue-Router 动态路由

  • 定义动态路由{ path: '/user/:id', component: User }
  • 获取动态参数
    • 组件内:this.$route.params.id
    • 模板中:$route.params.id
    • 组合式 API:import { useRoute } from 'vue-router'; const route = useRoute(); route.params.id

10. Vue3 特性了解

  • 响应式系统:基于 Proxy 实现,性能更优,支持更多数据类型
  • 组合式 APIsetup() 替代 Options API,逻辑复用更灵活
  • Tree-Shaking 优化:按需引入,打包体积更小
  • Fragment/Teleport/Suspense 新组件
  • 更好的 TypeScript 支持
  • 性能提升:编译优化、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. 综合重点:居中、跨域、缓存、构建工具、性能优化