每年三四月份,前端实习岗的笔试总是能刷屏技术社区。网易这套2018年前端实习生笔试题,我印象很深——它不是什么偏题怪题,几乎每一道都踩在前端开发者日常工作的主线上:JavaScript的坑、浏览器机制、算法基本功、CSS布局、框架原理。也正因为基础,它反而能拉开差距。实习生岗位的笔试题,考的不是你背了多少API,而是你拿到一个具体问题时的拆解思路和表达能力。这篇文章我就以这套题的方向为线索,把考察点、解题思路、易错点完整梳理一遍。无论是准备暑期实习,还是查漏补缺巩固基础,都可以把它当成一次系统的前端知识体检。
1. 前端笔试题的出题逻辑:网易在筛选什么样的候选人
1.1 实习生岗位的隐藏考察维度
很多同学拿到笔试题的第一反应是“这些题我好像都会”,但填完却心里没底。这就是实习笔试题的典型特征:它不考你“知不知道”,而是考你“怎么想”。网易前端实习题,本质上是在筛选三类能力:
第一类是语言基础是否扎实。前端开发的核心语言是JavaScript,笔试里大量题目都在围绕作用域、闭包、原型链、异步机制这些语言特性做文章。表面上是选择题,实际上是在看你是否理解语言底层的执行逻辑,而不是仅仅“用过”。
第二类是工程意识是否初步建立。这反映在浏览器原理、HTTP机制、性能优化、代码输出顺序这些题目上。面试官想确认你有没有从“页面能跑”到“我知道页面为什么能跑”的转变。
第三类是解决问题的结构化能力。算法题部分往往难度不大,不要求你在ACM赛场上拿名次,但要求你思路清晰、边界条件考虑周全,并且能用代码把思路表达出来。这其实是工程师的核心能力:把模糊问题拆解成可执行的步骤。
1.2 笔试与面试的能力互补关系
笔试承担的是“粗筛”角色,面试承担的是“深聊”角色。所以笔试题通常有个特点:覆盖面广、单题深度受限。一套卷子下来,HTML、CSS、JavaScript、网络、算法、框架基本都要沾一遍,每道题不会给你太多时间“绕圈子”。
理解了这层逻辑,备考方向就明确了:不需要钻进犄角旮旯的冷门API,但凡是教材里“重点章节”的内容,都需要能落笔写出来。我在实际复习时给自己定了一个标准:任何一个知识点,如果我不能在一分钟内向别人讲清楚,那它就不算掌握。
2. JavaScript核心机制:闭包、原型链与异步的高频陷阱
2.1 this指向与闭包:送分题还是送命题
JavaScript笔试里,this指向几乎必考。网易这套题里就有典型的this绑定题目,考法很直接:给你一段代码,问输出什么。
var name = 'Window'; var obj = { name: 'Object', getName: function() { return function() { return this.name; }; } }; console.log(obj.getName()());这道题输出的是Window。原因是obj.getName()执行后返回的是一个普通函数,这个函数在全局环境中调用,它的this默认绑定到全局对象。闭包确实保留了变量环境,但闭包不能改变this的绑定规则。很多同学错在以为闭包会把外层this一并保存,实际上保存的是变量对象,不是this。
另一个高频变体是箭头函数:
var name = 'Window'; var obj = { name: 'Object', getName: function() { return () => this.name; } }; console.log(obj.getName()());换成箭头函数后输出Object,因为箭头函数没有自己的this,它会捕获定义时所在上下文的this值。这里恰好可以形成对比记忆:普通函数的this看调用位置,箭头函数的this看定义位置。
2.2 原型链与继承:把这张网画清楚
原型链题目多以“下面代码输出什么”的形式出现:
function Parent() { this.name = 'parent'; } Parent.prototype.say = function() { console.log(this.name); }; function Child() { this.name = 'child'; } Child.prototype = new Parent(); var child = new Child(); child.say();这个问题最终输出child。核心在于实例属性遮蔽原型属性,child对象内部有name属性,所以访问child.name不会沿着原型链往上走。而say方法是从原型链上找到的,执行时this指向child实例,因此输出child而不是parent。
这类题我建议在草稿纸上画一条原型链:实例child→Child.prototype→Parent.prototype→Object.prototype→null。只要属性查找路径清晰,答案不会错。另外注意Child.prototype = new Parent()这种方式的问题:父实例的引用类型属性会被所有子实例共享,这是个经典的坑,笔试如果追问优化方案,可以回答用Object.create(Parent.prototype)加构造函数继承的方式。
2.3 事件循环:异步输出顺序的标准答案
异步考查是另一类高频题,考的是事件循环(Event Loop)的理解。这类题网易也很偏爱,尤其是宏任务与微任务的组合:
console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); }); console.log('script end');正确输出顺序是:script start→script end→promise1→promise2→setTimeout。
记忆口诀很简单:同步代码先执行,微任务清空后再取宏任务。Promise.then属于微任务,setTimeout属于宏任务。每一个宏任务执行完,都会去清空微任务队列,然后再从宏任务队列取下一个。
这里我强烈建议把async/await的输出顺序也一并复习了:
async function test() { console.log(1); await Promise.resolve(); console.log(2); } test(); console.log(3);输出顺序是1、3、2。await后面的代码相当于被放进了Promise.then里,属于微任务。
3. 算法与数据结构:常见笔试模式的前端化拆解
3.1 数组去重与排序:考察API还是要考察原理
网易笔试题里的算法部分通常不会太难,数组去重、字符串反转、排序是常客。但需要注意,这类题目的重点往往不只是“实现出来”,而是在多种方案里体现你的取舍能力。
以数组去重为例,三个层级的答案是递进的:
第一层用Set:
function unique(arr) { return [...new Set(arr)]; }第二层用filter加indexOf:
function unique(arr) { return arr.filter((item, index) => arr.indexOf(item) === index); }第三层考虑对象的键或Map,处理NaN、对象等场景:
function unique(arr) { const map = new Map(); return arr.filter(item => !map.has(item) && map.set(item, true)); }如果是我来回答,我会先说Set方案最简洁,然后补充一句“但Set的去重基于SameValueZero算法,NaN也能正确处理;对引用类型则比较的是引用地址。如果需要按属性去重,就要用Map做标记”。这个回答体现的不只是“会用API”,而是明白API背后的规则。
3.2 字符串与回文类题目:边界条件比核心逻辑更值钱
字符串反转是另一道典型题。基础写法很简单:
function reverse(str) { return str.split('').reverse().join(''); }但实际问题往往有变体:reverse一个整数、判断回文、找出字符串中最长回文子串。网易这类题目的价值在于看你能不能处理边界条件。
判断回文的标准写法:
function isPalindrome(s) { s = s.replace(/[^a-zA-Z0-9]/g, '').toLowerCase(); let left = 0, right = s.length - 1; while (left < right) { if (s[left] !== s[right]) return false; left++; right--; } return true; }这类题的核心逻辑可能只需要10分钟就能想清楚,但边界情况至少要列一遍:空字符串、全标点符号、大小写、数字、奇偶长度。面试官真正看重的,是你有没有列边界情况的习惯。
3.3 二叉树遍历:从递归到迭代的思维进阶
如果笔试里出现树相关的题目,大概率是二叉树的遍历。递归写法简单直观:
function inorderTraversal(root) { const result = []; function traverse(node) { if (!node) return; traverse(node.left); result.push(node.val); traverse(node.right); } traverse(root); return result; }但能默写递归只是及格线。进阶要求是用迭代法实现:
function inorderTraversal(root) { const result = []; const stack = []; let current = root; while (current || stack.length) { while (current) { stack.push(current); current = current.left; } current = stack.pop(); result.push(current.val); current = current.right; } return result; }做这类题时我习惯在纸上模拟一遍栈的变化,把节点进出栈的每一步画出来。尤其是中序遍历的“一路向左压栈、弹出访问、转右子树”三步曲,一旦形成肌肉记忆,考试时就不会卡壳。
4. 浏览器与网络机制:从URL输入到页面展示的完整链条
4.1 页面加载过程:一道可以展开成完整项目的问题
浏览器的知识点在网易前端笔试题中占比不低,常见考法是用一段“从输入URL到页面展示发生了什么”来串起DNS解析、TCP连接、HTTP请求、渲染引擎解析等环节。这道题的价值在于:它把一个宏观问题拆解成多个清晰的子阶段,考察你能否把零散知识组织成完整链路。
我的回答模板大致如下:
- 解析URL:浏览器判断输入的字符串是合法URL还是搜索关键字,然后补全协议头。
- DNS解析:查找浏览器缓存、系统缓存、路由器缓存、DNS服务器,得到目标IP地址。
- 建立TCP连接:三次握手建立可靠连接,如果是HTTPS还有TLS握手。
- 发送HTTP请求:请求行、请求头、请求体依次发送,服务器处理后返回响应。
- 浏览器解析渲染:构建DOM树、CSSOM树,生成渲染树,布局(Layout),绘制(Paint),合成(Composite)。
- 断开连接:四次挥手释放TCP连接,如果开启了keep-alive则复用连接。
不要只背要点,要能画出每个阶段的产出物和工作内容。比如渲染阶段DOM树和CSSOM树是并行构建的,这个细节就常考。
4.2 HTTP缓存机制:强缓存与协商缓存的优先级判断
HTTP缓存几乎是必考知识点。网易的题目通常会给你一张请求响应头表,问你下一次请求是否走缓存、走的是哪种缓存。
判断逻辑可以总结成三步:
- 优先判断强缓存:检查
Cache-Control(请求头/响应头)和Expires。如果Cache-Control: max-age=<秒>未过期,直接使用本地缓存,不向服务器发请求。注意Expires是绝对时间,容易被系统时间影响,而Cache-Control是相对时间,优先级更高。 - 强缓存失效后走协商缓存:请求带上
If-Modified-Since或If-None-Match,服务器根据Last-Modified或ETag判断资源是否变化。若未变化返回304 Not Modified,浏览器继续用本地资源;若已变化返回200和新资源。 - ETag优先于Last-Modified:因为
Last-Modified精度到秒,文件改动过快时无法判断;ETag基于文件内容生成,更精确。
我在准备这部分时,会把常见的响应头字段做一张速查表,这里也分享出来:
| 字段 | 类型 | 作用 |
|---|---|---|
| Cache-Control | 通用头 | 强缓存主控制字段,如max-age、no-cache、no-store |
| Expires | 响应头 | 强缓存,绝对过期时间,HTTP/1.0产物 |
| ETag | 响应头 | 协商缓存,资源唯一标识,配合If-None-Match |
| Last-Modified | 响应头 | 协商缓存,最后修改时间,配合If-Modified-Since |
| Age | 响应头 | 资源在缓存服务器中存活的时间 |
4.3 前端安全基础:XSS与CSRF的辨别与防护
安全类题目在实习笔试题中属于“会的人不多,但考到了就拉开差距”的类型。最常见的两个概念是XSS和CSRF。
XSS(跨站脚本攻击):攻击者把恶意脚本注入到页面中,在用户浏览器中执行。常见类型有存储型、反射型、DOM型。防护手段是:对用户输入做转义或过滤,设置Cookie的HttpOnly属性,使用Content-Security-Policy(CSP)限制脚本来源。
CSRF(跨站请求伪造):攻击者诱导用户在已登录的站点上执行非本意的操作,本质是“借刀杀人”。防护手段有:使用CSRF Token并校验,检查请求头的Origin/Referer字段,对关键操作使用POST请求且附带自定义Header。
判断两者最直观的方式是看攻击意图:XSS是“打破数据机密性/完整性”,CSRF是“利用身份伪造请求”。笔试做题时一旦分不清,就问自己:如果受害者不访问页面,攻击是否无法展开?若是,多半是CSRF。
5. CSS布局题目:从需求到方案的快速匹配
5.1 垂直水平居中:经典题目的完整方案清单
CSS布局题目里,“垂直水平居中”出现频率奇高。网易的题目通常问两种东西:一是“请你实现某布局”,二是“给出尽可能多的方案并比较优劣”。
垂直水平居中的方案,至少要能写出四种:
/* 方案一:flex */ .parent { display: flex; align-items: center; justify-content: center; } /* 方案二:position + transform(父元素相对定位) */ .child { position: relative; left: 50%; top: 50%; transform: translate(-50%, -50%); } /* 方案三:position + margin: auto(父元素相对定位) */ .child { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; } /* 方案四:grid */ .parent { display: grid; place-items: center; }回答这类题目时,我会在给出方案后补一句适用范围:flex方案适合父容器尺寸确定或未知都行,transform方案适合子元素尺寸未知但已知父容器,margin:auto需要子元素有明确宽高,grid方案桌面端兼容性稍弱,但现代浏览器已全面支持。
5.2 两栏三栏布局与栅格系统:嘴上说简单,手底下见功夫
布局题中两栏、三栏布局也是经典。常见的考法是“左侧固定宽度,右侧自适应”这种最日常的需求。
经典flex方案:
.container { display: flex; } .left { flex: 0 0 200px; } .right { flex: 1; }如果题目限定了不能使用flex,还需要会float+BFC的兼容老方案。overflow: hidden给右侧创建BFC,避免左侧浮动元素侵入右侧区域。虽然现在项目中早就用flex和grid了,但笔试中多写一种方案恰是加分项,能证明你了解布局演进的过程。
5.3 移动端适配:rem、vw与viewport的取舍
移动端适配题目考察的是工程化思维。方案之间没有绝对优劣,关键是说出取舍逻辑。
- rem方案:通过设置
document.documentElement.fontSize = clientWidth / 设计稿宽度动态改变根字号,配合postcss-pxtorem把px转rem。优点是兼容性好,缺点是需要JS参与。 - vw方案:
width: 750px的设计稿直接写成width: 100vw,单位换算天然适配。优点是纯CSS,缺点是部分旧浏览器兼容性一般。 - viewport meta设置:
width=device-width, initial-scale=1.0是移动端页面标配,配合maximum-scale和user-scalable控制缩放行为。
网易这类题目往往不会要求你写完整适配代码,而是给出一个场景让你分析。答这类题的重心放在“为什么”上:为什么用vw而不用百分比?因为百分比是相对父元素计算,vw是相对视口宽度计算,在多级嵌套场景下vw更符合设计稿还原的需求。
6. 框架原理题:从“用过”到“能讲清”的进阶路径
6.1 Vue响应式原理:Object.defineProperty的边界与替代
2018年前后端面试已经很爱问框架原理了。网易前端实习题中Vue的考察重点集中在响应式原理,核心是用Object.defineProperty重写对象的getter和setter,在读取时收集依赖,在写入时触发更新。
答题要点:
- 组件渲染时,会读取响应式数据,触发
getter,此时对应的Watcher会被收集到Dep中。 - 数据发生变化时,触发
setter,通知Dep里的所有Watcher更新,触发视图重渲染。 - 数组的
push、pop等方法无法被Object.defineProperty拦截,所以Vue 2要额外重写数组方法;新增/删除对象属性也要用Vue.set/Vue.delete。
这里补充一个细节,Vue 3把响应式从Object.defineProperty换成了Proxy。原因很简单:Proxy可以直接代理整个对象,包括新增属性和数组索引变化,不需要像Vue 2那样做各种hack。回答时可以提一句“如果面试官问Vue 2的局限,这就是最核心的点”。
6.2 虚拟DOM与Diff算法:考的是对“为什么存在”的理解
虚拟DOM的题目经常问“为什么要用虚拟DOM”。这个问题不能只答“操作DOM性能差”,要从两个层面讲:
第一,真实的DOM操作确实耗时,频繁修改会引起重排和重绘,虚拟DOM把多次操作合并为一次性差异更新。
第二,更重要的是跨平台能力。虚拟DOM是普通JS对象,渲染层可以不只是浏览器DOM,还能是移动端原生组件,这就是React Native、Weex这类跨端方案的基础。
Diff算法的核心是同层比较:只比较同层的节点,不跨层级比较;通过key属性尽量复用节点,减少创建和销毁的开销。答题时如果画一张新旧虚拟DOM树的对比图,会清晰很多。但注意,千万不要在纸上写伪代码,面试时口头讲清楚流程就行。
6.3 组件通信与前端开发规范:贴近实际工作的能力探测
框架题还会考察组件通信,Vue里是props/$emit、事件总线、Vuex、provide/inject,React里是props、Context、Redux。题目一般会给定场景让你选方案。我的选择逻辑是:
- 父子组件直接用props传参 + 自定义事件。
- 兄弟组件用父组件中转,或全局事件总线。
- 跨层级深层组件用Context或全局状态管理。
- 大型项目统一用Vuex/Redux,方便追踪数据流向。
这类题目其实在探测你的工程习惯。2018年前后端开发已经普遍强调代码规范,笔试中问组件通信方案,不是考你记不记得API,而是看你在多人协作时怎么设计数据流。一个原则值得记住:数据流向越单一,代码越容易维护。
7. 考场实战经验:时间分配与答题策略
网易这套笔试题的时间压力不算极端,但对知识面要求比较广。分享一下我在实际准备和复盘过程中的体会。
时间分配建议:选择题和基础题控制在总时长的40%左右;算法题和应用题每道控制在10至15分钟;最后留10分钟检查。如果一道题卡了超过15分钟,先做标记跳过,把后面有把握的题写完再回头想。很多同学容易在算法题上死磕,结果导致CSS和网络题没时间做,这非常可惜。
答题策略:前端笔试题不是非黑即白。除了代码题,简答题一定要分点作答,先写结论再写理由。如果题目要求“请实现一个函数”,不要只贴代码,在代码上方用一两行说明思路,在关键行上加注释。这既方便自己理清逻辑,也给面试官留下“这个候选人有工程习惯”的印象。
复习优先级:如果你的准备时间有限,优先顺序是:JavaScript核心机制、浏览器与网络、算法高频题、CSS布局、框架原理。这个顺序是我在实际面试中感受到的考察频率排序,也是我后来带新人时反复强调的备考顺序。
另外,一定要动手写代码。很多人复习时“眼睛会了,手不会”,一看答案觉得简单,自己写就卡壳。笔试考的是落笔能力,不是阅读能力。我备考时会把每道经典题用全新环境默写一遍,写不出来的题标记出来搞懂,第二天再默写。这个循环重复三轮,基本就不会在考场上忘记某个API的用法了。