拼多多前端笔试:代码输出选择题与三道 JS 手写题
- 轮次
- 笔试
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
选择题(三道)
- 给定一段代码,输出结果是什么?
- 事件循环的输出顺序是怎样的?
- HTTP 与计算机网络相关的选择题考了哪些内容?
JS 手写题(三道)
- 手写搜索框的题目逻辑,怎么实现?
- n 皇后的变种题怎么解?
- 网络请求缓存的手写题怎么做?
《参考解析》
笔试结构:在线笔试,选择题三道加手写题三道。选择题全部落在 JavaScript 语言细节上(给定代码求输出、事件循环、HTTP),手写题不追求算法难度,考的是能不能写出边界处理完整的工程代码,三道题分别对应交互、回溯和缓存三个常见方向。时间分配上选择题不要恋战,把大块时间留给手写题——手写题按点给分,写不全也要把骨架和关键分支写出来。
代码输出结果题:常考的坑集中在几处——变量提升与暂时性死区(var 在声明前可访问为 undefined,let/const 直接抛 ReferenceError);this 指向(普通函数看调用形式,箭头函数取定义时的外层,回调里容易丢);闭包与循环变量(var 在 setTimeout 里全部输出最后一个值,let 每次迭代生成绑定);隐式类型转换([] + {}、[] == false、null == undefined 为 true 而 null === undefined 为 false);以及 typeof null === 'object'、0.1 + 0.2 !== 0.3 这类基础陷阱。做这类题先把同步代码按执行顺序标号,再逐个代入。
事件循环:JavaScript 单线程,靠事件循环调度。一轮的规则是:先执行整段同步代码,然后清空所有微任务,再取一个宏任务执行,接着再清空微任务,如此往复。微任务包括 Promise.then/catch/finally、queueMicrotask、await 之后的续体、MutationObserver;宏任务包括 setTimeout、setInterval、I/O、UI 渲染。三个易错点:new Promise(executor) 里的 executor 是同步执行的,只有 then 的回调才进微任务;await 会把它后面的代码切成微任务续体;每执行完一个宏任务都要把微任务队列清空,所以 Promise.resolve().then() 永远排在下一个 setTimeout 之前。Node 环境还要额外记住 process.nextTick 优先于 Promise 微任务。
HTTP 与计算机网络:这部分是选择题的固定板块,考点通常是状态码语义、缓存机制、连接建立与版本差异。状态码要记准 301/302 的区别、304 表示协商缓存命中、401 未认证与 403 无权限、502/504 分别代表网关错误与网关超时。缓存要分清强缓存(Cache-Control: max-age、Expires)和协商缓存(ETag + If-None-Match、Last-Modified + If-Modified-Since),强缓存命中不发请求。连接层要能说 TCP 三次握手与四次挥手,以及为什么是三次而不是两次;HTTP/1.1 的队头阻塞与 HTTP/2 的多路复用、头部压缩、服务器推送;HTTPS 在 TCP 之上加 TLS 握手与证书校验;跨域则是同源策略加 CORS 预检(非简单请求先发 OPTIONS)。
手写搜索框:核心链路是「输入 → 防抖 → 发请求 → 渲染 → 处理乱序」。防抖 300ms 左右,避免每敲一个字符都发请求;同时要处理中文输入法的 compositionstart / compositionend,在拼音未上屏时不触发搜索。竞态是最容易漏的一步:多个请求并发返回的顺序不保证,必须用 AbortController 取消上一个请求,或者给每个请求打自增序号、只接受最新序号的响应。工程上再补三点:结果按关键词做本地缓存(相同 query 直接命中);空输入清空列表并回到初始态;加载中与失败态要有明确 UI,键盘上下键加回车能选中结果。
n 皇后变种:基础解法是按行放置,用三个集合分别记录已占用的列、主对角线和副对角线做剪枝(列冲突看 col,两条对角线分别看 row - col 与 row + col),复杂度约为 O(n!),n ≤ 13 时可以用位运算把三个集合压进整数,速度最快。变种一般只改两处:一是棋盘不再干净,某些格子不可放置,放置前要判断该格是否可用,剪枝条件不变;二是改变求解目标——只求方案数就直接计数并省去结果列表,只求第一组解就在找到后立刻返回,要求「任意两个皇后在行、列、对角线之外还有距离限制」就多加一条距离校验。答题时先说清「逐行放置 + 三向剪枝」的框架,再针对变种改哪一行,比直接默写模板得分高。
网络请求缓存手写:分两层来写。第一层是 HTTP 缓存:强缓存用 Cache-Control: max-age,命中则不产生请求;协商缓存用 ETag / Last-Modified 配合 If-None-Match / If-Modified-Since,服务端返回 304 时复用本地副本。第二层是应用层缓存,自己维护一个 Map,key 用完整 URL 加参数,value 存数据与过期时间;未过期直接返回,过期则走 stale-while-revalidate——先把旧数据给调用方,同时后台刷新。还有一个必须写的细节是请求合并:把进行中的 Promise 存进同一张 Map,相同 URL 的并发调用直接复用这个 Promise,请求结束后删除,这样既防重复请求也天然解决了并发乱序。最后补上超时、失败重试与缓存容量上限(LRU 淘汰)。