2018网易校招前端笔试题复盘:从JS基础到工程化的考点与思路
2018年那个秋招季我投了网易前端开发工程师BJ的岗位。笔试通知来得不算突然但点开笔试链接那一刻盯着满屏的前端基础题还是愣了一下——没有想象中复杂的算法题也没有那种“背一背面经就能过”的重复题。相反那种“我好像会但又不确定”的题占了大半。考完走出机房我脑子里反复回放的全是纸上的JS代码块和小到细枝末节的CSS陷阱。后来我跟不少参加这场笔试的同学复盘大家都有同感网易这场笔试考的并不是你“背了多少知识点”而是你“平时写代码踩过多少坑”。这篇文章就以我个人的复盘视角还原2018网易校招前端笔试卷的题型结构、考点逻辑和答题思路也聊聊那之后我重新整理的复习路线。1. 翻开这份卷子之前那年前端面试的技术版图1.1 2018年社区里在讨论什么如果只用一个词概括2018年的前端技术环境我会选“切换期”。ES6已经不再是“新特性”而是日常开发里的默认写法模块化、工程化、组件化从概念变成了入职基本功市面上主流的框架形成了Vue、React、Angular三足鼎立的格局而中小团队里Vue的普及率尤其高网易内部很多业务线的Web项目也大量使用Vue和React。当时社区里热门的话题大致有以下几类手写Promise、实现一个mini版Vue响应式系统webpack 4的零配置体验和dll分包优化HTTP/2多路复用、Service Worker离线缓存小程序横空出世后带来的跨端趋势大型项目的状态管理方案Vuex与Redux的对比CSS Grid开始普及但兼容性仍是难题Flexbox已经成为布局主流。这些话题不是随口聊的它们直接反映到笔试的大题和面试追问环节。翻看当年的各种前端笔试合集就会发现网易的题目里面向业务场景的题目占比不低它更看重你是否有工程思维而不是单纯考察API记忆。1.2 网易笔试喜欢从哪个维度出题网易的笔试不太走“偏题怪题”路线整体风格是偏基础和应用的结合。以2018校招前端开发工程师BJ笔试卷为例我回忆并重新整理后发现考点主要集中在四个维度维度具体内容占大致比例原生JS基础类型转换、作用域、闭包、原型链、事件机制、异步35%左右浏览器与网络渲染机制、缓存、跨域、HTTP状态码、性能优化20%左右CSS与页面布局BFC、Flex、居中、定位、响应式、兼容性15%左右编程题与手写题编码实操、算法、逻辑思路30%左右另外还会有一小部分HTML、ES6新特性、框架和工程化相关的选择题穿插在基础题里用来判断你是否有项目经验还是只在学校里学过一门《网页设计》。1.3 从真题看筛选逻辑校招笔试不考“会了多少”而考“踩坑之后能走多远”我在准备笔试的时候有一度很焦虑因为面经上别人的回忆看起来很简单但自己做起来总出错。后来我发现网易这类公司出校招笔试的筛选逻辑并不是为了考倒你而是为了判断你在真实业务环境下能不能独立解决问题。一个很典型的例子笔试卷里很爱考数组去重、防抖节流、深拷贝这类基础手写题看起来随便一个培训班学员都能写出来但它会在你写完之后继续追问边界情况处理、性能优化思路甚至会要求你对比不同实现方式的优缺点。这种考法考查的其实是你踩坑的能力——比如有没有处理过Symbol这种无法被常规Object.keys遍历到的属性比如有没有遇到过循环引用导致JSON.parse(JSON.stringify(obj))直接爆栈。笔试不是在问“你背没背过这道题”而是在问“你写代码时到底见没见过问题本身”。2. 选择题里的基础功每一道看起来简单但每道都能排除两个错误项2.1 CSS布局题浮动、BFC、垂直居中“三件套”网易笔试的选择题部分CSS布局题几乎是必考的。常见套路是给你一段HTML和CSS问某个元素最终的位置或宽度或者问以下哪种方式可以实现垂直居中。2018年的题量不算大但这几类题目几乎每场笔试都会以某种形式出现。以浮动布局为例。很多人记得浮动会让元素脱离文档流但是问到父元素高度塌陷怎么解决时能完整写出方案的人并不多。笔试里通常会给出几个选项比如父元素设置overflow: hidden、父元素也浮动、父元素设置固定高度、使用clearfix伪元素。正确答案是clearfix和使用overflow: hidden都能触发BFC解决塌陷但它们的适用场景并不完全相同overflow: hidden在某些情况下会截断溢出的下拉菜单或者影响定位元素的表现而clearfix是更安全的通用方案。这个在选择题里不会考那么细但到了问答题或者面试追问环节就会展开。垂直居中也是一样。2018年这个时候Flexbox方案已经成为主流但笔试仍会考其他方案的原因是考察你知不知道在Flex不可用或必须兼容旧浏览器时怎么办。我当时的答题思路是先把已知方案全列出来margin: auto配合绝对定位、transform: translate(-50%, -50%)、Flex布局、table-cell配合vertical-align。然后再逐一看题目给的限制条件比如父元素高度未知吗子元素是否定宽定高是否有overflow问题这些条件一出来能选的方案立刻就被压缩了。2.2 事件循环、作用域与异步笔试中真正的淘汰题如果选择题里有哪类题最让人心里发虚我猜很多人会说是事件循环Event Loop。网易的笔试题特别喜欢用一个看起来很简单的setTimeout、Promise、async/await组合题来考察比如async function async1() { console.log(async1 start); await async2(); console.log(async1 end); } async function async2() { console.log(async2); } console.log(script start); setTimeout(() { console.log(setTimeout); }, 0); async1(); new Promise(resolve { console.log(promise1); resolve(); }).then(() { console.log(promise2); }); console.log(script end);这道题我在准备阶段就见过很多次但真正在笔试时手推输出顺序还是差点推错。关键点在于await 会先执行右侧表达式但后面的代码会被放到微任务队列Promise的executor是同步执行的但then注册的回调是微任务setTimeout即使延迟设为0也是宏任务并且要等当前宏任务和本轮所有微任务都执行完才会进入整体输出顺序是 script start → async1 start → async2 → promise1 → script end → async1 end → promise2 → setTimeout。这种题的可怕之处不在于难而在于它跟工作高度相关。平时写代码时一个Promise的状态流转没想清楚排查bug就可能多花一小时。笔试考的就是你有没有“脑中执行代码”的能力而不是真的有更高效的工具帮你打日志。2.3 类型转换与原型链那些容易记混的对象API2018年笔试卷上还出现了不少关于类型转换和原型链的选择题。典型如[] ![] 的结果是什么为什么 b a a a 在浏览器里会得到字符串 baNaNaObject.prototype.toString.call 和 instanceof 的区别如何准确判断一个变量的类型。这些题在刚面前端岗位时让人很崩溃因为看起来像脑筋急转弯实际背后全是JS语言的设计机制。比如 号运算符在遇到字符串时会走字符串拼接一元加号会把变量转换Number所以 a 会变成NaN再跟前面的字符串拼接就成了baNaNa。你再看到这种题只要抓住“二元加号遇到字符串就拼接一元加号负责转数字”这条规则基本就不会被迷惑。原型链的题也是类似逻辑。题目问某个对象能不能访问一个方法或者某个属性查找的路径顺序本质上就是在考察“对象 → 构造函数的prototype → 构造函数的父级prototype → … → Object.prototype → null”这个链条是否清晰。我自己当时踩坑最深的是把proto和 prototype 搞混后来我总结了一句话——prototype是函数身上的属性__proto__是实例身上的隐藏指针。只要这句话还在原型链的题就丢不了分。3. 编程题与手写题没有一眼到底的标准答案只有边界和性能的比拼3.1 手写防抖节流从实现到场景分析网易笔试的编程题一般不止一道。其中一个高频考题是手写防抖debounce和节流throttle。2018年很多前端笔试都有这道题但网易的考法会加一步要求分析它们各自适合什么场景。我当时写的防抖实现function debounce(fn, wait) { let timer null; return function(...args) { const context this; if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(context, args); }, wait); }; }节流实现可以选择时间戳版或定时器版。时间戳版是立即执行定时器版是延迟执行很多人在笔试时因为没区分这两个版本而答错。我当时把两种版本都写上然后补充说明它们的行为差异面试官就能看出来这对知识点是真正吃透了的而不是死记一个模板。场景分析是拉开差距的地方。防抖适合输入框自动搜索、窗口resize停止触发节流适合滚动事件、拖动事件、高频点击上报。如果你能补充一句“防抖的特点是‘只执行最后一次’节流的特点是‘固定频率内最多执行一次’”这道题就基本稳了。3.2 深拷贝从JSON一行代码到边界case武装深拷贝是当年笔试里绕不开的题目。因为实现难度可高可低用来区分基础者和进阶者非常好用。第一档回答是const clone JSON.parse(JSON.stringify(obj));但能在笔试中过关的必须知道这种方案的坑只会拷贝可枚举属性、会丢失undefined和函数、无法处理循环引用、Date会被转成字符串、RegExp和Map/Set等特殊对象会被转成普通对象。进阶版是递归实现并处理数组和普通对象。再进一步需要处理循环引用最简单的方式是用WeakMap缓存已拷贝对象function deepClone(obj, hash new WeakMap()) { if (obj null || typeof obj ! object) return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); if (hash.has(obj)) return hash.get(obj); const cloneObj Array.isArray(obj) ? [] : {}; hash.set(obj, cloneObj); for (const key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] deepClone(obj[key], hash); } } return cloneObj; }在考场上能写到WeakMap这一层就已经超过很多人了。如果还能聊到Object.getOwnPropertySymbols、Reflect.ownKeys、以及如何拷贝原型链上的属性那这道题的得分可以直接拉满。3.3 手写Promise.resolve与异步流程控制2018年不少笔试卷还出现了让手写一个Promise或实现Promise.all的题目。网易那场是否有这道题我记得不太清但作为备考重点它几乎是必练的。因为这类题不仅考了异步编程模型的理解还考了对状态流转的处理pending → fulfilled、pending → rejected且状态不可逆。我当时练习时会先实现一个简化版Promise只关注resolve、reject、then的基本逻辑然后再给自己加需求比如实现链式调用、实现finally、实现resolvePromise的递归解析逻辑。每次写完都对自己提交的代码做一次自问如果有多个then注册resolved之后才注册then还会触发吗我需要缓存value并以异步方式触发回调吗这些细节一旦想清楚事件循环题和Promise题就都通了。当时拿到这道题的标准写法是Promise._all function(promises) { return new Promise((resolve, reject) { const results []; let count 0; for (let i 0; i promises.length; i) { Promise.resolve(promises[i]).then(value { results[i] value; count; if (count promises.length) resolve(results); }, reject); } }); };这里有一个容易忽略的坑用results.push(value)会导致结果顺序和输入顺序不一致必须通过索引赋值。笔试如果考到一定要表达出你已经意识到了这一点。它不是“背答案”而是你真的写过多线程或并发请求知道乱序的后果。4. 框架、工程化与网络不以选择题为主的“隐性考点”4.1 Vue的模板编译与响应式原理从使用到理解的跳跃网易笔试的选择题里会有几道Vue或React的基础题但很少直接让你写一个组件更多是考察原理层面的理解。比如Vue 2.x的响应式原理Object.defineProperty 对每个属性进行getter/setter劫持在getter中依赖收集在setter中触发更新。题目可能会直接问为什么Vue 2.x新增属性不是响应式的为什么删除属性也要用Vue.delete接着引导你思考Proxy与Object.defineProperty的区别以及Vue 3为何改用Proxy。我当时在复习时特意自己画了一张依赖收集的流程图每个组件实例对应一个Watcher每个data属性被渲染时在getter中把这个Watcher收集进Dep数组数据变化时setter里通知Dep去遍历Watcher并触发更新。虽然笔试未必考这么深但这个理解帮助我答对了几乎所有的Vue原理题因为底层逻辑通了换什么问法都能绕回来。4.2 webpack构建优化笔试里的问答题可能长这样2018年前端岗位没有哪个方向能绕开构建工具。网易的笔试试卷中有些场次会把webpack的内容放在问答题或者设计类大题里让你分析如何优化打包速度或首屏加载速度。这类题没有标准答案需要在几个方面展开按需加载/路由懒加载把import改成动态import让webpack按路由分包体积优化开启gzip、使用CDN、压缩混淆、Tree Shaking、去掉生产环境source-map缓存策略output文件名加hash配合浏览器强缓存多进程构建thread-loader、happypack2018年当时很流行减少编译范围resolve.modules指定node_modules唯一路径、exclude/include精准限制loader范围。我当时在答这类题目时会先分两大类一类是网络请求层面的减少请求数、减小体积、缓存一类是构建过程层面的减少模块搜索范围、开启缓存、并行构建。这样写有一个好处能让批卷人快速看出你不是零散背过几个优化点而是有一套清晰的分类框架。4.3 浏览器渲染与性能优化答之前先画一个时间轴再看浏览器相关的题目。网易笔试向来很重视“输入URL回车后发生了什么”以及“浏览器渲染管线”这类基础题。它们看起来是老生常谈但追问起来几乎没有上限。我的答题思路是先划分阶段DNS解析 → TCP连接 → HTTP请求 → 服务端处理并返回HTML → HTML解析与CSSOM构建 → DOM树构建与渲染树合并 → 布局与绘制 → GPU合成与显示。然后再针对每个阶段延伸优化策略DNS预解析、CDN加速、HTTP缓存、小图片base64或雪碧图、CSS放到头部JS放到尾部或加defer/async、避免重排重绘、减少长任务卡顿等等。4.4 跨域与网络安全每个前端人都必须过的坎跨域也是那年笔试卷的高频考点。网易的题目不会只问“怎么解决跨域”而是问你在某种特定场景下比如开发环境、线上接口、第三方登录哪种方案更合适为什么。我整理的方案清单包括JSONP只支持GET靠script标签绕过同源策略适合简单接口CORS服务端设置Access-Control-Allow-Origin支持复杂请求和自定义header是现代主流的做法代理转发开发环境用webpack-dev-server的proxy解决接口跨域生产环境由Nginx把静态资源和API反向代理到同一域postMessage适合iframe嵌套页面之间的通信WebSocket天然支持跨域但场景有限document.domain仅限同主域不同子域现在用得越来越少了。如果把这道题答好除了列出方案最好再补上“为什么JSONP不支持POST”“预检请求发生在什么情况下”“带上cookie时credentials怎么设置”这几个延展点。笔试经常不直接问但面试官会在下一轮追问。5. 笔试答完之后复盘那些差点丢分的细节5.1 我身边同学丢分最狠的三个地方丢分点第一名绝对不是算法题而是JS基础选择题里那些“看似可以蒙对”的坑。比如var a []; a.push(1, 2, 3); console.log(a.length); console.log(typeof a);几乎没有人不会但换一种问法var arr [1, 2, 3]; arr[2] 9; console.log(arr.length);很多人会以为数组的length不变因为arr[2]本来就在其实length还是3但如果你想的是“索引2已经被占用了”那这题你就跳进了陷阱。这种题从难度上讲不算难但考的是对数组本质的理解——原生数组的索引本质上也是属性只不过当属性名是非负整数字符串时JS会自动维护length。丢分点第二名是手写题不够完整。很多同学只写了核心逻辑没有处理参数校验和特殊边界比如输入为null、空字符串、超大数、多层嵌套。笔试时间紧张你要有意识地在写代码时多写几步防御阅卷人会明显高看一眼。丢分点第三名是答案结构混乱。简答题或问答题部分直接堆一堆名词没有分点、没有结论。我记得有一个同学答webpack优化把“压缩”“缓存”“拆分”混在一起写批卷老师很难抓到重点。比较好的方式是“先说问题的分类再逐类给方案最后给出你推荐的最优先措施”。5.2 答题顺序和时间分配建议网易笔试通常题量中等但陷阱题不少。我的建议是拿到试卷后先用2到3分钟扫一遍全卷把题目分成三档第一档自己极熟悉的知识点先快速拿分第二档需要一定推导或计算的题比如事件循环顺序、深拷贝边界、数组算法题留够时间第三档不太确定或需要长篇大论的问题放到最后避免卡在两分题上浪费大量时间。时间分配上选择题和填空题总共控制在40%以内编程题至少留40%问答题只占20%。很多同学最容易犯的错误是前面的选择题越做越纠结等到手写题时只能匆匆写个大概导致实力没发挥出来。5.3 如果重来一次我会怎么复习站在现在的视角回看2018年的笔试卷如果再让我准备一遍我会把复习重点做一次完全不同的排序。我不会再从“知识点清单”开始背而是先真实模拟笔试卡着时间做一套完整的题然后对着错题反推知识漏洞。比如事件循环推错一次就专门做10道相关题再手写一段混合Promise和setTimeout的代码去浏览器验证比如原型链选错一次就把instanceof、Object.create、constructor之间的关系全部梳理一遍。这个方法比按章节从头到尾刷题高效得多因为笔试不是检验你“背了多少”而是检验你在时间压力下能正确输出多少。以输出倒逼输入查漏补缺才是最快的路径。我会给自己定一个小目标每天手写两道最容易出错的题——防抖节流、深拷贝、函数柯里化、数组扁平化、Promise.all每个都写到边界情况无懈可击才允许自己收手。这套流程坚持两周效果远超啃完一整本面试题库。6. 笔试之后那些延伸出去的东西6.1 从笔试卷到面试每一道题都可能变成深挖的起点我后来发现网易笔试不像其他公司那样“考完就翻篇”它更像是一份面试官的提问地图。你笔试里做过一道关于事件循环的题面试时很可能被追问“宏任务和微任务在浏览器和Node里有什么区别”你手写过深拷贝面试时很可能被追问“structuredClone你知道吗和JSON方案相比有什么优势和限制”。所以笔试复盘的意义不仅是知道自己错了多少更是整理一套属于自己的“技术表达语言”。把每道题都从“知道答案”升级到“讲得清楚为什么是这个答案”面试时你会明显比只会背题的人从容。6.2 日常积累比考前突击更重要2018年那次笔试之后我养成一个习惯每遇到一个bug在修复后都会记录下来并思考它“在笔试题里会怎么考”。比如线上环境有个报错是一个undefined的map调用背后涉及的是可选链和数组方法的nodeType判断再比如移动端某个页面滚动卡顿追到底最终发现是频繁强制同步布局这对应的是渲染优化类题目。这种积累方式让知识点不再是孤立的而是跟真实场景绑在一起。下一次笔试或面试时你不需要刻意回忆就能答出“我遇到过类似情况当时是这样排查的”。在公司校招面试官面前这种表达的可信度远远高于一句“我刷过这道题”。6.3 写在最后的一个小经验如果你现在正在准备前端校招笔试尤其是想投网易这类一线互联网公司我想分享一个小技巧不用执着于去找“原题”更重要的时训练自己做题时的思考方式。网易的笔试试卷年年变但它的底子里始终藏着对基础深度的执念。你只需要把每道基础题背后可能的三个“为什么”都问一遍再去落笔写一道完整的手写题胜过背十套机经。考场上真正拉开距离的从来不是你做过多少题而是你能不能在一道看似简单的题里让阅卷人看到你踩过坑、想过为什么、并养成了专业的处理习惯。把一套笔试卷当作一次全面的体检做错的选项就是你体内的薄弱点。早暴露早补上这笔交易怎么算都不亏。