说在前面
"八股文"是程序员们对技术面试中那些经典、高频、基础问题的戏称。掌握它们不一定能让你成为大神,但绝对是通关面试的基石。以下内容整合了项目经验、框架原理、浏览器机制等多方面核心知识,用通俗易懂的方式帮你快速梳理记忆。
一、编程基础与核心
1. 作用域与闭包
-
**闭包是啥?** 一个能读取其他函数内部变量的函数。你可以把它想象成一个函数带着它出生的那个环境(作用域)一起"背包旅行"。
-
有啥用? 主要用来封装私有变量。在JS中,局部变量无法长期保存且不污染全局,闭包能创建一个持久的、私有的数据空间。
-
简单场景: 函数防抖/节流、模拟私有方法、在循环中正确绑定异步事件(经典的
for循环内setTimeout打印i的问题)。
2. 事件循环
JS是单线程,但异步操作靠事件循环机制来不"堵车"。
-
同步任务直接在主线程执行,形成"执行栈"。
-
异步任务 (如
setTimeout、Promise、ajax)会被放到"任务队列"里排队。 -
当"执行栈"空了,系统就会去"任务队列"里看看有什么可以执行的,把它拿到主线程执行。这个过程是循环不断的,所以叫事件循环。
-
微任务 vs 宏任务:任务队列还分VIP通道和普通通道。
-
微任务 (VIP):
Promise.then,process.nextTick等。一次事件循环中,执行栈清空后,会立即执行所有微任务。 -
宏任务 (普通):
setTimeout,setInterval,I/O等。一次事件循环执行一个宏任务,然后检查并执行所有微任务,如此循环。
-
3. 数据类型与检测
-
基本类型 :
String,Number,Boolean,Undefined,Null,Symbol,BigInt。存在栈内存,直接存值。 -
引用类型 :
Object(包含Array,Function,Date等)。存在堆内存,栈内存中存的是堆内存的地址(引用)。 -
检测方法:
-
typeof:能检测基本类型(null会返回object是个历史Bug),引用类型除function外都返回object。 -
instanceof:检测构造函数的prototype是否在对象的原型链上。只能用于引用类型。 -
Object.prototype.toString.call():最准!返回[object Xxx]。
-
4. 原型与new
-
原型 :每个JS对象(除
null)都有__proto__属性,指向它的构造函数的prototype属性。prototype本身也是一个对象,它有个constructor属性指回构造函数。 -
原型链 :访问对象属性时,如果自身没有,就通过
__proto__去它的原型上找,还找不到就去原型的原型上找,直到null。这条链就是原型链,是JS实现继承的基础。 -
new干了啥?-
创建一个新对象。
-
把这个新对象的
__proto__链接到构造函数的prototype。 -
将构造函数内部的
this绑定到这个新对象,并执行构造函数代码(为新对象添加属性)。 -
如果构造函数返回了一个对象,则返回这个对象;否则返回刚创建的新对象。
-
二、框架原理(Vue/React)
1. Vue
-
Vue2 vs Vue3 核心区别:
-
响应式原理 :Vue2用
Object.defineProperty,对数组和对象深层属性监听有局限;Vue3用Proxy,拦截能力更强,性能更好。 -
组合式API :Vue3的
setup函数和组合式API (ref,reactive,computed,watch等),让逻辑组织和复用更灵活,告别options API的"跳来跳去"。 -
生命周期 :
beforeCreate/created被setup替代。其他钩子名前加on,如onMounted。 -
更多 :
Fragment(多根节点)、Teleport、Suspense、更好的Tree-Shaking支持。
-
-
计算属性 vs 侦听器:
-
computed:计算一个值,有缓存,依赖变化才重新计算。适合模板中依赖其他数据的复杂逻辑。 -
watch:观察一个值的变化,执行副作用(如发请求、操作DOM)。可以执行异步操作,更强大。
-
-
data为什么是函数? 如果data是对象,所有组件实例将共享引用同一个数据对象,一个组件改数据,全变了!函数每次返回全新的对象,保证每个实例数据独立。 -
keep-alive原理 :它是一个抽象组件,自身不渲染DOM。包裹动态组件时,会将不活动的组件实例缓存在内存中,而不是销毁。通过include/exclude控制缓存,通过activated/deactivated两个生命周期钩子通知组件"激活/停用"。 -
Vue路由权限:
-
前端控制 :登录后获取用户权限列表。定义路由时添加
meta: { roles: ['admin'] }元信息。在全局路由守卫router.beforeEach中,检查目标路由所需的权限是否包含在用户权限列表中。 -
后端控制 :登录后,后端直接返回该用户有权限访问的菜单树数据 。前端根据这个数据动态生成路由表(
router.addRoute)。
-
2. React
-
函数组件 vs 类组件:
-
函数组件:无状态(过去),逻辑简单,性能好。React 16.8后有了Hooks,也能有状态和生命周期。
-
类组件 :有
this,有生命周期,有内部状态state。语法更冗长。 -
趋势:Hooks是未来,函数组件为主流。
-
-
React更新机制:
-
触发更新 :
setState、props变化、forceUpdate。 -
调度:React的调度器(Scheduler)会根据优先级安排更新任务。
-
调和 :Reconciler(Fiber架构核心)对比新旧虚拟DOM树(
ReactElement构成的Fiber树),找出差异(Diffing Algorithm)。 -
提交:Renderer将差异应用到真实DOM上,完成视图更新。
-
三、浏览器与网络
1. 输入URL到页面显示
-
URL解析:解析协议、域名、路径。
-
DNS查询:将域名解析为IP地址(有缓存则用缓存)。
-
建立TCP连接:与服务器进行"三次握手"。
-
发起HTTP请求:浏览器发送请求报文。
-
服务器响应:服务器处理请求,返回响应报文(HTML、CSS、JS等)。
-
解析与渲染:
-
解析HTML,构建DOM树。
-
解析CSS,构建CSSOM树。
-
遇到
<script>会阻塞解析(除非有async/defer)。 -
合并DOM和CSSOM,形成渲染树。
-
布局:计算每个节点的确切位置和大小。
-
绘制:将渲染树转换为屏幕上的像素。
-
-
断开TCP连接:"四次挥手"。
2. 跨域与解决方案
同源策略:协议、域名、端口三者必须一致。跨域主要是浏览器的安全限制。
-
解决方案:
-
CORS :最主流。服务器设置响应头
Access-Control-Allow-Origin。 -
代理 :开发时用
webpack-dev-server的proxy,生产时用Nginx反向代理。 -
JSONP :利用
<script>标签无跨域限制的特性,但只支持GET。
-
3. 缓存策略
-
强缓存 :浏览器直接读本地缓存,不发请求。HTTP 1.1用
Cache-Control(max-age), HTTP 1.0用Expires。 -
协商缓存 :浏览器询问服务器资源是否过期。用
Last-Modified/If-Modified-Since或ETag/If-None-Match。返回304状态码则用缓存。
4. HTTP状态码
-
2xx 成功 :
200 OK,204 No Content,206 Partial Content。 -
3xx 重定向:
-
301 Moved Permanently:永久重定向,域名已变更。 -
302 Found:临时重定向,搜索引擎不记新URL。 -
304 Not Modified:协商缓存命中,资源未修改。
-
-
4xx 客户端错误:
-
400 Bad Request:请求语法错误。 -
401 Unauthorized:需要身份验证。 -
403 Forbidden:服务器理解请求但拒绝执行。 -
404 Not Found:资源不存在。
-
-
5xx 服务端错误:
-
500 Internal Server Error:服务器内部错误。 -
502 Bad Gateway:网关错误。 -
503 Service Unavailable:服务暂时不可用。
-
5. HTTP 与 HTTPS
-
HTTP:明文传输,不安全,端口80。
-
HTTPS:HTTP + SSL/TLS加密,需要CA证书,端口443。建立连接有更复杂的"握手"过程,保证传输安全。
四、性能与安全
1. 性能优化
-
加载时优化:
-
减少请求:雪碧图、代码合并、资源内联。
-
减小体积:代码压缩、Tree Shaking、图片压缩(WebP)、Gzip。
-
缓存:强缓存+协商缓存。
-
异步/延迟加载 :
async/defer,路由懒加载,图片懒加载。 -
CDN加速。
-
-
运行时优化:
-
减少重排重绘 :
transform/opacity,避免频繁操作样式,分离读写操作。 -
防抖与节流 :控制高频事件(
scroll,resize,input)的回调频率。 -
虚拟列表:只渲染可视区域内的列表项,应对长列表。
-
合理使用
keep-alive。
-
2. 前端安全
-
XSS:跨站脚本攻击。攻击者将恶意脚本注入到网页中,在用户浏览时执行。
- 防御 :对用户输入进行转义(
<转成<)、使用Content-Security-Policy头、避免使用innerHTML, 用textContent。
- 防御 :对用户输入进行转义(
-
CSRF:跨站请求伪造。攻击者诱导用户在已登录的A网站中,访问恶意B网站,B网站冒用用户在A的登录状态发起请求。
- 防御 :使用
SameSiteCookie属性、验证Referer/Origin头、添加CSRF Token。
- 防御 :使用
五、工程与工具
1. Webpack基础概念
-
Loader :文件加载器。将非JS模块(如CSS、图片、TypeScript)转换为webpack能处理的模块。"翻译官"。
-
Plugin :插件。在webpack构建的生命周期中广播事件,执行更广泛的任务(如打包优化、资源管理、环境变量注入)。"功能扩展包"。
2. Git常用命令
git clone <url> # 克隆
git add . # 添加所有更改到暂存区
git commit -m "msg" # 提交
git pull origin master # 拉取远程更新
git push origin master # 推送
git branch # 查看分支
git checkout -b feat-xx # 创建并切换分支
git merge feat-xx # 合并分支
git stash # 暂存当前修改
git stash pop # 恢复暂存
3. 前端鉴权与登录流程
-
用户提交登录信息。
-
后端验证成功,返回
Token(如JWT)和用户信息。 -
前端将
Token存储在localStorage/sessionStorage/Cookie中,将用户信息存入Vuex/Redux。 -
后续每次请求API,在请求头(如
Authorization)中携带Token。 -
前端通过路由守卫检查访问权限,无
Token或Token失效则跳转登录页。
4. 首屏加载优化
-
代码层面:路由懒加载、组件异步加载、第三方库CDN引入、Tree Shaking、合理分包。
-
资源层面:图片懒加载/压缩/转WebP、开启Gzip压缩、开启HTTP/2。
-
缓存层面:合理配置强缓存与协商缓存。
-
服务端层面:SSR(服务端渲染)或预渲染。
面试小贴士
-
项目难题 :准备好1-2个真实、具体、有深度的"bug故事",突出定位问题、分析原因、解决方案、复盘收获的完整过程。自信讲述,逻辑清晰。
-
封装组件 :举例说明封装的场景、设计思路(Props/Events/Slots)、遇到的问题、带来的好处。比如:封装一个可复用的数据表格、弹窗、上传组件。
-
权限管理 :能清晰说出路由权限 和按钮/菜单权限在前后端分别如何实现,以及各自的优缺点。
-
职业规划 :表达出稳定性、持续学习、业务贡献、技术纵深的意愿,与公司的发展方向相结合。
这份"八股文"清单,基本覆盖了前端初中级面试的技术核心。理解其原理,而不仅仅是背诵,才能在面试中应对自如,也能在日常开发中游刃有余。祝大家面试顺利!