如果时间倒回2011年,前端行业还处在一个“有工种没地位”的尴尬阶段。那时候我拿到阿里巴巴前端工程师笔试卷,第一反应是:终于有一家公司把前端当成正经技术岗来考了。整张卷子没有一道“会不会用Dreamweaver”的题,全是JavaScript、DOM、浏览器兼容、性能优化这些硬功夫。后来回头看,这套试卷基本就是当年阿里面向“能直接上手写淘宝页面”的人设计的筛子,考的不是知识面,而是你在真实浏览器环境里解决问题的能力。
这篇文章会把当年那套笔试卷的考察逻辑、核心题目方向、参考答案思路完整拆一遍,再对照2026年的前端面试,看看哪些东西十五年了依然有效,哪些已经被扫进历史垃圾堆。无论你是准备面试的新人,还是带团队的老兵,这套“考古”都能帮你重新校准对前端基础能力的判断标准。
1. 2011年那场笔试,到底在考什么
1.1 2011年前端行业的真实状态
想看懂这张卷子,得先回到2011年的技术现场。那一年jQuery 1.6刚发布没多久,IE6还占着国内浏览器市场百分之二三十的份额,HTML5还在W3C的草案里打滚,CSS3的圆角阴影还得靠厂商前缀才能跑。前端这个岗位在国内刚从“网页设计师”和“后端模板工程师”之间分裂出来,真正成建制的团队一只手数得过来,阿里巴巴的淘宝、支付宝前端团队算是里面规模最大、最正规的之一。
也正因为业务量大,他们对前端的要求非常明确:能用原生JavaScript写出高兼容性的页面交互,能手工优化页面加载速度,能在IE6、IE7、Firefox、Chrome之间把像素做到基本一致。那是一个“前端工程师要跟浏览器斗智斗勇”的年代,没有webpack帮你打包,没有babel帮你转译,没有polyfill帮你垫平差异,所有坑都得自己踩过一遍才敢说会。
1.2 试卷的整体格局:题型与侧重点分析
当年阿里的笔试卷方向很集中,不像现在的面试动不动就问框架源码、工程化架构。我印象里整张卷子大致分成五块:JavaScript语言基础、DOM操作与事件、浏览器兼容、页面性能优化、简单逻辑与正则。题型有选择题、填空题、简答题,还有两三道手写代码题。选择题考的基本是作用域、闭包、类型转换这类语言细节,填空题喜欢考运行结果输出,简答题会让你解释某个概念并举例,手写代码题则是现场实现一个功能。
这套结构放到今天看其实是相当科学的,它把“会不会写”和“为什么这么写”分开了。选择题和填空题考的是语言理解是否精确,简答题考的是表达能力,手写代码题考的是实际工程能力。相比现在很多公司一上来就问“说说Vue和React的区别”,这份卷子更像在筛选真正写过代码、踩过坑的人。
2. 核心考点逐个拆解:从闭包、原型链到DOM性能
2.1 JavaScript语言功底:闭包、作用域与原型链
闭包是2011年前端笔试的绝对主角,没有哪张卷子会放过它。那时候还没有ES6的let和const,var是唯一的变量声明方式,函数作用域是唯一的隔离手段,所以闭包不仅仅是一个语言特性,更是模块化编程的基本工具。笔试题会考你对下面这种代码的理解:
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 100); }输出是什么?5个5。为什么?因为var是函数作用域,循环体里的i是同一个变量,等定时器回调执行时,循环早已结束,i已经变成了5。这个坑在今天依然是高频面试题,只是现在可以用let一行解决,但当年你必须在没有let的情况下写出正确方案。标准答案是改用闭包:
for (var i = 0; i < 5; i++) { (function(i) { setTimeout(function() { console.log(i); }, 100); })(i); }这道题考察的深度在于:你不仅要懂闭包的定义,还得知道闭包能捕捉变量的当前值,以及IIFE(立即执行函数表达式)是怎么工作的。笔试现场能写出这种方案的人,基本可以判断是有实战经验的,因为只有被这个bug坑过的人,才会对这个模式有肌肉记忆。
原型链也是必考项。2011年还没有class关键字,继承全靠原型链硬写。常见考点是让你手写一个继承方案,或者判断某个对象的原型关系。比如问:var obj = {}; obj.toString是从哪来的?答案是通过原型链沿着Object.prototype找到的。更难一点的是让你实现一个组合式继承,也就是在子类构造函数里调用父类构造函数,同时把子类的原型指向父类原型的实例:
function Animal(name) { this.name = name; } Animal.prototype.sayName = function() { return this.name; }; function Dog(name, breed) { Animal.call(this, name); // 继承属性 this.breed = breed; } Dog.prototype = Object.create(Animal.prototype); // 继承方法 Dog.prototype.constructor = Dog;当年Object.create的浏览器兼容性还不太好,很多人会写成Dog.prototype = new Animal(),这会让子类原型上多出无用的name属性,原理上不干净。笔试阅卷人看到你用Object.create或者自己写了一个create的polyfill,是会加印象分的。
2.2 DOM、事件与浏览器兼容:兼容性是当年最大的拦路虎
2011年写前端,最大的噩梦就是浏览器兼容。一张试卷如果不考IE和标准浏览器的差异,简直就是不专业。事件处理是最典型的考点,因为IE和W3C两套事件模型完全是两回事:
- W3C标准用
addEventListener,事件回调里的this指向绑定元素,event对象作为参数传入 - IE8及以下用
attachEvent,事件回调里的this指向window,event对象挂在window.event上,而且事件名还要加on前缀
当年手写代码题让你实现一个跨浏览器的bind函数是标配:
function bindEvent(elem, type, handler) { if (elem.addEventListener) { elem.addEventListener(type, handler, false); } else if (elem.attachEvent) { elem.attachEvent('on' + type, function() { handler.call(elem, window.event); // 修正this指向和event对象 }); } else { elem['on' + type] = handler; } }这个写法有个细节值得注意:attachEvent的回调用了包装函数,把this指向绑定元素,并把window.event作为参数传给handler。这套修正逻辑是当年阿里面试官非常看重的,因为它展示了你真的理解IE事件模型和标准事件模型的差异,而不是背了一个API名。
除了事件,DOM操作的兼容性也是重灾区。比如获取元素的样式,标准写法是getComputedStyle,IE用currentStyle;获取表格的行和单元格,IE有rows和cells属性,标准也有,但某些边缘情况行为不一致;还有getElementsByClassName在IE8以下不存在,只能靠getElementsByTagName遍历过滤。笔试会通过一个简答题让你列举“你遇到过哪些浏览器兼容性问题”,这种开放题其实是送分题也是送命题,答得越多越具体,越能证明你真的写过兼容代码。
2.3 页面性能优化:雅虎军规的黄金时代
2011年面试必背的一份材料是雅虎的“Best Practices for Speeding Up Your Web Site”,也就是俗称的雅虎军规。阿里的笔试卷几乎肯定会出页面性能相关的题,因为淘宝首页的PV量摆在那,每一次请求、每一KB体积都是真金白银。
性能题的常见问法是:“请列举你能想到的页面性能优化手段,并说明原理。”当年要答到点子上,需要覆盖几个维度:
- 减少HTTP请求数:合并CSS和JavaScript文件、使用CSS Sprite合并小图标、内联小图片为base64
- 使用CDN:把静态资源分发到离用户最近的节点,缩短网络延迟
- 启用Gzip压缩:文本类资源能压缩到原来的三分之一左右
- 图片优化:选对格式,缩略图用JPG,图标用PNG,动画用GIF,必要时用WebP
- 样式表放头部,脚本放底部:避免脚本阻塞DOM渲染
- 避免CSS表达式:IE6时代用
expression()做动态样式会导致页面频繁重绘
原理部分要能解释清楚“为什么脚本放底部”。我当年在笔试里写的是“脚本会阻塞后续资源的下载和DOM解析,因为浏览器在加载和执行脚本期间无法并行下载其他资源”,面试时还被追问了“那defer和async有什么区别”,当场有点卡壳,回去之后才彻底搞明白。defer是等文档解析完再执行,多个defer保持顺序;async是下载完立即执行,不保证顺序,适合无依赖的独立脚本。这个知识点放到今天依然要考。
性能题还有个进阶版本是“原生JavaScript vs jQuery”,因为当年用jQuery写惯了的人容易忽略原生方法和jQuery方法之间的性能差异。比如document.getElementById比$('#id')快很多,因为jQuery要解析选择器字符串、走查询逻辑,而原生的getElementById是浏览器直接暴露的接口。笔试会通过选择题考察这种细节,看你是否理解框架的本质只是封装,而不是魔法。
3. 当年的解题思路与参考答案示例
3.1 拿到手写代码题,先想清楚再落笔
这里先说一个笔试通吃的经验:手写代码题不要上来就写,先在草稿纸上列清楚输入、输出、边界条件,再动手。比如让你实现一个数组去重,你得先想清楚“去重之后要保留原顺序吗?”“数组里会不会有NaN这种用indexOf检测不到的元素?”这些边界问题在2011年的卷子里不会被单独拿出来问,但阅卷人会在你的代码注释或防御性判断里看出你有没有这层思考。
当年手写题还有一个隐性考核点:代码风格。缩进规范、变量命名有含义、函数职责单一,这些在阅卷人眼里是“这个候选人有没有在大团队里待过”的信号。阿里的工程师文化一直比较看重代码的可读性和可维护性,笔试现场写出的代码就是你日常习惯的投影,临时装是装不出来的。
3.2 几个经典题目的现场推演
我按记忆整理三个当年出现频率极高的手写代码题方向,顺带把参考思路写出来,今天用来练手依然不过时。
题目一:数组去重。
2011年没有ES6的Set,去重只能自己写。最朴素的方案是双层循环:
function unique(arr) { var result = []; for (var i = 0; i < arr.length; i++) { for (var j = 0; j < result.length; j++) { if (result[j] === arr[i]) break; } if (j === result.length) { result.push(arr[i]); } } return result; }时间复杂度是O(n²),但代码最直观,不容易出错。进阶方案是用对象哈希:
function unique(arr) { var result = [], hash = {}; for (var i = 0; i < arr.length; i++) { var key = typeof arr[i] + arr[i]; // 区分数字1和字符串'1' if (!hash[key]) { hash[key] = true; result.push(arr[i]); } } return result; }这个方案把时间复杂度降到O(n),但有个经典陷阱:typeof arr[i] + arr[i]会默认把对象转成字符串“[object Object]”,所有对象都变成同一个key,导致对象无法被正确去重。当年面试官就喜欢追问这个点,看你能不能发现并解决。解决方式是用JSON.stringify作为key,或者引入一个自增id做映射。这道题放在2026年面试依然能打,因为去重的语法糖越来越多,但边界处理的思维依然稀缺。
题目二:手写跨浏览器的事件绑定。
这个在上面已经写过了,这里补充一个踩坑经验:attachEvent的包装函数会导致removeEvent无法移除,因为传入的handler被包了一层,已经不是原来的函数了。要解决这个问题,得把wrapper存起来,移除时传同一个wrapper。这个细节是当年我和同事调了半天才发现的,笔试能写到这里基本就是满分水平。
题目三:递归遍历DOM树,统计指定标签的数量。
function countTag(root, tagName) { var count = 0; var children = root.children; tagName = tagName.toUpperCase(); for (var i = 0; i < children.length; i++) { if (children[i].tagName === tagName) { count++; } count += countTag(children[i], tagName); } return count; }这道题考的是递归思维、tagName在HTML里大写返回的细节、以及对children和childNodes区别的理解。childNodes会包含文本节点和注释节点,children只包含元素节点,如果用了childNodes而又没过滤节点类型,统计结果就会出错。这些细节都是阅卷人一眼就能看出来的,也是区分“背过DOM API”和“真正操作过DOM”的分水岭。
4. 老题新看:2011 VS 2026 前端面试的变与不变
4.1 十五年了,哪些能力依然硬核
如果把2026年的前端面试题拉出来对比,你会发现一个有意思的现象:JavaScript基础、事件机制、性能优化、手写代码这些板块,跟2011年那份笔试卷的考察逻辑几乎一模一样。现在的“八股文”里大量出现的防抖节流、深拷贝、Promise.all、数组扁平化,本质还是当年那些语言底层功底的变体。
比如现在面试常考的“手写防抖”,2011年虽然不叫这个名字,但面临的问题完全一样:窗口resize时频繁触发处理函数导致卡顿。当时没有Lodash,没有_.debounce,全靠自己用setTimeout实现。再比如深拷贝,现在可以用structuredClone一行解决,但面试还是喜欢让你手写,就是为了看你能不能递归处理对象、数组、循环引用。这些题目背后的能力——递归思维、类型判断、边界意识——十五年前和现在没有任何区别。
浏览器兼容性这块,虽然IE已经彻底退出历史舞台,但“兼容不同环境”的思维反而更复杂了:现在你要兼容的是不同厂商的WebView内核、不同版本的Safari、不同手机厂商魔改的浏览器内核,还有小程序那套跟标准DOM完全不同的环境。2011年你只需要记IE和标准两套行为,现在你要面对的是一个碎片化的生态,考你的依然是“是否能快速定位差异并给出优雅方案”的能力。
4.2 已经被扫进历史的技术细节
当然,2011年试卷里的很多内容今天已经完全没有参考价值了。CSS hack那一套(比如_property只对IE6生效、*property对IE6和IE7生效)现在提都没人会提,因为IE已经成为历史。table布局和CSS Sprite合并图标也基本被Flexbox、Grid和SVG、字体图标取代了。document.all、attachEvent这些API在MDN上已经标记为废弃,现在写代码根本用不到。
前端工程化更是天翻地覆。2011年的“性能优化”还在教你怎么手动合并脚本、压缩图片、减少请求数,2026年已经是webpack/Vite在打包时自动完成这些事了。现在的前端面试如果还问“如何减少HTTP请求”,答案会更偏向于“交给构建工具处理,同时用HTTP/2多路复用减轻请求合并的压力”。当年那套“手动合并文件”的功夫,在自动化工具面前确实没什么用武之地了。
框架这块更是彻底变天。2011年还是jQuery称霸、Backbone刚刚兴起的年代,笔试压根不考框架,因为会jQuery的人太多了,看不出区分度。现在前端面试85%时间在问React和Vue的原理、diff算法、响应式机制、Hooks实现,这种变化跟2011年完全是两个物种。但换个角度看,当年那份试卷的理念其实是对的:把语言底子和浏览器原理考扎实,框架随时可以上手学。这个理念放到2026年依然正确,只是很多候选人已经不太认同了。
4.3 2026年前端面试新增了哪些维度
跟2011年相比,现在前端面试增加了很多当年不敢想的板块。工程化是最大的一块,从包管理器、构建工具、代码规范、CI/CD、到微前端拆分,面试官会真的让你讲某个配置项的原理。TypeScript也成了必考项,类型体操考得比当年的正则还灵活。跨端方案(React Native、Flutter、小程序)是2011年完全不存在的话题。还有一个新兴方向是AI辅助开发,像CodeBuddy、Cursor这类工具的出现,让面试开始关心候选人如何利用AI提高效率,同时又如何保证代码质量不被AI带偏。这些方向在2011年的试卷上写都写不出来,时代变化就是这么剧烈。
我把两个时代的面试核心考察点放到一张表里,看得更清楚:
| 维度 | 2011年阿里笔试卷 | 2026年主流前端面试 |
|---|---|---|
| JavaScript | 闭包、原型链、作用域、ES3/ES5 | ES6+、Promise、异步、类型系统 |
| 浏览器 | IE6/7/8兼容、事件模型差异 | 内核机制、渲染原理、Web安全 |
| 性能 | 手动合并请求、雅虎军规 | Core Web Vitals、优化指标、懒加载 |
| 框架 | 基本不考(jQuery不算框架) | React/Vue原理、状态管理、Hooks |
| 工程化 | 几乎不涉及 | 构建工具、CI/CD、微前端、模块化 |
| 工具链 | 浏览器开发者工具、Firebug | 调试、TypeScript、AI辅助开发 |
5. 从笔试出发:给2026年前端求职者的实际建议
5.1 用“考古题”检验自己的基本功
我经常给团队里的年轻人一个建议:别急着刷2026年的最新面经,先找几份2011年左右的笔试卷限时做一遍。不是为了应付面试,而是用它做一次基本功体检。如果闭包、原型链、递归、事件机制这些老题你依然要卡壳,那说明你的基础还不够扎实,这时候刷再多的微前端面试题都是空中楼阁。因为微前端、响应式原理这些上层建筑,全部建立在JavaScript语言核心和浏览器工作机制之上。
我自己带人有个习惯,面架构师候选人时也会偶尔抛一个“.concat和.push的区别”这种老掉牙的题,很多人觉得我故意送分,但真的会有人答错:concat返回新数组,push修改原数组并返回新长度。就是这么简单的问题,能把“对语言API的理解是否准确”测出来。2011年那份笔试卷里的很多选择题,测的正是这种对细节的精准把握。
5.2 按“底层能力、工程能力、业务理解”三层构建知识体系
与其死记硬背面经,不如按三层结构系统整理自己的知识地图。底层能力是JavaScript语言、浏览器原理、网络协议、数据结构与算法,这一层跟2011年那份试卷高度重合,是永远不会过时的。工程能力是框架原理、工程化配置、性能调优、监控告警、团队协作规范,这一层是2026年面试的重头戏,也是“高级工程师”和“初中级工程师”的分水岭。业务理解是你能不能用技术解决实际业务问题,比如大文件上传、实时数据展示、复杂表单交互,这类题通常以项目经历的形式出现,需要你真实做过才能讲得有细节。
三层结构里,底层能力最容易被忽视,但恰恰是笔试最能拉开差距的部分。2011年的卷子没有项目经历可以聊,全靠现场写,所以底层能力不过关的人立刻原形毕露。现在的面试虽然多了很多环节,但笔试环节的逻辑其实没变,依然是用底层能力做第一道筛选。
5.3 面试现场要展示的不只是“会做”,而是“会想”
最后说一个我在几次参与面试后的体会:很多候选人代码写得没错,但面试官问“为什么要这么写”时,答案只有“大家都这么写”。这放在2011年的笔试里,可能还能蒙混过关,因为当时能写出正确答案的人就不多,现在的竞争环境完全不同。面试官想知道的是你能不能解释自己的每一步选择,比如:
- 为什么用
reduce而不是forEach来累加? - 为什么事件委托的
target要判断nodeType? - 为什么把某个计算逻辑放在
useMemo而不是直接写在render里?
这种“可解释性”恰恰是2011年那份笔试卷在填空题和简答题中一直在测试的能力。现在刷面经的人总喜欢背“标准答案”,但真正能区分候选人的,是答案背后的思维过程。如果你能在笔试或面试中把思考过程写出来、讲出来,就已经赢过大量只会背答案的竞争者了。
我到现在还记得当年笔试结束后那个傍晚,从杭州的面试楼里出来,心里非常清楚:那套题考的不是你会不会写一个按钮的点击事件,而是你愿不愿意把每一行代码为什么会出现在那个位置想明白。这个观念,我后来用了十几年,也用它一路筛选了不少靠谱的同事。前端这个行业变化快得让人眼花缭乱,但底层那些东西——对语言的理解、对用户的理解、对代码质量的要求——反而一直没变过。如果你想检验自己是不是真的适合走这条路,去找一份2011年的前端笔试卷做一遍,比刷一百道2026年的面经都管用。