ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

抖音前端一面面经:JS执行机制、浏览器渲染与Vue原理全解析

抖音前端一面面经:JS执行机制、浏览器渲染与Vue原理全解析 1. 整体情况回顾一面到底在筛什么先交代一下背景。我最近刚面完抖音前端的一面趁着记忆还在赶紧把过程和复盘整理出来。整个一面大概持续了50分钟左右没有上来就甩算法题而是先聊项目再逐步深入到JS基础、浏览器原理、CSS、框架最后手写了两道代码题整体感受是考得不算偏但对“基础是否扎实”这件事的考察非常认真属于典型的面试造火箭、工作拧螺丝不是抖音一面的题目其实很贴近日常开发只是它要求你能把“平时在用”的东西讲出底层原理来。先说一句总结性的判断抖音前端一面难度中等偏上重点在JavaScript执行机制、异步、作用域和闭包其次是浏览器渲染和缓存再次是CSS布局和Vue响应式原理。算法题一般不会太难一面大多数时候是一道热身的数组/字符串题关键是别写错边界条件。比起刷题数量面试官更在意你是不是真的理解代码的执行过程而不是背会了八股文。所以这篇文章我会按我这次面试的实际流程把每一类问题、考察意图、我的答法和我认为更优的答法都写出来。如果你是准备投字节系前端岗位、或者正处于春招秋招阶段这篇内容应该能帮你把一面最常考的考点都覆盖到直接照着准备就行。另外我多说一句面经这东西不同面试官风格差异很大同一岗位不同面试轮次的侧重也会不一样。我尽量写的是“覆盖面”而不是“押题”把你需要准备的知识范围拆开而不是单纯把我这场的题目背给你听。2. 自我介绍与项目深挖一面第一个隐形考点2.1 自我介绍怎么说才不白给面试官上来第一句话基本都是“先做个自我介绍吧”。很多人觉得这就是走个过场随便背一段就过去了。但我这次面的抖音一面自我介绍直接决定了他后面从哪个方向问项目。你说得越细他越容易顺着你的技术栈往下挖你说得太笼统他可能就只能从简历里挑几个关键词来问那主动权就不在你手里了。我的建议是自我介绍控制在2到3分钟结构就三块我是谁学校/工作年限、我做过什么挑一个最核心的项目说技术方案和难点、我擅长什么JS基础扎实、Vue比较熟等。千万别把项目从头到尾讲一遍那是后面项目深挖环节干的事。我当时说的大概是“我主要做Vue技术栈的开发最近一个项目是XX管理系统核心难点是大文件上传的秒传和断点续传用了worker做切片计算、hash去重还有并发控制。平时对JS的异步机制和浏览器渲染原理研究比较多。”这段话很关键因为它精准地给我后面的面试定了调——面试官接下来大概率就会问大文件上传相关的问题而这块是我提前准备过的这就是把节奏握在自己手里。2.2 项目难点怎么讲才显深度自我介绍之后面试官果然顺着“大文件上传”开始深挖。这块他问了大概三个层次第一层讲讲大文件上传的整体流程。这个我比较熟直接给他串了一遍文件选择后用File对象的slice方法切成多个chunk计算每个chunk的hash然后先发一个请求给后端注册文件后端返回该文件是否已存在如果已存在就直接秒传否则把chunk分批发给后端最后所有chunk传完后发一个合并请求。第二层hash怎么算的有没有性能问题这里有个很关键的细节如果每个chunk都用全量的内容去做hash计算文件一大主线程会卡死。我当时是先把chunk内容转成ArrayBuffer再用SparkMD5计算hash然后把计算放到Web Worker里做避免阻塞UI。面试官继续追问“为什么放worker就不会卡JS不是单线程吗”这个问题本质是在考验事件循环和线程模型的理解我说了worker是独立线程和主线程通过postMessage通信所以hash计算和页面渲染互不干扰。第三层有没有做并发控制如果一次性把100个chunk同时发出去会怎样我说用了一个并发池的方案控制同时最多发3个或5个请求每个chunk请求完成后从队列里取下一个同时记录失败重试的次数。到这里项目这块基本就过了总共也就8到10分钟。从复盘的角度说项目深挖的核心逻辑就是你说了什么技术点他就有权利把那个技术点问到底。所以面试前一定要对自己简历上的每一个字负责任何一个你提过的技术名词都要准备好被问三层是什么、为什么、怎么落地。不是所有面试官都会这样做但抖音的面试官大概率会。3. JS核心基础一面里面占比最大的部分3.1 代码输出题一道题暴露你的底层理解项目聊完面试官说“来我们做几道题”然后抛了一道代码输出题。代码大概是这样的console.log(1); setTimeout(() { console.log(2); Promise.resolve().then(() { console.log(3); }); }, 0); Promise.resolve().then(() { console.log(4); }); console.log(5);乍一看很简单但这道题陷阱挺多。正确的输出顺序是1、5、4、2、3。我当时答对了但如果只是背了“微任务先于宏任务”这句话很容易把4和2的顺序搞错。这里要理清的是第一次宏任务执行完整体同步代码打印1和5之后清空微任务队列也就是Promise的then回调打印4然后才会执行下一个宏任务setTimeout的回调打印2而这个回调内部又注册了一个微任务所以要先把当前宏任务执行完打印2再清空这个新微任务打印3。面试官紧接着追问了一个大杀器“如果setTimeout和Promise同时调整位置输出会变吗什么情况下会变”这其实是在考察你对宏任务和微任务的理解是死记的还是真的能推演出执行顺序。我的应答思路是不管代码怎么变核心就两条同步代码永远先执行完在每一个宏任务结束后都要把微任务队列彻底清空再进入下一个宏任务。只要抓住这两条大多数输出题都能推出来。遇到这种题建议你在纸上画两个队列一步步推不要看着代码就报答案。熟练以后其实很快但第一次接触的话还是老老实实画队列。3.2 作用域与闭包别只会背定义字节系一面必然有闭包题我这次也没逃过。他给了一段代码for (var i 0; i 5; i) { setTimeout(() { console.log(i); }, 100); }这条题考的就是var没有块级作用域循环结束之后i已经变成了5所以五个setTimeout回调打印出来的全是5。然后他问怎么改成0、1、2、3、4。两个方向用let替换var或者用立即执行函数包裹一层把i作为参数传进去。到这里还没完他加了第三问“setTimeout的第三个参数能实现吗”这个问法有点冷门但确实可以。JavaScript里setTimeout(fn, delay, ...args)的第三个及后续参数会作为回调函数的参数传入所以直接setTimeout((j) console.log(j), 100, i)也能做到而且比IIFE更简洁。能答出这一层面试官会觉得你真的研究过API细节而不只是刷过几道题。闭包的另一个经典问法是“闭包会造成内存泄漏吗”。有人一听内存泄漏就直接说“会”但严谨的答法是闭包本身不会必然造成泄漏但如果闭包引用的对象一直留在内存里而且不再被使用就相当于泄漏了。比如把闭包挂在全局对象上那它引用的整个作用域链都不会被GC回收。正常来说引用计数和标记清除会把不再被引用的闭包回收掉所以不用谈闭包色变。3.3 this指向与箭头函数最容易翻车的点this的题几乎是前端面试的保留节目。他给了一个这样的对象const obj { name: xin, getName: () { console.log(this.name); } }; obj.getName();这种题就是专门坑人的。对象方法写成箭头函数时this不是绑定到obj而是继承自定义箭头函数时所在的作用域。全局定义的对象箭头函数里的this就指向全局浏览器里是windowNode里是globalThis所以this.name是undefined。然后他延伸了一下那怎么让箭头函数拿到obj的name答案是别用箭头函数写普通函数getName() { console.log(this.name); }即可。箭头函数没有自己的this它不能通过call、apply、bind改变this指向这一点要记牢。我还被追问了bind和call/apply的区别。bind不会立即执行而是返回一个新函数新函数的this被永久绑定call和apply是立即执行区别只在传参方式call是逗号分隔的参数列表apply是数组。这些是纯记忆点但如果能解释到“bind的实现本质就是用call/apply包一层”会加分不少。3.4 手写代码一面算法和手写题策略抖音一面一般会有手写题但难度不会太高。我这次遇到的是手动实现Array.prototype.map。其实就是用for循环遍历数组把回调函数的计算结果收集到新数组里返回。但有几个细节要注意原始数组不能被修改回调函数接收三个参数当前元素、索引、原数组callback的thisArg需要支持。我当时的实现大概长这样Array.prototype.myMap function(callback, thisArg) { const result []; for (let i 0; i this.length; i) { if (i in this) { result[i] callback.call(thisArg, this[i], i, this); } } return result; };这里i in this的判断是我刻意写的用来跳过稀疏数组中的空洞。面试官看出来之后问我为什么这么写我就说“原生的map会保留稀疏数组的空位不会把它们变成undefined”这其实是一个很偏很细的知识点但如果面试官欣赏这种细节会大大加分。这是我在面试前看MDN文档时留意的没想到真的派上用场了。手写题训练建议map、reduce、filter、bind、new、防抖节流、深拷贝、扁平化数组、发布订阅这些高频手写题一定要在面试前全部在白纸上写过一遍。不是背是理解尤其是深拷贝和bind这种几乎场场都考。3.5 事件循环与宏微任务的边界说到事件循环这里再多说两句因为这是字节系的前端面试最偏爱的考点基本没有之一。追问完输出题之后他直接让我讲讲浏览器的事件循环和Node事件循环的区别。浏览器的事件循环核心模型是执行一个宏任务然后清空整个微任务队列然后根据渲染时机决定是否执行渲染然后进入下一个宏任务。而Node里新旧版本的事件循环实现还不一样。Node 11之前会在每个宏任务阶段之间执行微任务队列Node 11之后行为和浏览器趋同每个宏任务执行完都会清空微任务。所以同样的代码在浏览器和旧版Node里输出结果可能不一样。我建议准备这块的时候要把浏览器的事件循环机制图画在脑子里宏任务有哪些setTimeout、setInterval、I/O、UI渲染、微任务有哪些Promise.then、MutationObserver、queueMicrotask。注意process.nextTick只在Node里存在它的优先级还高于Promise的微任务这也是一个容易踩的对比点。4. CSS考点一面的隐藏分水岭4.1 居中方案你背的是方案还是原理很多人觉得CSS在字节系面试里占比不高但我这场问了大概5分钟的CSS而且问得还挺细。第一题是“实现一个元素水平垂直居中你能写出几种方案每种方案的适用场景是什么”我当时列了三种flexdisplay: flex; align-items: center; justify-content: center;、绝对定位负margin需要知道容器的宽高、绝对定位translate不需要知道宽高top: 50%; left: 50%; transform: translate(-50%, -50%)。面试官补了一句“如果容器尺寸不固定呢”我说那就flex或者grid的方案更适合负margin方案没法自适应因为margin的值和尺寸强相关。后来我复盘发现这里考察的其实不是你会多少种方案而是你能不能回答“为什么负margin方案不能自适应”。负margin需要你明确知道元素的宽高但实际布局里这个尺寸往往会随着内容变化所以它只适合尺寸固定的场景比如弹窗里的icon。flex和grid是从布局层面解决的transform: translate(-50%, -50%)是通过自身尺寸的百分比来移动的所以都不需要知道尺寸。4.2 Flex布局的经典坑flex: 1到底是什么意思他问了一道很常见的flex题flex: 1的完整含义是什么这个别看简单能答对的人真不多。flex: 1实际上是三个属性的简写flex-grow: 1; flex-shrink: 1; flex-basis: 0%。它的含义是主轴剩余空间按比例分配给自己同时允许收缩基准尺寸为0。很多人以为flex: 1是“占比相同所以等分宽度”但为什么有时候两个flex:1的盒子内容长短不一样宽度却一样原因就是flex-basis被设置为0%每个子项在分配剩余空间之前都被当成0宽度所以最后宽度只取决于放大比例和内容没关系。如果你用flex: auto那是flex-grow: 1; flex-shrink: 1; flex-basis: auto子项初始宽度和内容相关结果可能就不一样了。这块如果面试官再往深处问还会涉及flex-shrink的计算公式比如收缩比例还要乘以基准宽度。但一面通常不会问得那么深能把flex三个属性的作用、简写方式、常见面试场景讲清楚足够了。4.3 移动端适配rem、vw和视口移动端适配也是常考点我这次被问到“你常用哪种方案做移动端适配”。我说现在项目里用vw比较多偶尔配rem。VW的方案实现很简单设计稿宽度通常是750那就把写px的地方用计算属性转成vw或者在构建工具里用postcss-px-to-viewport这类插件自动转换。他会反问vw方案的兼容性有没有坑说实话vw在部分老Android WebView上有兼容性问题表现为布局错乱或字体大小异常。遇到这种情况降级方案是rem。但要说明rem的关键不是设置font-size而是动态修改html根节点的font-size——通常用媒体查询或者JS按屏幕宽度计算。JS方式更灵活但也引入了额外的脚本开销所以很多团队更倾向纯CSS的vw方案或者只用vw做布局不做font-size适配。5. 浏览器加载与渲染高频次重点5.1 从输入URL到页面显示没必要背完整链路这道题在前端面试里的地位不用多说。但我想先纠正一点很多面经说这个问题要背“DNS解析、TCP连接、HTTP请求、服务器返回、浏览器解析、渲染”照着说一遍就完事。实际上抖音一面的面试官不太喜欢这种流水账式的回答他更希望你锚定到“浏览器渲染”这个核心环节。我当时是直接拆分两条链路来讲网络链路DNS解析、建立连接、发送请求、接收响应和渲染链路解析HTML生成DOM树、解析CSS生成CSSOM树、合并成渲染树、布局、绘制、合成。讲到渲染链路的时候我特意说了JavaScript的加载和执行会阻塞DOM解析所以script标签要放在body底部或者使用defer和async属性。async是下载完立即执行执行时会阻塞DOM解析defer是等DOM解析完再执行而且多个defer会保持顺序。5.2 CSS会阻塞渲染吗这个追问是我没想到的。面试官问我CSS会阻塞DOM解析吗我第一反应想说不会但仔细一想发现不是那么简单的。CSS加载不会阻塞DOM树的构建但会阻塞渲染树的构建因为渲染树必须要CSSOM准备好之后才能创建。换句话说浏览器是可以先解析HTML生成DOM的但如果没有拿到CSS它不能把DOM和CSSOM合在一起画到屏幕上。所以从用户感知的角度看CSS会阻塞“首次渲染”不会阻塞“解析”。这个细节要能说清楚面试官基本就能确认你对渲染流程是真正理解了。另外还有一个小点CSSOM的构建是逐条的CSS代码越靠前渲染被阻塞的时间越短。所以实践上我们会把style标签放在head里而script放在body尾部除了规范要求也是因为前者对渲染友好后者对DOM进度友好。5.3 缓存机制强缓存和协商缓存缓存几乎是我经历的每一场前端面试都会问的点这次也不例外。他问强缓存和协商缓存的区别以及对应的HTTP头是什么。这个我答得比较顺强缓存是浏览器判断缓存没过期就直接用不发请求到服务器对应的是Cache-Control的max-age协商缓存是浏览器不确定缓存是否过期带着缓存的标识去问服务器服务器判断没过期就返回304对应的是Last-Modified/If-Modified-Since和ETag/If-None-Match。区别核心在于是否发送HTTP请求强缓存不请求协商缓存会请求一次但响应体很小304空body。实际开发里前端构建工具一般会给带hash的静态资源设置Cache-Control: max-age31536000, immutable因为文件名变了就相当于新资源可以永久强缓存而index.html这类入口文件要设置no-cache它每次都走协商缓存保证内容更新后能被客户端感知到。面试官对这个回答还算满意随后追加“ETag和Last-Modified选哪个”。这个问题我想提醒大家ETag一般是优先的因为它基于内容生成指纹能解决Last-Modified的几个问题——比如文件修改时间变了但内容没变或者秒级内的修改无法被Last-Modified感知。当然ETag也有它的代价服务器算hash有开销所以有些系统会选择两个都用、以ETag为主的策略。6. HTTP与网络基础不可忽视的基础分6.1 HTTP和HTTPS的区别以及握手过程这个题在传统的前端面试里出现频率极高但字节系的出现概率相对低一些。不过我还是建议认真准备因为一旦被问通常就是连环追问。我这次确实被问到了HTTPS的握手过程。我没有去背那个RFC流程列表而是用“怎么建立一条可信且加密的通道”这个主线来讲。第一步客户端发ClientHello带上支持的加密套件和随机数第二步服务端回ServerHello选好加密套件同时把数字证书发给客户端第三步客户端验证证书的有效性证书链是否可信、域名是否匹配、是否过期第四步客户端生成一个预主密钥用服务端的公钥加密发过去第五步双方用三个随机数客户端随机数、服务端随机数、预主密钥生成会话密钥后续通信都用对称加密。这样讲既能让面试官跟上你的思路又能准确的把非对称加密和对称加密的角色说清楚非对称加密只用来安全地传递密钥真正的数据传输用的是对称加密因为对称加密快得多。如果被追问“非对称加密为什么慢”可以提反复的模幂运算比对称加密的位运算在计算复杂度上高很多所以实际场景里不会把所有数据都用非对称加密。6.2 HTTP/1.1、HTTP/2、HTTP/3的演进这道题在近两年的面试里变得越来越重要抖音作为超大流量的业务场景面试官对网络优化一定是有专门的思考的。他问的是HTTP/2相比HTTP/1.1做了哪些提升有没有什么副作用核心提升是多路复用多个请求在一个TCP连接上并发传输、头部压缩HPACK、二进制分帧不再是纯文本协议、服务器推送Server Push。但多路复用有个著名的副作用就是TCP层的队头阻塞因为所有请求共享同一个TCP连接如果一个TCP包丢了整个连接上的所有请求都要等待重传反而可能比HTTP/1.1的多个连接策略更慢。这也是HTTP/3用QUIC基于UDP的原因它把传输层的传输控制逻辑从TCP搬到了用户态从根上解决了TCP队头阻塞。讲到HTTP/3的时候多数面试官不会再深入考因为你已经展示了自己对网络协议演进的理解。但如果你能补一句“HTTP/3在弱网环境下的表现更好因为TCP丢包重传会拖慢所有流而QUIC只在丢失的那个流上重传”面试官基本会满意地点点头。7. Vue原理与框架考察抖音团队的技术栈验证7.1 简历写了Vue就要准备到响应式抖音前端团队的技术栈以Vue为主也有部分React团队所以一面里面Vue的题目是必考的如果你简历写了Vue的话。核心问题一定是Vue 2和Vue 3的响应式原理是什么有什么区别。Vue 2是Object.defineProperty对对象的每一个属性进行getter/setter拦截。它有两个经典的缺陷新增属性不是响应式的要用Vue.set直接通过下标修改数组的元素不是响应式的要重写数组的push、splice等方法。Vue 3用的是Proxy可以拦截整个对象的读取、设置、删除、枚举等操作所以新增删除属性、索引修改数组都能自动响应。这是原理层面最核心的区别要能背得熟练更要能理解为什么Proxy能做到而defineProperty做不到——因为Proxy劫持的是对象本身而不是对象的某个属性。当时他还追问了一个很实际的问题那Vue 3直接使用Proxy之后还需要重写数组的方法吗答案是不需要了因为数组索引赋值和length变化都可以被Proxy拦截到所以Vue 3不需要像Vue 2那样对数组方法做hack。但如果目标是性能优化Vue 3里对大型数组的处理仍然可以用markRaw或shallowRef等手段跳过深层响应式转换。7.2 computed和watch的区别讲了无数遍但回答模式固定这个问题几乎是Vue面试的必问基础。computed是依赖响应式数据自动缓存的计算结果只有依赖变了才会重新求值适合“根据现有数据派生出新数据”的场景。watch更多的是副作用当你需要监听某个数据的变化并执行一些操作比如请求接口、处理异步逻辑时使用。但要注意watch也可以配immediate: true让初始化时就执行一次deep: true做深层监听。面试官如果继续深挖会问“deep: true的实现原理是什么”答案是递归遍历每一个属性收集依赖这样任何一个嵌套属性的变化都能触发回调代价就是性能开销大所以能用computed、能用手动展开的watch就别无脑开deep。7.3 组件通信方式从基础到边界Vue组件通信我也是必答的。父子通信用props和emit跨多级、兄弟之间用EventBus或者Provide/Inject复杂的全局状态用Vuex或Pinia。面试官这个时候问我“Vue 3的provide/inject是响应式的吗”这是一个很容易答错的点。答案是provide的普通值不是响应式的但当传入的是ref或reactive对象时它本身具备响应性子组件注入后可以感知变化。如果provide的是一个普通字符串子组件里改它不会响应父组件更新也不会自动通知。这就要看你要共享的是“稳定配置”还是“动态状态”。如果团队里用Vue 3建议在跨层级共享状态的时候直接上ref结合provide别再用EventBus了。8. 反问环节你问什么问题决定面试官对你的印象一面到了尾声面试官都会给你反问的机会。很多人直接说“我没有问题了”这其实挺亏的。反问环节看起来不影响技术评分但能侧面反映你对这份工作的兴趣和思考深度。我的策略是问一个“基于当前团队业务和技术栈”的具体问题而不是问“你们公司福利怎么样”“加班多不多”这种问题。我当时问的是“抖音前端这边对性能指标是怎么采集和分析的入职之后是直接参与业务迭代还是有专门的时间做基础建设”这个问题一方面表达了我对性能优化的兴趣另一方面也帮我判断这个岗位的真实工作节奏算是双赢。另外一个比较稳的反问是“如果我有幸通过一面接下来二面会更侧重考察哪个方向您建议我重点准备什么”这个问法在字节系特别实用因为它不仅让面试官感受到你的上进来还直接帮你拿到了二面的准备方向。有次我真按面试官给的提示准备了二面果然考了那块的题。不过我这次面的时候也没问太细因为二面风格的随机性太大指望面试官给准备方向不如把基础知识全过一遍稳。注意反问环节绝对不能问“百度能搜到答案”的问题比如“你们用Vue几”。这种问题会让面试官觉得你对岗位没有做过任何调研。9. 常见问题与避坑技巧实录9.1 一面高频失分点汇总整理了一下我这次面试和身边朋友被问到的问题结合各自的答法我总结了一张高频失分点表几乎每一条都是我自己踩过或者看别人踩过的坑问题失分表现正确的答法方向var和let的区别只说“一个能重复声明一个不能”从作用域、变量提升、暂时性死区、全局对象属性四个维度展开事件代理的原理说“给父元素绑定事件”就完了要补上事件冒泡机制、e.target判断、动态绑定和解绑场景宏任务微任务执行顺序背输出结果、换一道题就不会要掌握“每次宏任务后清空微任务队列”的推导逻辑数组去重只会[...new Set(arr)]要能扩展到对象数组去重、NaN的去重、性能分析闭包内存泄漏一说内存泄漏就说“是”要区分真正泄漏的场景和正常回收场景CSS选择器优先级只会背“id大于class大于标签”要能说出内联样式、!important、继承权重的具体计算规则以及为什么通常不用!important盒模型说“标准盒模型和怪异盒模型”就完要能说出两者的区别本质在于width是否包含border和padding并能手写出box-sizing: border-box的实际计算过程这些失分点有一个共性只记得结论没有掌握底层推导过程。面试官一旦追问“为什么”就露馅。所以准备面经的时候不要只背“标准答案”还要给每个答案准备一个“为什么”。9.2 面试前3天的复习策略如果你离面试只剩三四天最有效的策略不是大量刷题而是把知识面过一遍保证“听到任何一个关键词都能立刻说出三层以上的内容”。我当时的方法是把所有高频考点写成一张Excel表每行一个考点每列分别是一句话定义、核心原理、常见面试追问、我的实战经历。复习的时候只看关键词列努力回忆另外四列的内容想不起来的再查资料补充。这个方法效率很高也避免了自己在熟悉的地方反复浪费时间。同时面试前一定要动手敲代码。别看“手写debounce”很简单面试时在白板上或者简答题框里写得和IDE里写完全两个感觉。没有IDE的自动补全和lint提示很容易漏边界条件。建议至少把debounce、throttle、深拷贝、Promise.all、数组拍平这五个手写题在记事本里各写两遍一遍无辅助一遍带着注释。9.3 一面最实用的三个技巧最后分享三个小技巧都是我自己实战中验证过的第一个遇到不会的问题别直接说“不知道”。说一句“这块我平时用的时候接触得比较少我尝试从原理上推一下”会让面试官对你有更好的印象。哪怕推导结果是错的也比直接放弃要强。前端面试考察的是思维过程不是标准答案的唯一性。第二个手写题写完一定要自己跑一遍测试用例。不用真开浏览器就在脑子里过一遍边界条件空数组、只有一个元素、参数缺省。很多时候代码逻辑没问题但忘了对参数做合法性判断这种低级错误非常影响评分。第三个回答算法或手写题的时候先说思路再写代码。如果你直接埋头写完再口述万一中间改来改去面试官很难跟上你的思路。先花30秒说“我准备用双指针左边往右移动找区间右边界右边往左移动收缩时间复杂度O(n)”再开始写整个过程会顺畅得多。之前我面过一次字节的其他部门就是因为手写题没先说思路写了半天发现方向偏了改代码过程中又出幺蛾子最后虽然写出来了但面试官反馈我的思路不够清晰。从那之后我养成了一个习惯任何一道手写题说了思路才动键盘。10. 一面整体节奏复盘把整个时间线拉出来一面基本就是这个节奏问候和寒暄2到3分钟自我介绍2到3分钟项目深挖10分钟上下JS基础15到20分钟CSS 5分钟浏览器与网络10分钟Vue框架10分钟手写题10分钟反问5分钟。整体算下来一问一答之间面试官留给你思考的时间并不多尤其是手写题他可能就给你5分钟。平时如果习惯在IDE里写代码建议提前在纯文本框里练习手写代码的速度和准确度。我这里没有说“面试造火箭、工作拧螺丝”的意思因为衡量一个前端工程师的基本功JS的执行机制、浏览器渲染流程、Vue响应式原理这些确实是日常开发天天在打交道的东西。所谓八股文本质上是把已知的问题用清晰的语言表达出来的能力。准备一面与其焦虑地刷几百道题不如先把“基础中的基础”吃透。只要把你简历里写过的每一项技术栈都能从使用层面讲到原理层面一面大概率是稳的。面完之后我心里反而比以前更确定了一件事那些看起来最难啃的底层知识比如事件循环、浏览器渲染、响应式原理恰恰是最能拉开区分度的地方。最后再给一个很实际的小建议面试时如果允许录像或录音一定要录下来。哪怕只是翻看自己当时说的原话也会发现很多“我当时怎么会这么说”的地方。面经是写给下一个自己看的而复盘是给正在准备的人看的两件事都做了这一场面试才算真正结束。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进