跳到主要内容JavaScript大前端算法
前端核心面试题与实战指南
涵盖前端面试核心知识点,包括闭包原理、事件循环机制、BFC 布局、内存泄漏排查、Vue 响应式与虚拟 DOM 原理、ES6 新特性、HTTP 缓存策略及性能优化方案。内容从基础语法到架构模式,结合代码示例解析常见陷阱与解决方案,适合求职者系统复习或开发者查漏补缺。
道系青年5 浏览 前端核心面试题与实战指南
闭包
定义
闭包(Closure) 是指一个函数能够访问并记住其外部作用域中的变量,即使外部函数已经执行完毕。闭包由两部分组成:
- 一个函数(通常是内部函数)。
- 该函数被创建时所在的作用域(即外部函数的变量环境)
function outer() {
let count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
const counter = outer();
counter();
counter();
核心原理
- 作用域链:函数在定义时,会记住自己的词法环境(即外部作用域)。当内部函数访问变量时,会沿着作用域链向上查找。
- 变量持久化:闭包使得外部函数的变量不会被垃圾回收,因为内部函数仍持有对它们的引用。
常见用途
私有变量封装
通过闭包隐藏内部变量,仅暴露操作接口:
function createCounter() {
let count = 0;
return {
increment: () => count++,
getValue: () => count
};
}
const counter = createCounter();
counter.increment();
console.log(counter.getValue());
函数柯里化(Currying)
function add(a) {
return function(b) {
return a + b;
};
}
const add5 = add(5);
console.log(add5(3));
事件处理与回调
function setupButton() {
const button = document.getElementById('myButton');
let clicks = 0;
button.addEventListener('click', function() {
clicks++;
console.log(`按钮被点击了 ${clicks} 次`);
});
}
陷阱与解决方案
循环中的闭包问题
问题:循环中创建的闭包共享同一个变量,导致意外结果。
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
解决方案:使用 IIFE 或 let 创建块级作用域。
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 100);
})(i);
}
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 100);
}
内存泄漏
问题:闭包长期持有外部变量引用,导致内存无法释放。
function heavyProcess() {
const largeData = new Array(1000000).fill('data');
return function() {
console.log(largeData.length);
};
}
const leak = heavyProcess();
事件循环(Event Loop)
定义
事件循环是 JavaScript 处理异步任务的核心机制。由于 JavaScript 是单线程语言,事件循环通过任务队列(Task Queue)和调用栈(Call Stack)的协作,实现了非阻塞的异步执行模型。
核心概念
- 调用栈(Call Stack):用于存储函数调用的栈结构,遵循'后进先出'原则。
- 任务队列(Task Queue):用于存储异步任务的回调函数,分为宏任务队列和微任务队列。
- 宏任务(Macro Task)与微任务(Micro Task):
- 宏任务:包括
setTimeout、setInterval、I/O 操作、UI 渲染等。
- 微任务:包括
Promise.then、MutationObserver、process.nextTick(Node.js)等。
执行流程
- 同步任务执行:直接进入调用栈执行,直到调用栈为空。
- 微任务执行:调用栈为空后,检查微任务队列,依次执行所有微任务。
- 宏任务执行:从宏任务队列中取出一个任务执行,执行完毕后再次检查微任务队列。
- UI 渲染:浏览器在宏任务执行后执行渲染操作。
示例
console.log('1');
setTimeout(() => {
console.log('2');
}, 0);
Promise.resolve().then(() => {
console.log('3');
});
console.log('4');
应用场景
- 异步编程:通过
Promise、async/await 处理异步任务。
- 性能优化:将耗时任务拆分为多个微任务,避免阻塞主线程。
- 动画与渲染:使用
requestAnimationFrame 结合事件循环实现流畅动画。
BFC(块级格式化上下文)
定义
BFC(Block Formatting Context)是 Web 页面渲染时的一种布局环境,是一个独立的渲染区域,内部的元素布局不会影响外部元素。
触发条件
- 根元素(
<html>)。
float 值不为 none。
position 值为 absolute 或 fixed。
display 值为 inline-block、table-cell、flex、grid 等。
overflow 值不为 visible(如 hidden、auto、scroll)。
特性与应用
- 内部元素垂直排列:BFC 内部的块级元素按垂直方向依次排列。
- 避免外边距重叠:阻止相邻元素的外边距(margin)重叠。
- 包含浮动元素:避免父元素高度塌陷。
- 阻止元素被浮动元素覆盖:BFC 区域不会与浮动元素重叠。
.parent { overflow: hidden; }
内存泄漏
定义
内存泄漏(Memory Leak)是指程序中已不再使用的内存未被释放,导致内存占用持续增加。在 JavaScript 中,通常由不当的引用管理引起。
常见场景
- 未释放的缓存或 Map:缓存对象未及时清理。
- DOM 引用未清除:保存了 DOM 元素的引用,即使元素被移除,内存也无法释放。
- 闭包引用:闭包保留对外部作用域的引用。
- 未清理的定时器:定时器或事件监听器未及时清除。
- 意外全局变量:未使用
var、let 或 const 声明的变量挂载到全局对象。
排查与避免
- 工具检测:使用 Chrome DevTools 的 Memory 面板分析 Heap Snapshot。
- 最佳实践:清除定时器、事件监听器;使用
WeakMap 或 WeakSet 存储临时数据;避免在闭包中保留不必要的引用。
Vue 的虚拟 DOM
工作原理
- 生成虚拟 DOM:Vue 将模板编译为渲染函数,生成虚拟 DOM 树。
- Diff 算法:对比新旧虚拟 DOM 树,找出差异。
- 更新真实 DOM:根据差异应用变化,完成视图更新。
优点
- 性能优化:减少直接操作真实 DOM 的次数。
- 跨平台能力:抽象层可映射到不同平台。
- 简化开发:关注数据逻辑,无需手动操作 DOM。
MVVM
定义
MVVM(Model-View-ViewModel)是一种软件架构模式,分离 UI 逻辑与业务逻辑。
- Model:数据模型,管理数据和业务逻辑。
- View:视图,负责呈现 UI。
- ViewModel:连接 View 和 Model,处理 UI 逻辑和数据绑定。
核心概念
- 数据绑定:View 和 ViewModel 双向通信。
- 命令绑定:用户操作触发 ViewModel 方法。
- 依赖注入:解耦 ViewModel 与外部服务。
Vue2 与 Vue3 响应式原理
Vue2
使用 Object.defineProperty 实现响应式,通过劫持对象的属性定义 getter 和 setter。局限性在于无法检测新增/删除属性,数组响应式需重写方法。
Vue3
使用 Proxy 实现响应式,代理整个对象,拦截所有操作。优势在于全面拦截、性能提升且代码更简洁。
深拷贝与浅拷贝
区别
- 浅拷贝:只复制第一层属性,引用类型共享地址。
- 深拷贝:递归复制所有层级,完全独立。
实现方式
- 浅拷贝:
slice、concat、Object.assign、扩展运算符 ...。
- 深拷贝:
JSON.parse(JSON.stringify())(有局限)、第三方库 lodash.cloneDeep、递归实现。
npm 依赖管理
开发依赖 vs 生产依赖
- devDependencies:仅在开发环境使用(如构建工具、测试框架),不发布到生产环境。
- dependencies:项目运行必需依赖,随项目发布。
版本号符号
^:允许更新次版本和修订版本(兼容变更)。
~:仅允许更新修订版本(修复 bug)。
ES6 模块化
ES6 引入 import 和 export 关键字,支持静态加载、独立作用域和严格模式。相比 CommonJS 的 require,ES6 模块在编译时确定依赖关系,支持 Tree-shaking。
Vue 中 key 的作用
key 用于唯一标识虚拟 DOM 节点,帮助 Vue 识别节点变化,优化渲染性能。列表渲染中不建议使用 index 作为 key,因为索引变化会导致节点复用错误和状态混乱,应使用唯一 ID。
CSS 选择器优先级
优先级规则(从高到低):内联样式 > ID 选择器 > 类/属性/伪类选择器 > 元素/伪元素选择器。相同权重时,后定义的样式覆盖前面的。!important 可覆盖所有优先级,但应谨慎使用。
JavaScript 阻塞问题
JavaScript 是单线程,长时间运行的同步任务会阻塞主线程。解决方法包括使用异步 API(setTimeout、Promise)、Web Workers 后台线程、任务拆分及 requestAnimationFrame 优化渲染。
Promise 功能与用法
Promise 解决回调地狱,提供链式调用。状态包括 Pending、Fulfilled、Rejected。常用静态方法有 all、race、allSettled 等。
大量数据处理策略
- 加载:分页、懒加载。
- 处理:Web Workers、分批处理、高效算法。
- 存储:TypedArray、IndexedDB。
- 渲染:虚拟列表、减少 DOM 操作。
兼容性处理
- 浏览器:Polyfill、Autoprefixer、Babel。
- 设备:媒体查询、Flexbox/Grid。
- 操作系统:字体回退、路径规范。
CSS 绘制椭圆
使用 border-radius: 50% 将矩形变为椭圆,或使用 clip-path: ellipse() 裁剪路径,以及 SVG 绘制。
setTimeout 与 setInterval
- setTimeout:延迟执行一次,设为 0 时放入宏任务队列等待下一轮。
- setInterval:周期性执行,需注意回调堆积问题。
性能指标与检测
核心指标包括 FCP、LCP、TBT、CLS。工具包括 Lighthouse、Chrome DevTools Performance 面板、React Profiler 等。
HTTP 状态码
分为 1xx(信息)、2xx(成功)、3xx(重定向)、4xx(客户端错误)、5xx(服务器错误)。常见如 200 OK、404 Not Found、500 Internal Server Error。
箭头函数与普通函数
箭头函数没有自己的 this,继承外层作用域;不能作为构造函数;无 arguments 对象。普通函数 this 指向调用者,可作为构造函数。
防抖与节流
- 防抖(Debounce):事件停止触发后执行,适用于搜索框输入。
- 节流(Throttle):固定频率执行,适用于滚动事件。
宏任务与微任务
宏任务优先级低(如 setTimeout),微任务优先级高(如 Promise)。事件循环先执行完当前宏任务的所有微任务,再执行下一个宏任务。
跨域问题
同源策略限制跨域请求。解决方案包括 CORS、JSONP、代理服务器、Nginx 反向代理、PostMessage 等。
提高加载速度
压缩资源、使用 CDN、减少请求次数(合并文件、雪碧图)、代码分割、Tree Shaking、缓存优化(Service Worker)。
页签消息传递
使用 localStorage(storage 事件)、BroadcastChannel、SharedWorker 或 window.open + postMessage。
元素水平居中
行内元素用 text-align: center;块级元素可用 Flexbox (justify-content: center)、Grid (place-items: center)、绝对定位 + transform 或 margin 0 auto。
let、const 与 var
- var:函数作用域,可提升,可重复声明。
- let/const:块级作用域,存在暂时性死区,不可重复声明。
作用域与作用域链
作用域决定变量访问范围,作用域链是变量查找机制。闭包基于作用域链形成。
JavaScript 继承
原型链继承、构造函数继承、组合继承、寄生组合式继承(推荐)、ES6 class extends。
缓存与持久化
HTTP 缓存(强缓存/协商缓存)、LocalStorage、SessionStorage、IndexedDB、Service Worker。
require 与 import
CommonJS 的 require 是动态同步加载;ES6 的 import 是静态异步加载,支持 Tree-shaking。
px、em 与 rem
- px:绝对单位。
- em:相对当前元素字体大小。
- rem:相对根元素字体大小,适合全局布局。
盒模型
标准盒模型(width 仅内容)与 IE 盒模型(width 含 padding/border)。推荐使用 box-sizing: border-box。
ES6 新特性
变量声明、箭头函数、模板字符串、解构赋值、默认参数、扩展运算符、类、模块化、Promise、Symbol 等。
HTTP 缓存
强缓存(Cache-Control、Expires)不发送请求;协商缓存(ETag、Last-Modified)发送请求验证。
Vue Router 模式
Hash 模式(URL 含 #,兼容性好)与 History 模式(URL 美观,需服务器配置)。
JavaScript 缺点
单线程阻塞、弱类型易错、兼容性差异、安全风险(XSS/CSRF)、调试困难、生态碎片化。
原型与原型链
每个对象都有原型,通过原型链查找属性。__proto__ 指向原型对象,prototype 是构造函数的原型属性。
XSS 与 CSRF
- XSS:注入恶意脚本。防御:输入过滤、输出编码、CSP。
- CSRF:伪造请求。防御:Token、SameSite Cookie、Referer 检查。
HTTP 详解
请求/响应结构、方法(GET/POST/PUT/DELETE)、状态码、版本演进(1.0/1.1/2/3)。
分片(Chunking)
将大数据集或任务分割成小块处理,优化性能和内存。包括数组分片、文件分片、任务分片等。
懒加载原理
延迟加载非关键资源,直到进入可视区域。实现方式包括 scroll 监听、Intersection Observer API。
脱离文档流
position: absolute/fixed、float、display: none 使元素脱离文档流,不影响其他元素布局。
堆与栈
栈存储基本类型和调用栈,速度快空间小;堆存储引用类型,空间大速度慢,由 GC 管理。
v-model 原理
语法糖,本质是 v-bind:value + v-on:input,实现双向绑定。
Vue 组件通信
props/$emit(父子)、Event Bus(兄弟)、provide/inject(跨层级)、Vuex(全局)、$refs(直接访问)。
Diff 算法
比较新旧虚拟 DOM 树,同层比较,利用 key 优化列表更新,最小化 DOM 操作。
Webpack 配置
入口(Entry)、输出(Output)、加载器(Loader)、插件(Plugin)、模式(Mode)。支持多入口、热更新、代码压缩等。
URL 到网页呈现
URL 解析 -> DNS 解析 -> TCP 连接 -> HTTP 请求 -> 服务器处理 -> 接收响应 -> 解析渲染(DOM/CSSOM/Render Tree)-> JS 执行。
前端优化方法
减少 HTTP 请求、使用缓存、优化资源加载(懒加载/预加载)、压缩代码、优化图片、优化渲染性能、SEO 优化。
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online