Skip to content

附录 A1 · 手写题合集(30 道高频)

一句话开篇:手写题是前端面试的"基本功大考"。同样一段 Promise.all,能不能 30 行内手敲出来,直接区分初级、中级和高级前端。本章把 30 道高频手写题一次性梳理清楚——题目、思路、递进版本、复杂度、加分点全部到位。


0. 生活类比:手写题是"厨师颠勺"

把前端面试想象成厨师面试:

  • 概念题(什么是闭包?)= 让你说清"煎炒烹炸"的定义
  • 场景题(怎么设计权限系统?)= 让你描述一桌满汉全席怎么安排
  • 手写题(手写一个 debounce)= 让你当场颠一下勺——动作变形不变形,一眼就能看出来

颠勺漂亮的厨师不一定能开餐厅,但开餐厅的大厨必然颠勺漂亮


1. 面试为什么爱考手写题?

维度手写题能暴露什么
基础扎不扎实闭包、this、原型链、Promise 状态机这些概念,敢不敢、能不能落地成代码
API 熟不熟flat 不会用 concat、写 bind 不知道 Symbol,立马露怯
思维清不清晰能不能从"简单版 → 完整版 → 进阶版"逐层递进,体现工程素养
边界考不考虑防抖立即执行模式、深拷贝循环引用、Promise 多次 resolve、bind 配合 new ……都是基本盘
代码风不风骚同样实现,有人 50 行写不完,有人 8 行 + 链式 + 注释清晰

一句话:概念题考"懂不懂",手写题考"做不做得到"。


2. 30 道高频题地图

按"考察知识点"分组,方便你针对性补短板

┌─────────────────────────────────────────────────────────────────┐
│                    30 道高频手写题地图                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────────────────┐    ┌──────────────────────┐           │
│  │  ① 函数控制(5)      │    │  ② 类型与原型(4)    │           │
│  │  Q1  防抖 debounce   │    │  Q5  手写 new         │           │
│  │  Q2  节流 throttle   │    │  Q6  手写 instanceof  │           │
│  │  Q15 柯里化 curry    │    │  Q7  手写 call        │           │
│  │  Q16 组合 compose    │    │  Q8  手写 apply       │           │
│  │  Q24 sleep           │    │  Q9  手写 bind        │           │
│  └──────────────────────┘    └──────────────────────┘           │
│                                                                  │
│  ┌──────────────────────┐    ┌──────────────────────┐           │
│  │  ③ 异步与 Promise(7) │    │  ④ 数据结构与算法(6)  │           │
│  │  Q10 手写 Promise    │    │  Q3  深拷贝          │           │
│  │  Q11 Promise.all     │    │  Q4  浅拷贝          │           │
│  │  Q12 Promise.race    │    │  Q18 数组扁平化       │           │
│  │  Q13 .allSettled     │    │  Q19 数组去重         │           │
│  │  Q14 Promise.any     │    │  Q20 isEqual          │           │
│  │  Q25 asyncPool       │    │  Q27 LRU Cache        │           │
│  │  Q30 红绿灯          │    └──────────────────────┘           │
│  └──────────────────────┘                                        │
│                                                                  │
│  ┌──────────────────────┐    ┌──────────────────────┐           │
│  │  ⑤ 工具函数(5)      │    │  ⑥ 设计模式(3)      │           │
│  │  Q17 EventEmitter    │    │  Q26 LazyMan          │           │
│  │  Q21 千分位           │    │  Q28 JSON.parse       │           │
│  │  Q22 URL 参数解析    │    │  Q29 Object.create    │           │
│  │  Q23 模板字符串       │    └──────────────────────┘           │
│  │  Q23 render          │                                        │
│  └──────────────────────┘                                        │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

3. 高频题"出现频率"统计

综合阿里、字节、腾讯、美团、百度、京东、拼多多 2022—2025 面经统计:

频率题目
⭐⭐⭐⭐⭐防抖、节流、深拷贝、手写 Promise、Promise.all、bind、new
⭐⭐⭐⭐call/apply、instanceof、柯里化、EventEmitter、扁平化、去重、asyncPool
⭐⭐⭐compose、isEqual、千分位、URL 解析、Promise.race/allSettled/any、LRU
⭐⭐sleep、模板字符串、Object.create、JSON.parse、红绿灯、LazyMan

应聘建议

  • 校招/初级:⭐⭐⭐⭐⭐ 全部能 5 分钟内手写
  • 社招中级:⭐⭐⭐⭐ 全部熟练,理解原理
  • 社招高级/资深:30 道全部熟,能讲出"为什么这么写"和"边界 case"

4. 通用方法论:怎么写好一道手写题?

4.1 三段式答题法

每道题都按**「简单版 → 完整版 → 进阶版」**三段答:

┌─────────────┐  能跑就行    ┌─────────────┐  考虑边界    ┌─────────────┐
│  简单版     │ ──────────→ │  完整版     │ ──────────→ │  进阶版     │
│  (~10 行)   │              │  (~30 行)   │              │  (50+ 行)   │
└─────────────┘              └─────────────┘              └─────────────┘
   核心逻辑                    边界 case                    工程优化

示例:手写防抖

  • 简单版setTimeout 包一层就行
  • 完整版:处理 this 指向、参数透传、清除上一次定时器
  • 进阶版:支持立即执行(leading)、取消(cancel)、Promise 化返回结果

4.2 答题套路(面试现场版)

"好的,这道题我会从三个层次来回答。"

  1. 先口述思路(30 秒):让面试官知道你脑子里有图
  2. 写简单版(1 分钟):先把核心跑通
  3. 加边界处理(2 分钟):边写边说"这里要注意 this、要注意空数组、要注意循环引用……"
  4. 写进阶版本(如果时间允许):体现工程素养

4.3 一定要说出口的几句话

话术适用题目加分原因
"我用 Symbol 避免属性冲突"bind、深拷贝体现严谨
"我用 WeakMap 处理循环引用,不会内存泄漏"深拷贝、isEqual体现对 GC 的理解
"时间复杂度 O(n),空间 O(n)"几乎所有题体现算法素养
"如果是大数组,建议用 for 循环不要用 forEach"数组类题体现性能意识
"考虑一下 nullundefinedNaN 的边界"几乎所有题体现工程素养

5. 学习路线建议

第一周:函数与原型基本盘

  • Day 1-2:Q1 防抖 + Q2 节流(搞懂 setTimeout、闭包、this)
  • Day 3-4:Q5 new + Q6 instanceof(搞懂原型链)
  • Day 5-7:Q7/Q8/Q9 call/apply/bind(搞懂 this 绑定)

第二周:异步与 Promise 全家桶

  • Day 1-3:Q10 手写 Promise(最重要,多写几遍)
  • Day 4-5:Q11/12/13/14 Promise 静态方法
  • Day 6-7:Q24 sleep + Q25 asyncPool + Q30 红绿灯

第三周:数据处理 + 工具函数

  • Day 1-2:Q3/Q4 深浅拷贝 + Q20 isEqual
  • Day 3-4:Q18 扁平化 + Q19 去重
  • Day 5-7:Q15/Q16 柯里化、组合 + Q17 EventEmitter

第四周:综合 + 设计

  • Day 1-2:Q21/Q22/Q23 工具函数三件套
  • Day 3-4:Q26 LazyMan + Q27 LRU
  • Day 5-7:Q28 JSON.parse + Q29 Object.create + 复习 + 模拟面试

6. 学习资源

配套文件

  • 📖 qa.md:30 道题完整答案(题目 / 思路 / 递进代码 / 复杂度 / 加分点)
  • 💻 examples/01-debounce.js ~ examples/30-traffic-light.js:每道题独立可运行
  • 🌐 demo/index.html:浏览器交互演示页

怎么用本章?

  1. 第一遍:先看 qa.md 的题目,自己默写,写不出来再看答案
  2. 第二遍:对比 examples/ 下的代码,看你的实现差在哪
  3. 第三遍:打开 demo/index.html实际跑一跑,体会输入输出
  4. 第四遍:模拟面试,对着白板/记事本,5 分钟内手写完整版

7. ⚠️ 易踩的坑(10 大经典翻车点)

#翻车率
1防抖忘记返回函数,直接执行90%
2bind 没考虑配合 new 的情况80%
3深拷贝没处理循环引用70%
4Promise 没实现"状态不可逆"(pending → resolve 后再 reject 失败)60%
5call/apply 实现时用 obj.fn() 修改了原对象(没用 Symbol)60%
6扁平化用 flat() 而不是手写递归50%
7节流的"前缘 + 后缘"边界没处理50%
8EventEmitter 的 once 实现错误(移除时找不到原函数)50%
9Promise.all 任意一个 reject 后还在收集结果40%
10LRU 用对象不用 Map(无法保证遍历顺序)40%

8. 一句话总结

手写题不是炫技,而是用最少的代码暴露你最深的功底。背诵答案不如理解原理,理解原理不如独立写出三个版本。


9. 延伸阅读