B站2020前端校招笔试题解析:闭包、手写代码与框架原理

发布时间:2026/10/28 16:33:42

B站2020前端校招笔试题解析:闭包、手写代码与框架原理 1. 题目全景B站2020校招前端笔试卷到底在考什么1.1 试卷结构与考察方向拆解做前端校招这几年我经手过不少大厂的笔试卷子B站这套2020前端笔试卷一算是比较有代表性的。整张卷子想考察的方向非常明确不再考你背了多少API而是看你在真实场景下能不能把基础原理吃透、能不能手写出工程可用的代码。从题型分布来看基本可以分成四块。第一块是基础语法与数据类型题主要围绕typeof、instanceof、闭包、原型链这些JS核心概念展开第二块是手写代码题常见的有防抖节流、深拷贝、数组去重、Promise封装第三块是CSS布局与浏览器机制题比如flex布局、BFC、事件循环、渲染原理第四块是框架原理题Vue和React双线并重尤其爱考响应式原理、setState机制、虚拟DOM diff这些。这套题最值得研究的不是题目本身而是命题逻辑。你会发现它基本都是“启动条件简单、延伸深度大”的题型一句话描述场景然后让你写实现或者让你判断输出结果。这种出题方式的优势在于不给考生“背答案”的机会每一种写法背后都能反映你真实的理解深度。比如一个简单的防抖函数应届生可能只能写出300字的初版但真正理解闭包和this指向的人会在一版里就解决掉所有边界情况。这就是大厂筛人的核心逻辑。我的建议是做这套题不要只追求“写出来”要追求“为什么这么写”后面我会逐个题拆解。1.2 命题风格背后的人才画像看完B站这套笔试题我最大的感受是它们不是在招一个“会写页面的人”而是在招一个“能自己解决不确定问题的人”。整个岗位画像的核心词就两个扎实和灵活。“扎实”体现在对基础知识的追问方式上。比如列出null undefined和null undefined的输出结果这种题表面上是判断相等实际上考验你对JS隐式转换规范的掌握程度。而typeof NaN、typeof []这类输出题更是直接检验你有没有真正理解JS的数据类型系统。这些东西不背个三五遍现场很容易在细节上翻车。“灵活”体现在手写题和场景题上。卷子里会出现类似“实现一个带最大执行次数的防抖函数”“封装一个支持取消的Promise”这类变体题拼的就是你在标准答案之外能不能拓展出工程经验。笔试阶段还好到了面试环节面试官会顺着你的代码往下追问比如“为什么这里要用apply而不是call”“如果并发请求要怎么做边界控制”。这次复盘我会把每一类题都往这个深度去讲保证你看完不只能“过笔试”还能应对后续的追问。2. 手写题核心闭包、防抖节流与深拷贝的“工程级”写法2.1 闭包与作用域一道输出题背后的执行机制B站这套笔试卷子里的闭包输出题几乎是所有面试题的“开胃菜”。比如经典的for (var i 0; i 5; i) { setTimeout(function () { console.log(i); }, 1000); }这道题输出的是5 5 5 5 5而不是0 1 2 3 4核心原因在于var声明的变量是函数级作用域循环结束后i已经变为5而setTimeout的回调是在循环结束后的宏任务阶段才执行的此时访问的i自然指向同一个变量。很多同学答错这道题不是因为不知道异步而是没有把“作用域、变量提升、事件循环”三个知识点串联起来。正确的改法也不止一种。第一是用let声明利用块级作用域为每次循环创建独立的绑定第二是用 setTimeout 的第三个参数透传局部变量第三是用立即执行函数IIFE包裹形成闭包。我推荐第三种的变体因为你能顺带回答面试官的追问“如果我偏要用var你还有哪些办法”for (var i 0; i 5; i) { (function (j) { setTimeout(function () { console.log(j); }, 1000); })(i); }这里的关键是理解IIFE的入参i在每轮循环时就被“快照”到参数j上闭包记住的是参数j而不是外部变量i。这种题没有太多花哨技巧靠的是你对作用域链和闭包原理的底层理解。2.2 防抖与节流从“能跑”到“好用”的边界处理B站笔试卷里的防抖节流题通常不只是“写出来就行”它会限定场景。我见过最典型的版本是这样的实现一个防抖函数要求首次触发时立即执行且支持取消。这个版本的考点就比普通防抖多了一层。普通防抖的核心是在事件触发后延迟执行如果在延迟期间再次触发则重新计时。标准写法如下function debounce(fn, delay) { let timer null; return function (...args) { const context this; if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(context, args); }, delay); }; }但“首次立即执行”意味着要在开头加一个判断如果timer为null立刻调用否则才启动新的定时器。而“支持取消”就需要在返回值上挂一个cancel方法清空定时器并重置状态。完整的工程版本我习惯这么写function debounce(fn, delay, immediate false) { let timer null; const debounced function (...args) { const context this; if (immediate !timer) { fn.apply(context, args); } if (timer) clearTimeout(timer); timer setTimeout(() { fn.apply(context, args); timer null; }, delay); }; debounced.cancel function () { clearTimeout(timer); timer null; }; return debounced; }节流的工程版本也同理核心是控制执行频率。需要提醒的是笔试时切记不要把防抖和节流的定义搞混防抖是“只执行最后一次”节流是“固定间隔执行一次”。面试官大概率会让你用自己的话说出两者的区别和适用场景比如搜索框输入用防抖滚动加载和按钮点击频率限制用节流。2.3 深拷贝完整方案必须考虑到这四层深拷贝是B站这类校招笔试卷里最稳的一道手写题但这道题的上限极高。普通的浅层复制写法function deepClone(obj) { return JSON.parse(JSON.stringify(obj)); }这个版本在笔试中只能算基础分。JSON.stringify会忽略undefined、function、Symbol并且无法处理循环引用也无法处理Date、RegExp、Map、Set这类特殊对象。笔试想拿高分我的建议是至少实现到一个支持循环引用、能区分数据类型的版本。推荐一个能应对笔试和日常开发的深拷贝模板function deepClone(obj, hash new WeakMap()) { if (obj null || typeof obj ! object) return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); if (hash.has(obj)) return hash.get(obj); const target Array.isArray(obj) ? [] : {}; hash.set(obj, target); Reflect.ownKeys(obj).forEach((key) { if (typeof obj[key] object obj[key] ! null) { target[key] deepClone(obj[key], hash); } else { target[key] obj[key]; } }); return target; }这里有两个细节需要展开。第一用WeakMap作为缓存目的是解决循环引用问题否则遇到a.self a会直接栈溢出。第二用Reflect.ownKeys而不是Object.keys是因为前者能拿到不可枚举属性和Symbol属性这在工程中很关键。笔试时即使不要求写到这个完整度也可以在注释里写出“这里还可以处理Symbol属性”让面试官知道你有这个意识。3. 框架与原理题从B站考法看Vue和React的核心区别3.1 Vue响应式原理从Object.defineProperty到Proxy的演进B站这套卷子里Vue相关题目主要围绕响应式原理展开。最典型的问法是“对data中的一个数组执行push操作页面会更新吗”。如果对Vue 2的响应式实现不了解很容易答错。Vue 2 的响应式重写了数组的七个方法push、pop、shift、unshift、splice、sort、reverse所以push后页面会更新但直接通过索引修改数组元素则不会触发。这就是为什么Vue 2 文档里强调要用Vue.set或splice来修改数组。Vue 3 则换成了Proxy这张卷子如果放在2020年之后考Vue 3的概率会更大。const reactive (obj) { return new Proxy(obj, { get(target, key, receiver) { // 依赖收集 track(target, key); return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { const result Reflect.set(target, key, value, receiver); // 触发更新 trigger(target, key); return result; } }); };对比两者最大的差异在于Object.defineProperty只能劫持已有属性新增属性需要额外处理而Proxy可以对整个对象进行代理新增、删除操作都能被监听。笔试时建议从“对象是否被整体代理”“数组是否要特殊处理”“新增属性是否需要额外API”三个维度来对比回答这样逻辑清晰也方便面试官顺着往下问。3.2 React setState同步还是异步取决于谁在调用React相关题目里B站比较偏爱考察setState的执行时机。这道题的细节非常多在React 18之前setState在事件处理函数中是异步的在setTimeout、原生事件监听器、Promise回调中是同步的。到React 18之后自动批处理机制会让所有场景默认执行异步批处理同步执行的场景需要显式使用flushSync。笔试时如果遇到“点击按钮后连续调用三次setState(count count 1)最终count是多少”这类题答案是3而不是1。因为传入的是更新函数React会把多个更新合并按顺序依次执行。如果传入的是普通值比如setState(count 1)三次最终只会加1因为React的批处理机制会用最后一次赋值覆盖前面的更新。能区分这一点基本就能证明你对React状态更新机制有真实理解。4. 浏览器机制与网络基础事件循环、渲染与跨域问题4.1 事件循环与宏任务微任务输出顺序题的通解思路前端面试绕不开的必考题B站笔试卷里也有不少“写出下列代码的输出顺序”题。核心逻辑并不复杂只要你记住同步代码先执行微任务先于宏任务宏任务按先后顺序执行。来看一道典型题目console.log(script start); setTimeout(() { console.log(setTimeout); }, 0); Promise.resolve().then(() { console.log(promise1); }).then(() { console.log(promise2); }); console.log(script end);输出顺序是script start→script end→promise1→promise2→setTimeout。原因在于回调队列里微任务的优先级高于宏任务而setTimeout即使延时为0也要先进入宏任务队列。动手做这类题时我习惯先在草稿纸上列出“同步任务”“微任务”“宏任务”三个队列再把每个代码块依次入队顺序就一目了然了。4.2 跨域方案不必求全但要会“对比差异”跨域是试卷里的常客B站这边也不例外。最常见的出题方式是让考生回答“如果要向另一个域名的接口发送请求有哪些方案分别有什么优劣”。我建议从以下四个主流方案讲起JSONP、CORS、代理转发、postMessage。JSONP利用script标签不受同源策略限制的原理只能支持GET请求适合老项目对接。CORS后端在响应头设置Access-Control-Allow-Origin可以支持所有HTTP方法是当前的主流方案。代理转发在开发环境用webpack的devServer.proxy生产环境用Nginx反向代理本质是让同源的服务器去请求跨域接口再返回给前端。postMessage适用于iframe和window.open打开的页面之间通信。回答时不需要每个方案都背得滚瓜烂熟但一定要能说出“为什么JSONP不支持POST”“CORS的预检请求触发条件是什么”这两个追问点。5. CSS与工程化布局、选择器优先级和前端构建5.1 布局题flex三栏布局的几种写法CSS布局题在B站这套卷子里也占一定比重尤其是flex布局。最经典的题是“左右固定宽度中间自适应”的三栏布局。答案其实不止一种.container { display: flex; } .left { width: 200px; } .right { width: 200px; } .center { flex: 1; }这里有个容易被忽略的细节flex子项的默认min-width: auto会导致内容过长时中间栏被撑破所以通常需要给中间栏加上min-width: 0或overflow: hidden。这类小坑在笔试时不容易暴露但面试官一旦让你“说一个flex布局的坑”你回答这个就非常加分。5.2 工程化题模块化规范与性能优化2020年的前端校招试卷工程化相关内容已经相当普及。B站这套卷子里出现过“CommonJS与ES Module的区别”“如何做首屏性能优化”这类题目。CommonJS和ES Module的区别建议从三个角度展开加载时机、静态分析能力、循环依赖处理。CommonJS是运行时加载模块导出的是值的拷贝ES Module是编译时输出接口模块间是值的引用。这个区别延伸出来的问题就是:ES Module能进行tree shaking而CommonJS很难做到。性能优化题这块可以从网络、渲染、代码层面各说一条。网络层做HTTP缓存、CDN、接口合并渲染层做图片懒加载、骨架屏、减少重排重绘代码层做路由懒加载、第三方库按需引入、长列表虚拟滚动。“代码分割”容易答但“为什么分包可以提升首屏速度”的回答最关键浏览器只需要下载当前路由所需的代码把非首屏代码拆出去首屏JS体积变小加载和解析自然变快。笔试时我习惯列一个“优化手段实现思路收益说明”的结构表格一目了然。6. 笔试复盘考场上的常见失分点与冲刺建议6.1 那些年我们在笔试题上踩过的坑第一类常见失分点是“手写题能跑通但不考虑边界”。防抖函数里不处理this指向、深拷贝里不考虑循环引用、节流函数里不处理最后一次触发这些都会让面试官认为你停留在“能写Hello World”的阶段。第二类是“输出题凭感觉不写推导过程”。事件循环题里如果只写答案不写步骤丢分很可惜。即使是笔试我建议也要在代码旁边简短写上“为什么”的推导因为很多在线笔试题会要求提交解释。第三类是“框架题只背结论不解释原因”。比如知道Object.defineProperty无法监听新增属性但说不清新增属性为什么不会触发响应式更新这涉及Vue初始化时递归遍历的机制也是分水岭所在。6.2 冲刺阶段的准备思路结合B站2020这套笔试题我给正在准备校招的同学三个建议。第一刷题不能只刷“简单版”。像防抖、节流、深拷贝这类题网上到处都是基础答案你要做的是主动给自己“加条件”模拟面试官会提出的实际场景限制。第二建立自己的笔记体系。每道错题不只是记录答案而是记录知识点之间的关联。比如闭包输出题关联到事件循环再关联到防抖节流和函数柯里化。这种网状结构比零散刷题有效得多。第三把“手写题”真正写到肌肉记忆的程度。考场上时间紧张手写题如果还需要现场思考思路通常写不出完整版本。建议在笔试前把高频手写题至少默写三遍一直到不需要犹豫就能写完整。从我个人经历来看B站这套笔试题的难度在当年校招里属于中上水平但它考察的知识点都非常“正”没有什么偏题怪题。认真把基础原理搞懂把经典手写题练到顺手通过笔试并没有想象中那么难。最后再分享一个小技巧在线笔试前把本地编辑器的自动补全关掉练几轮手写等上了考场你会发现真正的做题速度比你想象中要快得多。
延伸阅读

更多相关文章

2026/10/24 9:08:36

Pygame贪吃蛇游戏开发:从零搭建静态界面与网格化设计

1. 项目概述:为什么从界面开始?很多朋友学编程,第一个想做的游戏就是贪吃蛇。它规则简单,逻辑清晰,是理解游戏循环、事件处理和图形绘制的绝佳入门项目。但不少教程一上来就讲蛇的移动、食物的生成,把一堆代…

2026/10/28 16:32:23

Agent Skills实战:从只会聊到会干活,技能机制全解析

你有没有过这种经历:一个Agent吹得天花乱坠,接进来之后日常聊天确实像模像样,可只要一让它干点具体的活——画一张分镜、生成一份带样式的落地页、批量整理一批文件——就开始拉胯。要么给一堆正确的废话,要么做出来的东西根本不能…

2026/10/28 16:32:23

Web 3D优化实战:KTX2纹理压缩与Draco几何编码管线

如果你是一个 Web 3D 项目的负责人,应该对这套流程一点都不陌生:美术在 Blender 里调了一下午,导出几百 MB 的 glTF 模型;你也认真写了模型加载代码,结果用户打开页面先盯着加载条看了三秒,然后说“这页面怎…

2026/10/28 16:32:23

C++ Socket编程:从基础到高级实践

1. Socket编程基础概念解析在C网络编程中,Socket(套接字)是网络通信的基本构建块。简单来说,它就像是两台计算机之间的电话插座——插上就能通话。Socket本质上是一个抽象层,位于应用层和传输层之间,为应用…

2026/10/28 16:32:23

C++20 Ranges适配器视图与代理迭代器深度解析

1. 项目概述在C20标准中引入的std::ranges库彻底改变了我们处理序列数据的方式。作为一名长期使用C进行系统开发的工程师,我发现其中最令人兴奋的特性莫过于适配器视图(Adapter Views)与代理迭代器(Proxy Iterators)的…

2026/10/28 16:32:22

STM32H743定时器触发ADC+DMA双缓冲:高速采样不拖累CPU的工程模板

简介:在嵌入式数据采集与电机控制中,ADC采样率提升常导致CPU被中断拖累。利用定时器硬件触发ADC转换,再配合DMA双缓冲(乒乓缓冲)搬运数据,可让采样链路几乎不占用CPU资源。STM32H743基于异步时钟域的ADC与高…

2026/10/28 16:27:19

Flask+WebUploader实现大文件分片上传与断点续传

简介:这是一份基于Flask与WebUploader实现的大文件分片上传与流式下载的完整Web应用Demo,面向Python后端开发者、Web全栈初学者及需要解决大文件传输瓶颈的工程实践者。资源解决了传统单次HTTP上传易超时、内存占用高、并发上传冲突等问题,通…

2026/10/28 14:42:12

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/28 15:28:56

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/28 3:32:29

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/28 0:02:13

Python股票自动交易系统源码解析:从行情获取到风控的完整链路

简介:这份资源是面向高校计算机、金融相关专业毕业设计场景的完整项目源码包,主题为基于Python的股票自动交易系统,适合需要完成毕设选题、课程设计或自学金融量化交易开发的学生与开发者参考。压缩包共收录687个文件,整体约14.93…

2026/10/28 0:02:13

视酷酷信IM源码部署指南:Java 17+MySQL 8.0.33实战配置

简介:这是一套2024年亲测可部署的视酷酷信IM即时通讯系统源码,面向具备Java、OC、C#及Vue开发能力的技术人员,解决私有化即时通讯平台快速搭建与二次定制需求,尤其适用于需集成商城、保障数据主权的中小型企业或独立开发者。资源共…

2026/10/28 0:02:13

Python爬取百度迁徙数据:接口解析、批量采集与避坑指南

简介:这份资源是一个用Python爬取百度迁徙数据的脚本压缩包,面向具备Python基础、希望入门网络爬虫与数据解析的开发者,解决按日期获取全国热门城市人口迁徙数据的问题。包内共1个文件,为单个py脚本,压缩包约1KB&#…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑