ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

用友2017前端笔试题深析:底层能力仍是校招分水岭

用友2017前端笔试题深析:底层能力仍是校招分水岭 每年到这个时间点总有很多准备校招的同学在群里翻旧题。用友2017年这套Web前端笔试题我当年也刷过后来校招季又反复拿它给学弟学妹做模拟。八年过去框架从jQuery时代走到了Vue 3、React 18遍地走的阶段但这套题依然值得拿出来逐题拆一遍——不是因为题目多新恰恰因为它很“旧”旧到能看出企业笔试出题人真正想筛选什么。这套题覆盖了前端基础三件套、JavaScript核心机制、简单算法、网络与浏览器原理整体难度在当年的校招里属于中规中矩但陷阱不少。适合正在准备暑期实习或秋招的同学拿来当自测卷也适合工作了两三年、想查漏补缺的前端工程师。它会告诉你在“用友”这类做企业级软件的公司里前端岗笔试为什么这么出考查的底层能力到底是什么以及哪些题放到今天依然会考。1. 整张卷子的设计思路企业校招笔试题到底在筛什么1.1 不是考你会不会用框架而是考你“能不能干活”很多同学看到笔试题没有Vue、没有React第一反应是“这公司技术栈太老了吧”。实际上企业级软件公司尤其是做ERP、云平台这类产品的出校招笔试题首要目标是筛掉“只会调框架API”的简历型选手。这类公司产品线复杂往往需要维护多年沉淀下来的老系统同时也在做新平台的研发所以面试官真正关心的是给你一段没见过的业务代码你能不能看懂给你一个没遇到过的bug你能不能顺着JS的执行机制找到原因。所以这套题里大量出现原型链、闭包、事件循环、变量提升完全不是技术栈陈旧而是这些内容在任何框架下都是通用的底层思维。框架年年换但JavaScript语言核心机制二十年没大变企业招聘要的是能跨越技术迭代长期干活的人。1.2 用友这类企业级公司对前端岗的画像以用友的校招背景来看前端工程师进去后接触的往往不是那种炫酷的C端营销页而是大量表单密集型页面、审批流界面、数据报表看板。这意味着几个能力特别重要对浏览器兼容性敏感企业客户什么浏览器都有尤其老旧内核。对数据交互、异步流程控制熟练。能在复杂业务逻辑中写出可维护的代码。这套笔试题的分布也印证了这一点HTML/CSS考页面布局和标签语义JavaScript考作用域和数据变换算法只考数组去重、排序这类实用场景不考脑筋急转弯。一切都贴着实际工作需求来这在2017年的校招里属于比较务实的一套题。2. 核心考点逐项拆解哪些题是分水岭2.1 HTML与CSS看着送分实际全是细节这套题里的HTML/CSS部分印象里重点考了三块语义化标签、盒模型、经典布局。语义化标签这道题很多人能答出header、nav、main、footer这些新增标签但问“为什么用语义化标签”就卡住了。这里要答三层一是SEO搜索引擎能理解页面结构二是无障碍访问读屏软件可以按landmark跳转三是代码可维护性团队协作时看一眼标签就知道区块作用。用友这种公司做B端系统特殊用户群体比如财务人员用读屏软件并不是小概率事件所以语义化不是口号。盒模型更经典标准盒模型和IE盒模型的区别、box-sizing: border-box的应用场景几乎是送分题。但坑在会延伸考一个元素width设成200pxpadding左右各20pxborder左右各2px标准盒模型下实际占位是多少答案是244px。这种小学数学级别的计算考试时一紧张就容易算错建议用公式记标准盒模型总宽widthpadding2border2IE盒模型总宽width含padding和border。布局题考的是两栏/三栏布局要求“左侧固定宽度右侧自适应”。写出浮动、绝对定位、flex三种方案是基本操作但题里往往加一个约束“中间部分要优先渲染”这时浮动布局就失效了得用flex的order属性或双飞翼布局。这个考点放到今天依然有效因为企业后台的列表页、详情页大量使用这类结构。2.2 JavaScript一套题里真正的重头戏这套笔试题在JavaScript部分的占比是最高的题目设计很有层次感从“知不知道”到“会不会用”再到“能不能变通”逐级递进。第一层是基础语法现象比如变量提升。console.log(a); var a 10;输出什么答案是undefined不是报错也不是10。很多非科班同学第一次接触会懵这里要理解JavaScript的编译阶段会先把var声明提升到作用域顶部但赋值留在原处所以读取到的是已声明但未赋值的undefined。第二层是闭包。典型题目是循环里用var绑定事件问点击输出什么。经典陷阱for (var i 0; i 5; i) { setTimeout(function() { console.log(i); }, 1000); }输出的是5个5不是0、1、2、3、4。原因是setTimeout的回调函数在循环结束后才执行而此时i已经变成5所有回调共享同一个变量。解决办法可以用let声明块级作用域也可以套一层立即执行函数把i作为参数传进去。这套题考的就是这种“能不能说出为什么”而不是背答案。第三层是原型链。用友这套题里出现过一个经典的构造函数题目function Person(name) { this.name name; } Person.prototype.sayHello function() { return Hello, this.name; }; var p new Person(Tom);然后问p.sayHello()的this指向谁、如果执行var fn p.sayHello; fn()会怎样。后者会输出“Hello, undefined”——因为函数单独调用时this指向window严格模式下是undefined而window上没有name属性。这就是考查原型方法和this绑定的组合理解。2.3 算法题难度不大但考验基本功是否扎实这套题里的算法部分基本是数组去重、字符串反转、排序、数组扁平化这些。放到LeetCode横行的今天看简直是小菜一碟但2017年校招考这些是有道理的企业级前端面对的数据处理场景90%是这类基础操作而不是动态规划。数组去重这道题有多个层次的写法。最简单的是用Setconst arr [1, 2, 3, 4, 2, 3]; const unique [...new Set(arr)];但面试官会追问如果数组里同时有数字1和字符串1你这个去重会把它们合并吗Set的去重是基于严格相等SameValueZero数字1和字符串1类型不同不会合并。所以答案是“不去重”这正好是考察对Set机制的掌握程度。如果要求手写去重而且不能用Set就要用对象键值对或indexOf。用对象键值对时有个坑键名会被转成字符串{true: 1}和{true: 1}无法区分。老手会直接用Object.create(null)作为Map的替代品或者用Map数据结构来避免这个问题。2.4 网络与浏览器原理容易被忽略的分数这套题里网络相关的题目占比不高但属于“会者不难”的送分题每年失分的人却不少。典型题目包括HTTP状态码语义、GET与POST的区别、浏览器输入URL到页面展示的过程。状态码考的是理解而不是背诵200是成功、301是永久重定向、302是临时重定向、304是协商缓存命中、403是拒绝访问、404是资源不存在、500是服务器内部错误、502是网关错误。其中有个易错点301和302的区别。301之后浏览器会缓存重定向不再请求原地址302每次都重新走一次。企业级系统做域名迁移时用得最多这个区分在实战里很重要。GET和POST的区别是另一道高频题要答出表面区别参数位置、长度限制、是否缓存、是否可收藏和数据层区别POST更安全但注意HTTP明文传输下都不安全真正的安全要靠HTTPS。这套题的有意思之处在于很多同学回答“GET用于获取数据POST用于提交数据”这恰恰不是标准答案——GET也可以带请求体POST也可以只获取数据。语义上的约定和协议层面的能力是两回事能说出这层才算高分。3. 典型题目实战推演从读题到写出满分答案3.1 布局题三栏布局的完整解题步骤用友这套题里有一道三栏布局题左右各200px中间自适应且要求中间栏优先加载。我当时踩过坑后来整理了一套标准解法第一步判断约束条件。“中间优先加载”意味着在HTML结构中中间DOM必须写在最前面不能因为布局需要而调整HTML顺序。第二步选择技术方案。纯浮动布局在这个约束下无法实现“中间优先加载”的视觉正确性因为中间元素如果写在最前面浮动后两侧元素会掉到下一行。经典解法是圣杯布局或双飞翼布局利用margin负值把两侧元素拉回原位div classcontainer div classmain中间内容/div div classleft左栏/div div classright右栏/div /div.container { padding-left: 200px; padding-right: 200px; } .main { float: left; width: 100%; } .left { float: left; width: 200px; margin-left: -100%; position: relative; left: -200px; } .right { float: left; width: 200px; margin-left: -200px; position: relative; right: -200px; }第三步如果允许用现代布局直接上flex一行代码解决.container { display: flex; } .left, .right { flex: 0 0 200px; } .main { flex: 1; }而且flex天然支持通过order属性调整视觉顺序HTML里main写在前面只要给left设order: -1视觉上依然左边。这道题我在讲解时一直强调布局方案没有唯一答案重点是你能不能说清楚每种方案的适用边界这比默写代码更重要。3.2 闭包题层层递进的追问链有一道题是写出代码执行结果并解释闭包是什么。题目大致的形态是function outer() { var count 0; function inner() { count; return count; } return inner; } var fn outer(); console.log(fn()); console.log(fn());输出1和2这算入门级别。进阶追问是outer执行完后count变量为什么没有被垃圾回收因为inner函数还保持着对outer作用域链的引用这个引用关系导致count所在的变量对象仍然可达GC阶段不会回收它。闭包的本质不是“函数套函数”而是“函数携带了它定义时的词法作用域”。再进阶一步会问闭包的性能问题。每次调用outer都会创建新的变量对象和新的inner函数如果这个函数被大数组里每个元素引用内存占用会明显上升。所以实际编码时如果不需要保持私有状态不要随意用闭包包裹大函数。这也是为什么企业级代码评审里会有人坚持“能用class就不用闭包来模拟私有属性”不是风格之争是性能可预测性的权衡。3.3 排序题从冒泡到手写快排的解题节奏这套题里排序相关题目通常不要求背快排模板而是给一个已经写好的冒泡排序要求指出时间复杂度、优化空间。这比白手写算法更难因为你得能看懂别人的代码并发现缺陷。冒泡排序的时间复杂度是O(n²)优化点有两个。一是如果某一轮没有任何交换说明已经有序可以提前退出二是每轮比较的范围可以缩短因为末尾元素已经排好无需再参与比较。优化后的代码function bubbleSort(arr) { var len arr.length; for (var i 0; i len - 1; i) { var swapped false; for (var j 0; j len - 1 - i; j) { if (arr[j] arr[j 1]) { [arr[j], arr[j 1]] [arr[j 1], arr[j]]; swapped true; } } if (!swapped) { break; } } return arr; }这个解法在考试里属于“满意答案”因为面试官考的不是手速而是你有没有意识到冒泡排序的优化前提是“部分有序的数组”。如果数组完全逆序那提前退出机制形同虚设复杂度依然是O(n²)。3.4 事件循环题异步输出的顺序陷阱这套题里有道异步执行顺序题典型的就像这样console.log(a); setTimeout(() { console.log(b); }, 0); Promise.resolve().then(() { console.log(c); }); console.log(d);正确答案是a、d、c、b。这里考的是对“宏任务”和“微任务”的理解同步代码先执行微任务队列Promise.then在当前同步任务结束后立刻执行宏任务队列setTimeout在下一轮事件循环才执行。我见过很多同学栽在这题上因为从表面上看setTimeout的0毫秒延迟好像应该立即执行。这里要给一个更实用的记忆方式微任务是插队宏任务是排队。当前线程把同步代码跑完后会先清空微任务队列然后才从宏任务队列取下一个任务。2017年那会儿Promise正在普及所以这套题考微任务其实很前卫很多老前端人还没形成这个意识。4. 应考策略与高频丢分点实录4.1 笔试题的时间分配技巧用友这套题的题量不小主观题和编程题混在一起整体时间通常在90分钟左右。我的建议是先做简答和编程题再做选择填空。理由很简单编程题分值高且需要思维状态在线选择题里有些纠结题会消耗大量时间一纠结就是十分钟还不一定做对。先把能拿满分的高分题解决掉再回头处理那些模棱两可的题目心态会稳很多。另外笔试题答卷时不要留白。即便某道编程题完全不会也要写出思路、写出伪代码、写出你能想到的API名。面试官看卷子时看到“不会但知道思路”和看到“空白”是完全不同的评价。前者说明有潜力、有解决问题的基本框架后者直接归入基础不扎实。4.2 高频丢分点从失分题反推复习方向第一个高频丢分点是this指向尤其是隐式绑定丢失的场景。var fn obj.method; fn()这类代码在笔试里一考一个准。这个知识点必须做到能不看资料推导出结果调用点决定this谁调用this就指向谁没调用者就是全局严格模式undefined。第二个高频丢分点是HTTP缓存相关。ETag和If-None-Match的区别、Cache-Control的max-age与no-cache的区别这两组概念非常容易混淆。用一句话记no-cache表示“使用缓存前必须向服务器验证”不是“不缓存”no-store才是“完全不缓存”。企业系统的数据更新频率差异很大缓存策略设计的正确性直接影响用户看到的数据是否最新。第三个高频丢分点是数据类型的隐式转换。1 2是123 * 4是12[] []是空字符串[] {}是[object Object]。这些题看着偏门但实际上Web开发里从URL参数、表单校验里取出的一堆值都是字符串能不能预判类型转换结果决定了你会不会写出“永远不成立”的判断条件。4.3 面试官从笔试题中衍生出的追问清单笔试交上去后面试环节会围绕卷面做二次提问。我接触过的用友系面试官比较喜欢追问这几类问题原型链的尽头是什么答案是Object.prototype它的原型是null。追问为什么要有null作为终点因为需要给查找链条一个明确的结束标记。闭包里如何访问外部函数的this典型场景function outer() { var self this; setTimeout(function() { console.log(self.name); }, 0); }用箭头函数也可以直接沿用外部this。这两者的差别值得展开理解箭头函数没有自己的this它继承定义时所在作用域的this这在React类组件和Vue选项中处理回调时非常有用。什么场景下会主动使用闭包标准答案是防抖、节流、模块化私有变量。能说清楚防抖函数里timer变量的存活周期就说明对闭包的理解不是背出来的。4.4 复习资料与刷题路径建议针对这套题我给一个四步复习法第一步把JavaScript高级程序设计里的“变量、作用域与内存”和“函数表达式”两章翻熟这套题80%的JavaScript考点都出自这两章。第二步上牛客网做近五年前端校招真题不用贪多每天一套重点看错题解析里关于“为什么错”的解释。第三步剑指Offer的简单题挑着刷重点覆盖数组、字符串、链表不用追求Hard题。企业级前端面试的算法目标是验证“能写代码”不是“能拿竞赛奖”。第四步针对自己的简历项目准备一两段代码细节面试官大概率会问“这段代码为什么这样设计”比刷题更能体现工程能力。5. 技术演进之后这套题还能给我们什么5.1 从用友的产品线反推前端技术要求用友是做企业服务软件起家的产品线从财务软件扩展到云平台前端的复杂度和传统互联网公司完全不同。这类企业级B端产品的特点非常明显页面数量多、业务逻辑重、权限模型复杂、需要兼容老浏览器。所以笔试里考布局、考闭包、考原型链本质上是匹配产品形态的。如果你面试的是这类公司不要只刷框架题要做做jQuery时代的原生JavaScript题它们考察的核心能力在如今依然不过时。5.2 今天再看这套题的可取与过时之处这套题的可取之处在于对JavaScript语言机制的考察放到2025年依然成立。语言核心机制、异步模型、原型体系没什么大变化理解透彻的人写Vue3、写React也好写后端Node.js也好底子都在。过时之处也很明显没有考ES6模块化没有考前端工程化Webpack构建流程、模块热更新原理没有任何框架题。用当下标准看这份考卷对“现代前端”的覆盖是不完整的。不过这不是瑕疵而是时代背景。2017年正是Vue 2刚火、React 16刚发布、TypeScript还在普及前的阶段校招笔试用基础题来筛人是正常的。5.3 如果我要按这套题的风格设计今天的模拟卷如果今天让我出一套风格相似的模拟卷我会保留原型链、闭包、事件循环和布局题再替换一部分内容增加TypeScript的类型体操基础题比如PartialT的实现原理。增加模块化相关题目比如ES Module与CommonJS的差异。增加浏览器渲染机制题目比如重排和重绘的触发场景。增加一道Vue或React的响应式原理简述题。但核心设计原则不变考底层、考变通、考业务场景下的综合应用。所以我的建议是刷这套2017年的题重点刷思路而不是期望在考场上遇到原题。原题大概率不会重复但“为什么闭包会造成内存泄漏”“为什么布局要优先渲染中间区域”“为什么微任务先于宏任务”这些问题换个场景还会继续考。最后再分享一个小技巧。刷这类题的时候不要看一道做一道按主题分批刷比如今天只刷闭包相关的所有变体明天只刷布局。人的大脑对同主题的信息密集轰炸时记忆效率和理解深度远高于来回切换。我当时用这个方法两周时间就把这套题背后的知识点串起来了后面做任何一家公司的校招真题JavaScript部分都没有怎么丢过分。
返回列表