ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

前端笔试备战:小红书2020校招笔试题卷二核心考点拆解

前端笔试备战:小红书2020校招笔试题卷二核心考点拆解 小红书2020校招前端笔试题卷二在当年的校招群里流传度非常高。我记得好几个学弟学妹轮番来问我同一个问题这套卷子该怎么准备我翻完流传出来的题目版本之后最大的感受是它没有一句废话——闭包、this指向、事件循环、跨域、渲染机制、手写代码几乎把前端基础里最容易出错的硬骨头都点名了一遍。哪怕现在已经不是2020年前端技术栈一直在变但这套卷对准备校招、跳槽和想系统性自查基础的人来说依然是一份很好的体检清单。它能帮你快速找到那些“我以为是会的其实根本不懂”的地方。如果你正在准备前端岗位的笔试面试或者工作两三年后感觉自己基础不牢都可以拿这套题做一次自测。下面我会按模块拆解卷子里最容易考、也最容易丢分的几个方向把核心原理、答题思路和当时同学踩过的坑一起说清楚。1. 试卷结构与考察思路拆解1.1 卷二在整轮笔试中的定位小红书2020校招前端笔试实际投放的不止一套卷子卷二属于典型的基础综合卷逻辑是在简历筛选之后、面试之前先用机器或者人工快速筛一遍候选人的下限。这类卷子不会故意出偏题怪题但普遍题量大、覆盖广限时内想拿高分并不轻松。当时我拿到流传出来的版本印象最深的是题目层级很分明大致可以分成三类选择题负责考察概念辨析和语法易错点包括单选和多选简答题负责考察理解深度比如让你解释某个机制或者某个方案编码题则直接要求手写实现比如防抖节流、数组去重、深浅拷贝等。选择题测的是“知不知道”简答题测的是“理不理解”编码题测的是“能不能写出来”。这三个层次层层递进比单纯刷算法题更能反映一个前端候选人的真实水平。所以如果你只是在牛客、LeetCode上狂刷题忽视了对知识体系的理解卷二这类试卷很容易让你原形毕露。1.2 校招笔试真正想看到的答案长什么样很多同学容易陷入一个误区简答题写得越多越好最好把所有相关名词都堆上去。其实打分的人更想看到“先说什么、后说什么、为什么这样设计”的逻辑链条。举一个高频简答题为例“跨域有哪些解决方式”。如果只是列出来JSONP、CORS、postMessage、代理转发那只能算及格。真正能拿高分的答法是先点出跨域的本质是同源策略对“协议、域名、端口”的限制再分别说明每种方案适合什么场景最后给出当前项目里的推荐做法和注意事项。卷二里的简答题占比不低答法不同分数差距会很大。我建议平时复习时不要只背面经可以试着把每个知识点当成一个“小报告”先定义、再解释原理、最后给场景这样无论题目怎么变形你都能答到点子上。1.3 考点分布速查表考察模块常见题型推荐优先级JavaScript 基础选择、简答、编码极高浏览器与网络选择、简答高CSS 与布局选择、编码高Vue/React 框架选择、简答中高手写代码编码极高这个优先级参考了近几年的校招笔试题和面经统计不一定完全对应某一次考试但大方向是稳定的。考生复习时应该优先保证JavaScript和手写代码的正确率因为它们几乎每套卷都会出现而且一旦写错基本没有蒙对的概率。2. JavaScript 基础闭包、作用域与this指向2.1 闭包经典考法从输出结果到修复代码卷二在JavaScript部分最常出现的是闭包相关题目。闭包的经典考法有两种一种是问输出结果另一种是让你修复代码中的问题。问输出结果几乎是绕不开这个场景的for (var i 0; i 5; i) { setTimeout(function() { console.log(i); }, 1000); }这段代码最终不是打印0、1、2、3、4而是一秒后连续打印五个5。原因有两层第一var声明的i是函数级作用域循环体里外共用同一个变量第二setTimeout的回调是在循环完全结束之后才执行的此时i已经自增到了5。只要抓住“变量作用域 异步执行时机”这条主链类似题目基本不会再错。考试里还会继续追问改成let i为什么就对了因为let在每次迭代中都会创建一次新的词法环境绑定闭包捕获的是当前这一次的i而不是循环结束之后的最终值。另一个常见修法是用立即执行函数把i作为参数传进新函数作用域for (var i 0; i 5; i) { (function(j) { setTimeout(function() { console.log(j); }, 1000); })(i); }如果考简答大概率会让你解释闭包是什么、为什么存在、有什么坑、怎么解决。要答得漂亮最好讲清楚三点闭包能在函数外部访问到其内部作用域的变量它能让变量长期驻留所以常被用来封装私有状态但如果使用不当也可能造成内存泄漏或循环引用。2.2 this指向不要背口诀要会看调用方式this指向问题是前端笔试的常青树卷二里有个很经典的嵌套函数版本var name window; var obj { name: obj, getName: function() { return function() { return this.name; }; } }; console.log(obj.getName()());这段代码最终打印的是window而不是obj。原因是函数调用时this指向取决于调用者。嵌套的那个匿名函数是独立调用的没有对象前缀所以this指向全局对象浏览器环境就是window。这类题目经常搭配三种修法来考把外层this保存到一个变量里比如var self this改用箭头函数因为箭头函数没有自己的this它从定义时的外层作用域继承或者在返回函数时用bind(this)。很多同学喜欢死背“谁调用就指向谁”的口诀但它的例外实在太多。我建议用更可靠的判定方法也就是看函数的调用表达式属于哪一种fn()直接调用非严格模式下this指向全局对象。obj.fn()方法调用this指向obj。new fn()构造调用this指向新创建的对象。fn.call(obj)/fn.apply(obj)/fn.bind(obj)显式绑定this指向指定的obj。把这四种情况分清楚再遇到任何this题都能慢慢推出来。卷二里还常把this和原型链结合出一道输出题所以先复习好调用方式后面再遇到更复杂的场景也不容易翻车。2.3 作用域提升与块级作用域最容易被忽略的送分题除了闭包和this作用域提升也是一道常见的选择题。典型的题目是console.log(a); var a 1;控制台输出的是undefined而不是报错。原因在于var声明会被提升到当前作用域顶部但赋值并没有被提升所以执行到console.log(a)时a已经存在值却是undefined。这里需要注意如果换成let a控制台就会直接报错因为let存在暂时性死区在声明之前访问变量是不允许的。这些知识点单独拎出来都不难但在限时笔试的高压环境下很多同学会凭第一印象选出错误答案。我自己的习惯是遇到这类题先在草稿纸上把“声明提升、赋值执行、作用域链查找”三个过程画出来顺序捋清楚再选正确率会高很多。3. 浏览器与网络从渲染原理到跨域方案3.1 渲染流程、重排重绘与性能优化浏览器原理中渲染流程绝对是高频考点。简化的过程是HTML解析成DOM树CSS解析成CSSOM树两者结合生成渲染树然后计算布局、绘制合成。这个流程本身不难背难的是把它和相关问题串起来。比如卷子里可能问“为什么操作DOM会影响性能”答案不是简单说“会重排重绘”而是要说明任何改变DOM大小、位置、结构的行为都可能触发重新布局而布局计算会阻塞渲染线程所以频繁操作DOM累积下来就会非常卡顿。更深入的追问可能是“如何减少重排”。比较靠谱的答案包括批量修改DOM可以用documentFragment先积攒再一并插入用CSS类一次性替换多个样式而不是逐条修改内联样式对动画元素使用transform或opacity让它独立成合成层减少对主线程布局的触发。这些实战技巧在笔试里很加分因为阅卷人一眼就能看出你是不是真的处理过性能问题。3.2 跨域的源头与主流解决方式跨域在卷二里出现频率很高很多考生能列举JSONP、CORS、postMessage但一到简答题就说不清为什么会有跨域。它的根源是浏览器的同源策略目的是防止一个源随意读取另一个源的数据。同源要求协议、域名、端口三者完全一致任何一项不同都算跨域。理解了这个前提再去区分方案就清晰很多JSONP利用的是script标签不受同源限制的特性只能发GET请求适合接口比较简单的老系统。CORS是通过后端在响应头里声明允许的源这是现代Web应用的标准方案。需要区分简单请求和非简单请求非简单请求会先触发OPTIONS预检。代理转发适合开发环境和同源部署场景让前端请求打到同源后端再由后端转发到目标接口这样浏览器层面就不存在跨域问题。选择题里常见的坑是混淆“跨域能不能发请求”和“跨域能不能读到响应”。实际上非简单请求会先发出预检请求真正的报错往往发生在响应被拦截阶段而不是请求没有发出去。只要把这一点理解到位跨域选择题的准确率能提升不少。3.3 事件循环与微任务宏任务别在嵌套里算错顺序浏览器部分大概率会有一道事件循环题。核心知识点是JavaScript是单线程的同步代码先执行遇到异步任务会交给浏览器其他线程处理异步任务完成后回调会被放进任务队列在执行栈清空后浏览器先处理微任务队列再取出一个宏任务执行循环往复。经典的输出题形如console.log(1); Promise.resolve().then(() console.log(2)); setTimeout(() console.log(3), 0); console.log(4);结果是1、4、2、3。原因就是Promise的then属于微任务setTimeout的回调属于宏任务微任务会在下一个宏任务之前先执行。如果再混入async/await会更容易算错async function test() { console.log(1); await Promise.resolve(); console.log(2); } console.log(3); test(); console.log(4);这里的输出顺序是3、1、4、2。注意看调用test()后函数体里的console.log(1)是同步执行的遇到await才把后续代码异步化所以主线程继续往下执行了console.log(4)然后才轮到微任务里的console.log(2)。我的笨办法是拿到题目先标记同步代码再把宏任务和微任务分别列成小队列最后按顺序执行基本不会错。3.4 HTTP缓存与存储选择题里的隐形考点除了渲染和跨域浏览器部分还经常穿插HTTP缓存和存储相关的选择题。缓存方面要能清晰区分强缓存和协商缓存强缓存直接通过Cache-Control或Expires判断缓存是否有效有效期内不会发请求协商缓存则需要带上Last-Modified或ETag去服务器验证服务器返回304则继续用缓存。存储方面cookie、localStorage、sessionStorage、IndexedDB四者的区别也是高频题考试时经常拿“容量限制”“是否随请求发送”“是否自动过期”这几个维度做混淆选项。这些知识看起来零散实际上背清楚一张对比表就能稳稳拿到分。4. CSS与布局BFC、flex与经典布局实战4.1 BFC一个独立渲染小世界CSS部分卷二对BFC的偏爱非常明显。BFC全称是块级格式化上下文你可以把它理解为一个独立的渲染小世界在这个小世界里元素的布局不会影响外部外部也不会影响它内部。哪些情况会触发BFC浮动、绝对定位、inline-block、overflow不为visible的块级元素、flex容器等都会触发。卷子里常考的题目是“如何清除浮动”答案里一定会提到overflow: hidden。但你要能解释它背后的原理给父容器创建了一个BFC让浮动元素也参与父容器的高度计算从而把子元素“包”起来。另一个高频考点是“如何防止margin合并”同样可以通过在父容器上创建BFC让相邻元素的垂直margin被隔离在独立的上下文中。这里我把容易混淆的触发条件整理成一个清单float不是none。position是absolute或fixed。display是inline-block、table-cell、flex或grid。overflow不是visible。考试时问到某个元素是否创建了BFC直接按这几个条件套就能判断。4.2 盒模型一个必拿的基础分盒模型虽然简单但错的人非常多。标准盒模型里width只包含内容区而IE盒模型box-sizing: border-box里width包含了内容、padding和border。卷二选择题特别喜欢给一组场景比如“给一个元素设置width: 100px; padding: 20px; border: 5px标准模型里的真实占位宽度是多少”很多人一紧张就算错。其实答案很简单标准模型下真实占位宽度是100 20*2 5*2 150px如果是border-box真实占位宽度就是100px。这类题没有任何难度只要在读题时先确认一下是否设置了box-sizing就能稳拿分。4.3 垂直居中与两栏布局高频编码实操布局题也是卷二的高频题尤其是“垂直居中”和“两栏/三栏布局”。垂直居中看似简单但不同场景对应不同最佳解。父容器宽高未知子元素尺寸也未知最推荐flex方案.parent { display: flex; justify-content: center; align-items: center; }如果要求兼容老浏览器可以用绝对定位加负margin但前提是子元素尺寸已知。还有基于transform: translate(-50%, -50%)的方案它的百分比是相对于元素自身尺寸计算的所以不需要知道具体宽高这也是它适合当作通用方案的原因。两栏布局里经典做法是左侧固定宽度右侧自适应。用flex实现很简单左边flex: 0 0 240px右边flex: 1。三栏布局则常考圣杯布局和双飞翼布局目的是让中间栏先渲染再通过负margin或padding把两侧让出来。要理解这类布局核心是吃透“负margin会改变元素在文档流中的占位位置”剩下就是组合游戏。死记代码很容易忘但把原理想明白之后任何变体都能应对。5. 框架知识Vue/React 核心机制5.1 Vue的响应式原理从Object.defineProperty到Proxy2020年的笔试题框架部分默认你已经会Vue或React。Vue高频题是“响应式原理是什么”要答清楚它不是魔术而是数据劫持加发布订阅。2.x版本用Object.defineProperty遍历对象属性并定义getter/setter页面读取数据时收集依赖数据变化时派发通知触发重新渲染。3.0版本改成用Proxy它能拦截更多操作比如属性的新增和删除同时性能更好。卷子里如果出这类题很可能搭配一个实操问题给Vue 2的数组新增元素为什么页面不更新原因在于Object.defineProperty无法拦截通过索引设置新值这种操作所以需要借助$set或者重写过的数组方法来触发更新。很多同学只背了“数组要用$set”这个结论却不知道背后的边界在哪里。我的建议是复习时亲手写一个小例子在Vue 2和Vue 3里分别改数组亲眼看看输出差异这比背十篇面经都更牢固。5.2 虚拟DOM与diff为什么key不能乱用indexReact和Vue都会聊到虚拟DOM。它到底是什么可以理解为用JavaScript对象来描述DOM结构一次界面渲染对应一棵虚拟节点树。为什么需要它因为直接操作真实DOM成本高而操作JavaScript对象是纯内存操作非常快再加上diff算法能找出前后两棵树的差异只更新真正变化的部分整体性能体验更好。卷子里常考的并不是diff的每行代码而是它的基本策略同层比较、tag不同直接替换、key用于尽可能复用节点。关于key高频追问是“为什么列表渲染时不能滥用index作为key”。因为在数组头部插入或删除元素时index会整体变化导致原本被复用的节点错乱轻则渲染状态不对重则出现难以排查的交互问题。这个场景不需要高深技术用一个todo列表自己操作一遍就能理解。5.3 生命周期与组件通信框架部分的简答题还经常围绕生命周期出题。Vue里最常见的追问是created和mounted的区别created时数据已经初始化但DOM还没挂载适合在这里发请求或初始化数据mounted时DOM已挂载适合做依赖真实DOM的操作。React那边则常问函数组件里useEffect如何对应类组件的生命周期以及为什么要清理副作用。组件通信也是必考方向Vue里的props/emit、provide/inject、VuexReact里的状态提升、Context、Redux都要能说出各自的适用场景。答这类题不需要长篇大论核心点出“单向数据流”和“状态管理解决什么问题”就够了。6. 编码题实战手写实现与算法基础6.1 手写防抖与节流三个细节决定分数编码题部分手写防抖和节流几乎是保留节目。防抖的核心思想是事件触发后等待一段时间再执行如果在这个等待时间里再次触发就重新计时。节流的核心思想是在一段时间内只允许执行一次。它们分别适合什么场景输入框实时搜索适合防抖因为用户连续输入时不需要频繁请求滚动监听和按钮防连击适合节流因为需要保证一定的执行频率。防抖的经典实现是这样的function debounce(fn, delay) { let timer null; return function(...args) { const context this; clearTimeout(timer); timer setTimeout(() { fn.apply(context, args); }, delay); }; }这里有三个细节很容易丢分。第一要保留this指向所以用了apply第二要透传参数所以用了...args第三是否能说出“什么是立即执行版本、什么场景需要立即执行”这决定了你是背代码还是真掌握了原理。节流的实现也有时间戳和定时器两种常见版本考试时能说出两者区别第一次是否立即执行、最后一次是否补执行会非常加分。6.2 数组去重与扁平化从一行API到进阶追问数组去重是编码题的另一个常客最简单的版本是const unique arr Array.from(new Set(arr));一行代码就能解决。但你能讲讲它的局限吗Set去重使用类似全等的规则对基本类型没问题对对象类型则只能比较引用所以两个内容相同但引用不同的对象都会被保留。如果要求对象数组按某个字段去重就需要用Map来记录。再往下考数组扁平化也有多层考法基础版是直接调用flat()方法进阶版是手写递归再进一层是支持指定深度。这些题目表面看是考API实际是考你能否在特定限制下写出清晰可靠的代码。6.3 深拷贝、手写call/apply/bind卷二的手写题还可能涉及深拷贝和手写call/apply/bind。深拷贝的面试题很考验功底基础版是递归遍历属性进阶版需要处理数组、Date、RegExp等特殊类型还要用WeakMap缓存引用避免循环引用导致死循环。手写call的思路则是利用临时属性改变this指向Function.prototype.myCall function(context, ...args) { context context || window; const fn Symbol(fn); context[fn] this; const result context[fn](...args); delete context[fn]; return result; };这里用Symbol是为了避免覆盖context上已有的同名属性。其实这类手写题对日常业务开发帮助不大但它在笔试里能快速检验一个人对JavaScript底层机制的理解程度。准备方式是理解思路后亲手敲三遍而不是把代码背下来。6.4 算法题策略别输在“看得懂却写不出”算法题在卷二里的难度一般不会达到LeetCode困难题更多是链表反转、二叉树层序遍历、最长不重复子串这类中等偏下题目。很多同学的问题不是没有思路而是没有把边界条件、空值处理、循环终止条件写完整。我建议刷题时不要只看题解要动笔把主路径写出来再补边界。笔试时间有限遇到算法题先花两分钟确认输入输出再写一个能跑通的主路径最后补边界这个顺序比追求最优解更实际。7. 常见问题与排查技巧实录7.1 考生最容易丢分的三个习惯我翻过不少同学的笔试复盘发现丢分点往往不在知识本身而在表达和代码习惯。第一个坏习惯是简答题写太短只给结论不给过程比如“跨域用CORS”却没有说明场景和限制。第二个坏习惯是代码题一上来就封装各种工具函数结果主功能反而没写完正确策略是先实现核心流程保证基本用例通过再考虑封装扩展。第三个坏习惯是不检查边界比如防抖函数没有处理this、数组去重没有考虑空数组这些小问题会让阅卷人对工程素养打个问号。7.2 时间分配与答题顺序建议根据卷二这类基础综合卷的题量和难度我的建议是拿到卷子先快速扫一遍全部题目估算每种题型的大概耗时。选择题不要犹豫太久先按第一直觉选不确定的做标记简答题控制在每题十分钟以内写出核心逻辑链编码题给足时间最好留出二十分钟做检查。做题顺序上建议先做自己有把握的模块把分数先拿到手再回头啃硬骨头。笔试往往按总分筛选稳拿的分比钻牛角尖更有价值。7.3 常见问题速查表问题常见原因解决办法事件循环输出顺序算错混淆微任务与宏任务先列同步代码再分别收集两个队列闭包打印全是循环末值没理解var作用域与异步时机改用let或IIFE垂直居中布局失效父容器或子元素尺寸约束不一致确认flex三要素检查子元素是否被压缩跨域请求报错忽略预检请求或响应头配置分清简单请求与非简单请求数组增删后列表渲染错乱key用了index改用业务唯一id这张表是我根据同学常问的问题整理出来的不一定覆盖全部但能解决八成笔试现场出现的低级失误。7.4 手写题的一个小技巧最后分享一个我自己用过很多次的小技巧手写题如果一时想不起具体API不要空着。先把函数签名写出来把注释写好再用伪代码表达思路。阅卷者通常会给“思路正确但实现有瑕疵”的答案额外同情分。比如防抖你忘了clearTimeout那就写“清除之前的定时器”这种注释至少能让阅卷人知道你的方向是对的。卷面整洁、命名规范在同等条件下真的能拉开差距。小红书这套2020年的前端笔试题卷二我后来给身边准备跳槽的同事也用过。大家的共同感受是题目不算难但很能暴露基本功。闭包、事件循环、BFC、跨域这些知识点平时写业务的时候感觉都用不上可一旦被问到才发现自己只是眼熟而不是掌握。准备这类笔试最忌讳的就是只看面经背答案。我的体会是把每个考点都自己动手验证一遍比如在浏览器控制台跑一遍this指向的代码看看输出到底是什么把防抖节流的调用方式写进一个真实的小项目里感受它们在网络请求上的区别。这样学一遍比考前突击三十道题都管用。希望这篇拆解能帮你在下一次笔试里少踩几个我已经替你踩过的坑。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表