用友2019校招Web前端笔试题解析:JS基础、Vue与手写题考点

📅 发布时间:2026/9/1 17:15:55
用友2019校招Web前端笔试题解析:JS基础、Vue与手写题考点
秋招刷题那会儿我拿到一套《用友2019校招web前端笔试题一》做完最大的感受是这套卷子比大多数互联网大厂的基础题更“实在”。它没有偏题怪题也没有动辄让你手写红黑树但每个考点都踩在web前端开发真正用得到的地方。无论你现在备战校招还是刚工作一两年想回头检验一下自己的前端基础这套题都值得一道一道过一遍。这篇文章我不打算把整套卷子原封不动复述出来那样对读者没有增量。我更想按这套题里最高频、也最容易被忽略的几类考点把背后的原理、答题思路、以及我踩过的坑拆开来讲。文章会涉及JavaScript基础、CSS布局与浏览器原理、Vue框架核心、手写代码题四个大块最后聊聊复盘时的真实体会。先提个醒这套题有不少题是“一题多考点”的出法表面问A实际考察B所以分析的时候我会多往底层牵扯一层这样对面试和实际项目都有帮助。1. 一张卷子背后的企业需求用友校招前端在筛什么人1.1 传统软件厂商与互联网大厂的出题差异用友这类老牌企业软件厂商产品和互联网大厂完全不同。它的核心业务是ERP、财务系统、人力系统、数据中台这些toB产品意味着前端同学日常面对的不是铺满动画和炫技效果的C端页面而是大量表单、表格、复杂交互的中后台系统。这种产品形态直接决定了企业招人的标准可以不会炫酷的动效库但必须把JavaScript基础打牢把数据管理和组件通信吃透写出来的代码要稳定、可维护、经得起多人长期迭代。所以对比下来你会发现一个很有意思的差异互联网大厂笔试题常问算法、框架源码、设计模式用友这类企业更爱考闭包、事件循环、浏览器渲染原理、Vue响应式数据这些“基础中的基础”。原因很简单toB系统的页面逻辑复杂数据流转链路长一个闭包引用错误可能导致整个表单状态错乱一次不当的DOM操作可能引发大面积重排。笔试题看起来“传统”其实背后都是真实业务场景的缩影。我当时做完这套题的最大感触就是“这卷子是在筛一个能直接上项目干活的人而不是一个只会背八股文的人。”1.2 卷面结构里藏着的筛选逻辑一套标准的校招前端笔试题通常按难度和考察维度分层设计。客观选择题用来做海量初筛覆盖知识面广从基础语法到浏览器、网络、性能优化都有涉及手写代码题用来考察知识深度和临场工程能力看你拿到一个需求能不能快速写出高质量代码场景设计题则考察业务抽象能力比如给定一个组件需求你怎么设计数据流和组件拆分。用友这套2019校招笔试题一的结构也遵循这个逻辑。选择题里JavaScript和CSS占比最高其中原型链、this指向、闭包几乎必考手写题则集中在防抖节流、深拷贝、数组去重、事件总线这类常用工具函数上。这里有一个求职者需要特别注意的信号选择题的错题率可能影响你是否进面试但真正决定你面试起点高低的往往是手写题的完成质量。很多同学笔试分数不错一到技术面被追问手写题的边界条件就露馅因为面试官会顺着你的代码继续深挖。所以这套卷子的正确打开方式不是对完答案就完事而是每道错题都要往下钻两层搞清楚它到底在考什么知识点网络里的哪一环。2. JavaScript基础决定你的下限三大高频考点拆解2.1 原型与原型链别只背结论要能画出查找链路原型链题几乎是每套前端笔试题的必考题用友这套也不例外。但很多人在准备时有一个误区只记住了“实例的__proto__指向构造函数的prototype”这句话遇到具体题目还是错。我建议你把这条查找链路完整画出来画一次比背十遍都管用。比如有一个构造函数Personnew Person()得到实例p那么p.__proto__指向Person.prototypePerson.prototype.__proto__指向Object.prototypeObject.prototype.__proto__是null。这条链路里任何一个环节都可以出选择题。题目可能会问“p.hasOwnProperty(name)能不能调用”“Person.prototype.constructor指向谁”“instanceof的判断依据是什么”等。还有人容易在Function和Object的特殊关系上翻车比如Function.prototype Object.proto或者“Function instanceof Object和Object instanceof Function分别是什么”这类题表面考instanceof实际考你对原型链全貌的理解。回答这类题我给你一个通用思路遇到一个属性查找问题先定位对象的完整原型链再沿着链路逐层找属性找到就返回找不到就报undefined或继续往上。手写题如果要求实现instanceof也可以用这个思路判断右边构造函数的prototype是否出现在左边对象的原型链上。面试官真正想看的不是结论而是你能不能把这个机制讲透。2.2 闭包与作用域链for循环加setTimeout这套组合题闭包题在笔试题里出现频率极高最常见的出题姿势是“写出以下代码的输出”for (var i 0; i 5; i) { setTimeout(function() { console.log(i); }, 1000); }答案是连续输出5个5而不是0、1、2、3、4。原因在于var声明的i是函数作用域循环结束后i已经变成5而setTimeout回调函数是在循环结束之后才执行的它访问的是同一个变量对象里的i。这就是闭包的典型效果内部函数保留了对外部作用域变量对象的引用哪怕外部函数已经执行完成。但光会背答案不够改法也得能解释清楚。第一种改法是把var换成let因为let是块级作用域每次循环都会创建一个新的词法环境i的值被正确保存第二种改法是借用IIFE立即执行函数包一层把每次循环的i作为参数传进去第三种改法是把setTimeout放进一个工厂函数里返回闭包。三种改法背后对应的是作用域和闭包的不同理解角度。这里要特别提醒一下闭包的双刃剑效应闭包能帮我们封装私有变量、实现模块化但也会让变量长期驻留内存。如果闭包引用了一个庞大的对象而你又没有及时置空引用就可能造成内存泄漏。笔试题如果问“闭包的缺点是什么”一定要答到内存占用和释放问题这才是加分项。2.3 this指向与call/apply/bind一套判断口诀搞定选择题this指向是JavaScript里最容易混淆的知识点之一。但是别慌只要掌握一套完整的判断规则选择题基本都能秒杀。规则可以归纳成四种绑定方式默认绑定函数独立调用时非严格模式下this指向window严格模式下指向undefined隐式绑定obj.fn()这种通过对象调用函数的场景this指向该对象显式绑定通过call、apply、bind手动改变this指向new绑定通过new调用构造函数时this指向新创建的对象。优先级从高到低是new绑定大于显式绑定显式绑定大于隐式绑定隐式绑定大于默认绑定。箭头函数不绑定this它会继承外层词法作用域的this所以不能用call、apply、bind强行改变箭头函数的this指向。还有一个容易被忽视的细节给call、apply、bind传null或undefined时在非严格模式下this会落回window在严格模式下则保持null或undefined。很多真题故意挖这个坑比如var obj { name: test }; function foo() { console.log(this.name); } foo.call(null);在非严格模式下this指向window如果window上没有name输出undefined在严格模式下this是null直接报错。这类题一出现就能刷掉不少人。我的考前建议是把上述几条规则整理成一张纸做选择题时先圈出“函数是怎么被调用的”再套优先级表基本不会错。3. CSS与浏览器原理布局题和渲染题怎么做到不失分3.1 高频布局题水平垂直居中、两栏三栏布局的实现布局题在笔试题里属于纯送分题但很多人在手写时只能写出一种方案或者写出来的代码有兼容性问题。我建议至少掌握flex、grid、定位三种常用的水平垂直居中实现并清楚各自的适用场景。flex方案最省事父容器设置display:flex、justify-content:center、align-items:center子元素自动居中不需要知道子元素宽高。绝对定位加transform方案也很常用父容器相对定位子元素绝对定位且top和left为50%再用transform: translate(-50%, -50%)回移自身宽高的一半好处是不需要知道子元素具体尺寸。grid方案在网格布局场景下很干净父容器display:grid、place-items:center即可。笔试题如果要求多写几种方案建议把这三类都写上。两栏布局考得最多的是左侧固定宽度、右侧自适应实现方式有flex左侧定宽右侧flex:1、浮动加BFC左侧float:left右侧overflow:hidden、或者grid的grid-template-columns: 200px 1fr。三栏布局除了flex和grid还会考圣杯布局和双飞翼布局。这里我想说的是笔试答案不仅要求“能实现”还要求“能说明优缺点”。比如flex布局简单灵活但如果在老项目里要考虑IE11grid的有些特性就要谨慎浮动布局兼容性好但需要处理清除浮动的问题。答题时把方案选的考虑写出来面试官会明显感觉到你是有实际项目经验的人而不是只会背代码。3.2 浏览器渲染机制与重排重绘toB场景的性能考点关于浏览器的问题是前端笔试的常客但很多人的回答停留在“从输入URL到页面渲染”的背诵流程上。用友这套题更关注的其实是渲染过程中的性能瓶颈比如重排和重绘。先理一遍关键渲染路径浏览器拿到HTML后解析成DOM树解析CSS构建CSSOM树两者合并生成渲染树然后进行布局计算每个节点的几何位置再进行绘制最后合成为用户看到的画面。当JavaScript修改了DOM的几何属性比如宽高、边距、位置浏览器需要重新计算布局这就是重排如果只修改颜色、背景、visibility等外观属性浏览器只需要重新绘制这就是重绘。重排一定会触发重绘但重绘不一定触发重排。在复杂的中后台页面里频繁重排是卡顿的主要原因。笔试题最常见的问法是如何减少重排。答题方向可以从几个维度展开合并DOM操作把多次修改放到一个DocumentFragment里再一次性插入使用class批量修改样式避免逐条修改内联样式避免频繁读取offsetWidth、clientHeight这类强制布局属性用transform代替top、left做动画เพราะtransform只触发合成不触发布局计算。这些都是实测有效的优化手段而且写到简历项目里也是亮点。我在实际开发中踩过大面积表格重新渲染导致页面卡死的问题后来就是靠减少重排和虚拟列表解决的这类经验在面试里讲出来比任何背诵都有说服力。3.3 选择器优先级一道看似简单实际送命的题CSS选择器优先级是个基础得不能再基础的考点但每次笔试都能筛掉不少人。原因在于题目经常把内联样式、!important、继承样式混在一起考答案一不小心就错。优先级计算规则可以理解为一套权重体系!important最高然后是内联样式接着是ID选择器再是类选择器、属性选择器和伪类最后是元素选择器和伪元素。比较优先级时把每条规则的选择器拆开计算权重权重大的胜出权重相同后定义的覆盖先定义的。这里有一个常见误区有人认为后出现的样式一定覆盖前面的其实只有在权重相同的前提下才成立。比如div p .box和#content .box同时命中一个元素无论后者写在多少行最终生效的都是ID选择器权重更高的#content .box。还要注意!important的使用场景和风险。它能强制覆盖其他任何声明但滥用会让样式维护变成灾难。笔试题如果问“你怎么看待!important”角度要全面在覆盖第三方库样式时可以临时用但业务代码中长期依赖!important说明选择器结构设计有问题。作答选择题时我建议永远先数一遍各个选择器的权重不要凭肉眼判断先后顺序这样能避免掉进大多数陷阱题。4. 框架知识点Vue的回答怎么答才显得有功底4.1 Vue响应式原理从Object.defineProperty到Proxy用友的前端体系里Vue用得非常多所以这套笔试题里Vue相关的题目比例不低其中响应式原理是出题频率最高的点。很多候选人能背出“Vue2使用Object.definePropertyVue3使用Proxy”但一被问“具体怎么实现”就卡壳。我建议把整个链路拆开记忆。Vue2响应式的核心是数据劫持加发布订阅初始化时遍历data对象的每个属性用Object.defineProperty把它们改写成带getter和setter的形式组件渲染时render函数读取数据会触发getter在getter里收集依赖当数据发生修改setter里触发依赖更新通知对应的Watcher重新执行渲染。这套机制能工作但存在天然的短板无法侦测对象新增属性和删除属性所以Vue2才提供了Vue.$set和Vue.$delete这两个补丁方法对于数组则通过重写push、pop、splice等原型方法来实现拦截。Vue3改用Proxy从根本上解决这些问题。Proxy可以直接代理整个对象新增删除属性都能拦截数组索引变化和长度变化也能拦截到而且性能更高。如果笔试题要求“比较Vue2和Vue3响应式方案的优劣”就围绕“能否侦测新增删除属性”“数组变更侦测”“性能表现”三个维度展开。回答时如果能顺带提一句“Proxy只能代理一层所以Vue3内部还需要用Reflect配合WeakMap做深层次依赖收集”面试官会立刻对你的源码功底刮目相看。4.2 组件通信、生命周期、computed与watch的辨析组件通信在场景题里出现频率非常高尤其是实际业务中父子通信、兄弟通信、跨层级通信的需求特别常见。答题时我建议先列方案再说明选型理由父向子用props子向父用emit事件兄弟组件用事件总线或Vuex共享状态跨层级用provide/inject复杂项目用Pinia/Vuex统一状态管理。关键是不能只罗列API要说清楚每个方案的适用边界。比如provide/inject适合跨多层传递数据但不适合用于频繁更新或复杂状态流转的场景事件总线在组件少时方便但项目变大后事件名管理混乱容易出隐蔽bug。笔试题给一个具体业务场景你要能根据数据流复杂程度推荐方案这比单纯默写API名字有用得多。生命周期也是必背考点但很多人的背诵停留在“created里请求接口mounted里操作DOM”这种口诀上。笔试题更常考的是父子组件生命周期执行顺序因为实际开发中你会在父组件created里初始化数据、在子组件mounted里绑定事件如果顺序不清晰稍不注意就会拿到undefined数据。顺序可以整理成父beforeCreate、父created、父beforeMount、子beforeCreate、子created、子beforeMount、子mounted、父mounted更新时是父beforeUpdate、子beforeUpdate、子updated、父updated。答这个题时画个时间线图辅助说明清晰度秒杀纯文字描述。computed与watch的辨析也是一道经典送分题。computed是计算属性有缓存只有依赖的响应式数据变化才会重新计算适合模板中需要同步计算的场景watch是监听器适合数据变化后执行异步操作或开销较大的操作。常见坑点有两个computed里不能修改其他响应式数据否则会陷入无限循环watch默认不监听对象内部属性的变化需要设置deep: true但deep监听会带来性能开销大对象上要慎重使用。答这类题时我习惯用一个真实案例说明搜索框的实时联想结果用computed不合适因为要请求接口所以用watch加防抖才合理。这种业务结合的回答要比干巴巴背定义打动人得多。5. 手写代码题从“能跑”到“加分”的三个层次5.1 高频手写题清单与三种解法思维手写题是整张卷子里区分度最高的部分用友这套题里出现的手写题基本都集中在工具函数上比如数组去重、深拷贝、防抖节流、发布订阅、Promise.all、bind实现等。这些题看似简单但如果你只准备了一种解法遇到面试官追问“还有没有更好的做法”时就会露怯。我举数组去重为例。最低限度要能写出Set版Array.from(new Set(arr))。加分做法是filter加indexOf或reduce加includes能体现你对数组方法的理解。但更进阶的答法是讨论适用场景如果数组里包含对象要去重的是某个属性Set就解决不了需要手写reduce配合Map。这种递进式的回答方式能直接展示你的思考深度。深拷贝是另一个我见过翻车概率很高的题。最低限度的答案是JSON.parse(JSON.stringify(obj))但面试官一定会追问它的缺点无法处理函数、undefined、Symbol、循环引用Date会被转成字符串RegExp会被转成空对象。所以要能写出一版递归深拷贝并且处理特殊类型和循环引用用WeakMap来记录已经拷贝过的对象避免死循环。写这部分时最好逐层展示先判断基础类型再处理数组和对象最后加上循环引用保护。笔试评判很多时候不是看最终结果而是看你写代码的思维顺序先处理什么后处理什么这些暴露的是你的工程习惯。5.2 笔试题对代码的隐性要求边界、命名、注释很多候选人手写题代码能跑但拿不到高分原因在于没有留意到笔试评分里的“隐形标准”。一套优秀的手写代码首先要给函数起一个语义化且准确的名称比如debounce、deepClone而不是fn1、test其次要处理入参边界情况比如防抖函数如果不停触发要不要实现immediate参数立即执行一次深拷贝如果传入null或基础类型怎么办第三关键逻辑处要有简短注释不是为了凑字而是为了告诉阅卷人“我清楚地知道这一步在做什么”。我建议手写题一律按“三步走”来写先写函数签名和注释说明功能再写核心逻辑最后补边界判断。这样即使某个边界处理忘记写了整体的代码结构也能给阅卷人留下好印象。还有一点特别重要不要在一道题上死磕太久。如果卡住了先用最朴素的写法实现一个能跑的版本再回头优化。笔试是时间和正确率的博弈先把基础分都拿到再去追求额外加分这个策略在任何校招笔试里都成立。6. 复盘与准备建议聊聊我刷完这套题之后的真实体会6.1 刷题真正的价值在于考点迁移而不是背答案老实讲刚刷完用友2019校招web前端笔试题一那会儿我也整理了一堆错题但真正让它发挥作用的是我后来做的“考点迁移”练习。每道错题我不止看正确答案还问自己三个问题这个题考察的核心知识点是什么、它跟哪些其他知识点关联、如果面试官换个问法我还认不认得出来。举个例子闭包题常见考法不止是for循环加setTimeout还可能换成事件监听、防抖节流、循环创建DOM元素。可一旦你理解了闭包的本质这类题不管怎么变形都能应对。原型链题也不止存在于选择题手写new、手写instanceof、理解Vue源码中的原型挂载本质上都是同一张知识网络。这种迁移能力才是刷题给你留下的长期资产比任何一份错题笔记都值钱。6.2 如果时间有限按这个优先级准备效率更高校招准备时间永远是不够用的如果你是临时抱佛脚我建议按“JavaScript基础、手写题、浏览器与性能、Vue、工程化和网络”这个顺序来分配时间。JavaScript基础是笔试和面试的根花两天把原型链、闭包、this指向、事件循环彻底盘一遍效果立竿见影。手写题每天练两到三个重点不是背代码而是默写后立刻设想几个输入测试数据去验证边界条件。浏览器和网络问题在笔试中占比不低但知识点相对固定把请求缓存、渲染机制、跨域方案、HTTP缓存这几块吃透就足够应付大多数场景。Vue相关题目重点放在响应式原理和组件通信上这两块是用友这类企业最关心的实际开发能力。工程化部分可以结合你的项目经验来复习比如webpack的打包流程、为什么配置loader、怎么做代码分割这些都是把项目和知识点串起来的好话题。最后花一天模考整套卷子统计失分模块再针对薄弱项补一轮比我毫无目的地刷二十套题高效得多。我个人的体会是这套题带给我最大的价值不是让我背会了几个标准答案而是让我意识到前端笔试真正考的从来不是单个知识点而是长期积累形成的知识网络。面试官顺着你的答案往下追问本质上就是在测试你这张网络织得密不密。所以别满足于“这道题我会了”多往底层钻一层理解它为什么这么设计、底层是怎么运转的这种深度会让你的每一次面试都比别人多一分底气。