尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

2019用友前端笔试题解析:基础能力与工程素养考察要点

2019用友前端笔试题解析:基础能力与工程素养考察要点 2019年那会儿前端校招的笔试题目已经相当有区分度了。用友这套题我印象里不算偏怪但覆盖面很扎实属于那种“基础不牢就露馅”的类型。今天不聊空泛的面经直接拿这套笔试题当切片拆一拆它背后到底在考什么、为什么要这么考以及如果你现在要准备类似的笔试该往哪些方向使劲。1. 整体设计与思路拆解用友这套题到底在筛选什么样的人先说结论用友2019校招的前端笔试题三整体定位是“基础能力扫描工程素养初筛”。它没有故意出偏题怪题也没有追当时已经有点过热的新框架细节而是把精力集中在计算机基础、JavaScript语言特性、浏览器工作原理、CSS布局能力和基础算法这五块。为什么是这个组合用友的业务线以企业级应用为主这类产品对前端的要求不是“炫技”而是稳定、可维护、团队协作时不容易踩坑。所以笔试环节重点看三件事候选人有没有扎实的语言基本功尤其是JavaScript的核心机制是不是真懂。能不能理解浏览器环境下页面是怎么渲染的会不会处理异步、性能这类实际问题。有没有基本的算法和逻辑建模能力能不能用代码解决明确的问题。这套题里还有一个隐藏的考察维度审题能力。很多题目题干不长但设置了边界条件比如排序要“稳定”、去重要“保持顺序”。能不能快速、准确地提取这些约束直接反映了以后接需求时会不会漏掉关键点。对比当时其他大厂的笔试题字节跳动和快手的题目更偏向算法和数据结构出题风格接近LeetCode中高难度阿里和腾讯更看重场景设计会给你一个业务场景让你设计方案用友的题则更接近“课本知识常见实践”的组合难度适中但对基础概念的精确度要求很高。换句话说这套题是给“基础扎实但还没刷太多算法题”的同学准备的它更看重你是否能稳定输出可靠代码。所以如果你现在打算投企业服务类公司或者想检验自己的前端基础是不是有漏洞拿这套题当自测非常有价值。通过它你能快速定位出自己在JS语言机制、浏览器原理、CSS细节、编码规范这几个维度上的短板。2. 核心考点解析从题目回推前端必须掌握的知识体系这套题覆盖的知识点如果归类大致可以分为四个方向。每个方向我都会结合当年题目里常出现的形态讲讲它背后的考察重点和应对思路。2.1 JavaScript基础与手写代码考察的是“你真的理解”而不是“你背过”这一块在笔试题里占比最重。常见形态有var和let的作用域差异、闭包的实际应用场景、原型链的查找过程、深浅拷贝的区别、this指向的几种绑定规则以及手写实现防抖节流、数组去重、深拷贝、函数柯里化等函数。当年这套题里有一道关于闭包的经典变形题大致意思是在for循环中用var声明变量并绑定事件最终点击时输出的值是什么。很多人知道答案是“最后一次循环的值”但题干再追问一句“怎么改才能得到预期值”这里就分层了只知道用let替换不够你得说清楚let是创建了块级作用域每次迭代都会绑定一个新的变量副本如果面试官追问“不用let怎么实现”你还得能写出用闭包IIFE传参的方案。再比如手写深拷贝这道题很多人都能写个递归但只写递归是不够的。你得考虑循环引用问题否则深拷贝一个包含环形引用的对象时会爆栈你还得考虑Date、RegExp这类内置对象普通复制只会得到空对象或字符串丢失原型方法。更细致的考察点还包括Symbol作为key时能不能遍历到、函数要不要特殊处理、原型链要不要保留。我建议准备这类题目时不要背答案直接用Node把每一种边界情况跑一遍亲眼看看结果印象会深得多。2.2 浏览器与网络基础考察的是“页面性能的底层直觉”这套题里浏览器相关的题目集中在几个方向从输入URL到页面展示的完整过程、重排和重绘的区别及触发条件、HTTP缓存机制强缓存和协商缓存、HTTP和HTTPS的区别、TCP三次握手四次挥手。从URL输入到页面展示这个题几乎是所有校招笔试的必考题用友也不例外。这个题目表面考“流程”其实考的是你有没有把“网络请求”和“页面解析渲染”这两个阶段完整串联起来。很多人写这个题只写到“拿到HTML然后渲染”但漏了关键细节DNS解析是有层级的浏览器会先查本地缓存再逐级向上查询TCP连接是三次握手断开是四次挥手为什么握手要三次而挥手要四次这个“为什么”比“多少次”更重要HTTP请求发出后浏览器解析HTML时遇到CSS会阻塞渲染遇到script标签会阻塞解析所以才有CSS放头部、JS放底部的实践建议。按顺序完整答出这些阶段说明你有系统性的知识结构而不是零散地看过几篇博客。重排和重绘也是常客。出题方式通常是给几个操作场景问你哪些会触发重排、哪些只触发重绘。读offsetWidth、写style.width这些操作前者会强制同步布局后者如果前面攒了一批待处理的样式变更再立刻读布局信息浏览器会被迫提前做一次重排这就是layout thrashing的原理。能答到这一层基本就通过筛选了。HTTP缓存题当年也出现过通常给你一组请求头字段让你判断命中强缓存还是协商缓存以及服务端返回304后浏览器怎么处理。这里容易混淆的是强缓存不需要发请求直接从本地读取对应Expires或Cache-Control的max-age协商缓存一定有一次请求如果资源没变服务端返回304浏览器再使用本地缓存。要注意Cache-Control优先级高于Expires以及no-cache并不是“不缓存”而是“每次使用前都要到服务端验证”。2.3 CSS布局与样式细节考察的是“页面还原能力”CSS在笔试题中的呈现方式比较传统但很能拉开差距。常见的有flex布局的几种核心属性及其计算规则、水平垂直居中的实现方案、两栏和三栏布局的实现、盒模型标准模型和IE模型的区别、margin塌陷和BFC。垂直居中这个题面试官一般不会满足于你只会一种方案。你得至少掌握flex方式父元素display:flex子元素margin:auto或父元素设置justify-content和align-items为center、绝对定位加transform、grid布局、以及老式的table-cell方案。每种方案的适用场景和限制也要说得清楚比如绝对定位的方案要求父元素有明确高度transform方案在子元素有文字模糊的极少数情况下会有字体渲染问题。两栏布局、三栏布局在当年也是高频题虽然现在flex已经非常简单但笔试还是会问。圣杯布局和双飞翼布局就是那个时代的产物它们考查的核心是浮动定位的原理、负margin的理解、以及如何让中间列优先渲染。虽然现在实际开发中已经很少手写这两种布局了但理解它们的历史背景和原理能让你更清楚flex和grid到底解决了什么问题。margin塌陷和BFC这道题也几乎年年出现。父元素没有padding或border子元素的margin-top会把父元素一起顶下来这就是经典的塌陷。解决方法就是给父元素创建BFCoverflow:hidden、float、display:inline-block、position:absolute等都能触发。理解了BFC的规则你就能解释清楚为什么overflow:hidden能解决这个问题因为它创建了一个独立的渲染上下文子元素的margin就不会溢出到外部。2.4 框架与工程化基础考察的是“开发效率意识”2019年这个时间点Vue和React已经是绝对主流用友的笔试题里也会涉及框架层面的基础认知。不过这套题里的框架题难度不大更多是概念性的Vue中v-if和v-show的区别、Vue组件间通信的方式、computed和watch的区别、虚拟DOM的作用React中state和props的区别、key的作用等。v-if和v-show的区别是最基础的一类。v-if是惰性的初始条件为false时元素不会被渲染切换时会销毁和重建DOMv-show则始终渲染通过display:none来控制显隐。所以高频切换用v-show低频、初始不展示用v-if这是一条非常实用的经验。computed和watch的区别则是高频进阶题。computed有缓存只有依赖的响应式数据变化时才重新计算适合“由一个状态推导出另一个状态”watch是监听某个值的变化然后执行回调适合“一个值变化后需要做异步操作或副作用”。很多人把这两个混用其实设计理念完全不同。虚拟DOM和key的作用也值得认真准备。虚拟DOM不是“比真实DOM操作快”这么简单它的真正价值在于用JS对象描述DOM结构在状态变化后通过diff计算出最小更新范围再批量更新真实DOM。key的作用是帮助diff算法识别哪些节点是复用的如果用index做key列表中间插入或删除元素时容易导致组件状态错乱。这个考点直到今天依然是高频面试题。工程化相关的题目2019年还没有现在这么卷。一般会问你webpack构建的基本流程、loader和plugin的区别、常用loader有哪些、怎么做代码分割。现在再准备的话还需要补充Vite的整体思路、ESM和CommonJS的区别等因为工具链迭代太快了。3. 实操过程与思路复盘用真题视角拆解题思路笔试不是面试没有追问机会所以答题方式很重要。下面拿几个经典类型的题目走一遍完整的解题思路。3.1 手写防抖函数从基本实现到边界优化当年笔试里经常出现类似“手写一个防抖函数”的题目。首先你要理解防抖的应用场景搜索框输入联想、窗口resize事件、按钮点击防重复提交。防抖的核心思想是事件触发后不立即执行而是等待一个时间窗口如果窗口内再次触发就重置计时器。基础版实现大概长这样function debounce(fn, delay 300) { let timer null; return function (...args) { if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(this, args); }, delay); }; }这里有两个细节需要注意第一个是this指向如果内部直接用fn(args)而不是fn.apply(this, args)那么当事件处理函数里需要访问this时就会出问题。第二个是参数透传用...args收集参数再透传给原函数保证原函数能拿到事件对象。如果你还想展示一点进阶能力可以补充一个“立即执行”版本的防抖即第一次触发时立即执行之后在延迟窗口内的触发都被跳过function debounceImmediate(fn, delay 300, immediate true) { let timer null; return function (...args) { const callNow immediate !timer; if (timer) clearTimeout(timer); timer setTimeout(() { timer null; }, delay); if (callNow) fn.apply(this, args); }; }笔试时如果能写出带immediate选项的版本明显比只写基础版更有竞争力。3.2 数组去重从暴力解法到多种边界方案数组去重也是一道经典手写题。最直接的解法是用Setfunction unique(arr) { return [...new Set(arr)]; }一行代码看起来很漂亮但笔试的边界条件往往会升级如果要求去重后保持元素相对顺序用Set天然满足。如果数组里包含对象以某个属性为去重依据呢这时候Set就不够用了得用Map或对象做标记function uniqueBy(arr, key) { const seen new Map(); return arr.filter(item { if (!seen.has(item[key])) { seen.set(item[key], true); return true; } return false; }); }如果数组里有NaNset的去重结果是能正确去重的因为Set内部使用SameValueZero算法但普通对象作为key时会有字符串化的坑。这些细节都能体现你是否真的遇到过这些问题。3.3 经典排序不只写出来还要知道怎么选排序题在笔试题里也很常见常见要求是手写快速排序或归并排序。快速排序的普通实现很多但要注意如果每次递归都创建新数组空间复杂度是O(n log n)原地排序的空间复杂度是O(log n)。笔试时最好写原地版本不然面试官追问起来容易露怯。一个常见考点是sort函数默认是按字符串编码排序的所以[10, 9, 8].sort()会得到[10, 8, 9]要传比较器函数。另外稳定排序这个概念在企业级应用里很重要比如表格先按时间排序再按城市排序时如果排序算法不稳定相同城市的记录可能会打乱之前的时间顺序。3.4 场景手写题设计一个“带并发限制的异步调度器”用友当年这类题虽然不常出现但设计题能很好地体现工程能力。比如让你实现一个调度器保证最多同时执行N个异步任务。这个题考的是Promise、队列和控制并发实现思路大致如下class Scheduler { constructor(limit) { this.limit limit; this.running 0; this.queue []; } add(task) { return new Promise(resolve { this.queue.push({ task, resolve }); this.run(); }); } run() { while (this.running this.limit this.queue.length) { const { task, resolve } this.queue.shift(); this.running; Promise.resolve(task()).then(value { resolve(value); }).finally(() { this.running--; this.run(); }); } } }这里的关键是每个add返回一个Promise让外部可以await到任务真正完成内部维护一个队列把task和resolve包装在一起当某个任务结束后running减一再自动从队列取出下一个任务执行。这样整个调度器就是一个“队列水龙头”的模型控制同时运行的数量。4. 常见问题与排查技巧这些坑几乎人人都踩过4.1 拿到一道题没思路怎么办笔试时最怕的就是看到题目大脑空白。我自己踩过几次坑之后总结出的经验是先看输入输出确定边界条件再想算法。如果算法一时想不出来先写暴力解法通过率和代码可读性都比空着不写强太多。很多笔试题是按测试用例得分跑通几个算几个先保底再优化。4.2 代码能跑但题目要求“手写实现”怎么办有些题目比如new的实现、bind的实现、instanceof的实现考查的就是你能不能脱离语法糖从底层原理实现它。这时候只写const instance new Foo()是不行的。你需要对JavaScript的底层机制有真正的理解比如new的过程是创建一个新对象、把原型链指向构造函数的prototype、把构造函数的this绑定到新对象上、如果没有显式返回对象则返回新对象。4.3 浏览器缓存题总是记混怎么办我建议不要死记字段名而是用“要不要发请求”作为分界线。先判断这个请求到底发没发出去没发出去就说明命中了强缓存涉及Cache-Control/Expires发出去了再看服务端返回什么如果返回304说明命中了协商缓存涉及ETag/If-None-Match、Last-Modified/If-Modified-Since如果返回200就是重新拉取资源了。这个思路在写题时非常好用抽象成“是否发请求”这个维度就不会混。4.4 布局题怎么写才能让阅卷人觉得你熟练首先是方案数量至少两种以上其次要写清楚每个关键属性的作用不要只是堆代码最后一定要说适用场景。比如flex适合一维布局grid适合二维布局float布局主要用在图文环绕场景。阅卷人看的是你“会选型”而不是“会堆代码”。多写一点设计思路的说明往往比代码本身更占优势。4.5 时间分配与答题顺序这也是一个非常实际的技巧。笔试时间有限我一般建议先快速浏览一遍所有题目做到心里有数然后优先做会做的、能拿到分的题不要在一道难题上死磕超过15分钟。手写代码的题先把主流程写出来再去补边界条件。如果最后还有时间再回头优化。这里有一个很现实的问题很多笔试题即使你答得不够完美只要把思路写清楚也会有不小的概率进入下一轮。写一点“思路是xxx由于时间原因先这样实现”之类的注释有时候会很管用。4.6 不同公司的笔试风格差异如果时间充裕最好针对不同公司做差异化准备。用友这类企业服务公司更看重基础、规范和工程意识互联网大厂更看重算法和系统设计外企可能会考英文题目和更多数据结构题。你提前研究一下目标公司的历年真题大概就能摸清出题风格。准备笔试不是把所有知识点平均用力而是根据目标公司集中突破。5. 后续可以怎么继续深挖这套题的价值这套题虽然来自2019年但它的知识点体系到现在依然没有过时。JavaScript核心机制、浏览器渲染原理、HTTP缓存、CSS布局、框架基础这些依然是前端面试的核心范围。变化的是工具链和框架细节。如果你刚做完这套题我建议你做一次“错题归因”不要只改答案要把每道错题背后的知识点重新梳理一遍。具体操作是准备一个错题本写成“题目描述我当时怎么想的错在哪正确思路相关延伸知识点”的格式。这个习惯坚持下来比反复刷三遍题都管用。另一点是把笔试里的手写题整理成一个独立清单包含防抖节流、深拷贝、Promise相关、数组去重、几种排序、new/bind/instanceof实现等。这个清单就是你的“考前冲刺手册”面试前半小时过一遍效果很明显。这套题也让我想起一个当年一起准备校招的室友他不刷题而是把每一个知识点都推演一遍能做到“看到题目知道出题人想考什么”。这种能力需要大量的积累才能练成但只要从一套真题开始一个知识点一个知识点地啃你也能慢慢建立这种感觉。前端这个领域更新快但底层知识反而是最保值的那部分投资值得花时间把它打牢。
返回列表