前端八股文面经大全:字节前端一面(2026-2-1)·面经深度解析
前言
大家好,我是木斯佳。
在这个春节假期,当大家都在谈论返乡、团圆与休息时,作为一名技术人,我的思考却不由自主地转向了行业的「冬」与「春」。
相信很多人都感受到了,在AI浪潮的席卷之下,前端领域的门槛在变高,纯粹的“增删改查”岗位正在肉眼可见地减少。曾经热闹非凡的面经分享,如今也沉寂了许多。但我们都知道,市场的潮水退去,留下的才是真正在踏实准备、努力沉淀的人。学习的需求,从未消失,只是变得更加务实和深入。
正值春节,也是复盘与规划的好时机。结合ZEEKLOG这次「春节代码贺新年」活动所提倡的“用技术视角记录春节、复盘成长”,我决定在这个假期持续更新专栏,帮助年后参加春招的同学。
这个专栏的初衷很简单:拒绝过时的、流水线式的PDF引流贴,专注于收集和整理当下最新、最真实的前端面试资料。
我会在每一份面经和八股文的基础上,尝试从面试官的角度去拆解问题背后的逻辑,而不仅仅是提供一份静态的背诵答案。无论你是校招还是社招,目标是中大厂还是新兴团队,只要是真实发生、有价值的面试经历,我都会在这个专栏里为你沉淀下来。
温馨提示:市面上的面经鱼龙混杂,甄别真伪、把握时效,是我们对抗内卷最有效的武器。
在这个假期,让我们一起充电,为下一个技术春天做好准备。

面经原文内容
📍面试公司:字节
🕐面试时间: 2 月 1 日
💻面试岗位:前端
❓面试问题:
- 1.自我介绍
- 2.平时如何学习前端
- 3.实验室的指导
- 4.用户在浏览器地址栏输入一万到页面展示发生了什么(http,浏览器渲染逻辑)
- 5.异步代码输出(set time out,async)
- 6.js事件循环
- 7.css垂直居中
- 8.position垂直居中具体做法
- 9.vue响应式原理(vue2.3)
- 10.工作中遇到的设计模式
- 11.选择器优先级
- 12.git代码提交冲突怎么解决
- 13.项目:拖拽功能实现,图片懒加载(什么情况下加载什么情况下不加载)
- 14.项目中最有技术挑战的是什么
- (1)实现new操作符
(2)列表到数的数据变形
- (1)实现new操作符
来源: 牛客网 温柔的海螺ssp到手了
📝 字节前端一面·面经深度解析
🎯 面试整体画像
| 维度 | 特征 |
|---|---|
| 部门定位 | 字节跳动(未明确部门) |
| 面试风格 | 广度覆盖型 |
| 难度评级 | ⭐⭐(两星,覆盖面广都是常见八股文) |
| 考察重心 | 网络原理、事件循环、Vue原理、设计模式、Git协作、手写实现 |
🌐 从输入URL到页面展示·完整流程
问题:用户在浏览器地址栏输入URL到页面展示发生了什么
✅ 参考复习知识:
第一阶段:网络请求
// 1. URL解析- 协议(http/https) - 域名(www.example.com) - 端口(默认80/443) - 路径(/path/to/resource) - 参数(?key=value) - 哈希(#section) // 2. DNS解析- 浏览器缓存 → 操作系统缓存 → 本地hosts文件 → 路由器缓存 → ISPDNS → 根域名服务器 - 递归查询 vs 迭代查询 -DNS预解析:<link rel="dns-prefetch" href="//example.com">// 3. TCP连接(三次握手) 客户端 ──SYN──> 服务端 客户端 <─SYN+ACK─ 服务端 客户端 ──ACK──> 服务端 // 4. TLS握手(HTTPS)- Client Hello(支持的加密套件) - Server Hello(选择加密套件 + 证书) - 客户端验证证书 - 密钥交换(RSA/ECDHE) - 生成会话密钥 - 加密通信开始 // 5. HTTP请求- 请求行(GET/path HTTP/1.1) - 请求头(Host、User-Agent、Accept等) - 请求体(POST数据) // 6. 服务器处理- 负载均衡 - 反向代理(Nginx) - 应用服务器处理 - 数据库查询 - 生成响应 // 7. HTTP响应- 状态码(200、304、404等) - 响应头(Content-Type、Cache-Control等) - 响应体(HTML/JSON等) // 8. TCP四次挥手 客户端 ──FIN──> 服务端 客户端 <─ACK─── 服务端 客户端 <─FIN─── 服务端 客户端 ──ACK──> 服务端 第二阶段:浏览器渲染
// 1. 解析HTML生成DOM树HTML字符串 → 词法分析 → 语法分析 → DOM树 // 2. 解析CSS生成CSSOM树CSS字符串 → 词法分析 → 语法分析 → CSSOM树 // 3. 合并生成渲染树(Render Tree)DOM树 +CSSOM树 → 去除不可见元素(head、display:none)→ 渲染树 // 4. 布局(Layout/Reflow) 计算每个元素在视口中的确切位置和大小 - 盒模型计算 - 相对单位转换(rem、vw等) - 浮动、定位处理 // 5. 绘制(Paint) 将元素绘制到屏幕上 - 绘制背景、边框、文字、阴影等 - 分层绘制(图层独立) // 6. 合成(Composite) 将不同图层合成最终图像 -GPU加速(transform、opacity) - 避免重绘重排 第三阶段:特殊处理
// 优化点1. 预加载扫描器(Preload Scanner) - 在构建DOM树的同时,提前加载资源 2. 渲染阻塞 -CSS阻塞渲染(CSSOM未构建完成) -JS阻塞解析(async/defer优化) 3. 关键渲染路径 - 首屏渲染优化 - 避免长时间JS执行 💡 面试官考察点:
这个问题不是让你背流程,而是看你对Web技术栈的整体理解
能讲出细节(如TLS握手、渲染树构建) → 加分
能讲出优化点 → 加分
🔄 异步代码输出·事件循环
问题:异步代码输出 + JS事件循环
✅ 完整解析:
1. 典型考题
asyncfunctionasync1(){ console.log('async1 start');awaitasync2(); console.log('async1 end');}asyncfunctionasync2(){ console.log('async2');} console.log('script start');setTimeout(()=>{ console.log('setTimeout');},0);async1();newPromise((resolve)=>{ console.log('promise1');resolve();}).then(()=>{ console.log('promise2');}); console.log('script end');// 输出顺序:// script start// async1 start// async2// promise1// script end// async1 end// promise2// setTimeout2. 关键点解析
// 为什么await后面的代码在promise2之前?-awaitasync2() 相当于 Promise.resolve(async2()).then(()=>{ console.log('async1 end')})- 但这里有一个微任务队列的微妙顺序 // 更精确的理解asyncfunctiontest(){ console.log('1');await1;// 相当于 Promise.resolve(1).then() console.log('2');}// 等价于functiontest(){ console.log('1');return Promise.resolve(1).then(()=>{ console.log('2');});}3. 事件循环机制
// 完整流程1. 执行当前宏任务(同步代码) 2. 执行所有微任务(清空微任务队列) 3. 尝试渲染(requestAnimationFrame) 4. 取下一个宏任务 // 宏任务与微任务宏任务队列:[setTimeout, setInterval,I/O,UI渲染]微任务队列:[Promise.then, MutationObserver, queueMicrotask]// 特殊说明- 微任务中产生的微任务,会在当前宏任务结束前执行(不是下一轮) - requestAnimationFrame 在渲染前执行 - requestIdleCallback 在空闲时执行 🎨 CSS垂直居中·全方案总结
问题:CSS垂直居中 + position垂直居中具体做法
✅ 完整方案:
1. Flexbox方案(推荐)
.container{display: flex;align-items: center;/* 垂直居中 */justify-content: center;/* 水平居中(可选) */height: 300px;}2. Grid方案
.container{display: grid;place-items: center;/* 同时垂直水平居中 */height: 300px;}3. Position + Transform(最常考)
.container{position: relative;height: 300px;}.child{position: absolute;top: 50%;transform:translateY(-50%);/* 向上移动自身高度的一半 *//* 水平居中 */left: 50%;transform:translate(-50%, -50%);}4. Position + Margin(需知宽高)
.child{position: absolute;top: 50%;left: 50%;width: 200px;height: 100px;margin-top: -50px;/* 高度的一半 */margin-left: -100px;/* 宽度的一半 */}5. Line-height(单行文本)
.container{height: 300px;line-height: 300px;/* 与高度相等 */text-align: center;}6. Table-cell
.container{display: table-cell;vertical-align: middle;text-align: center;height: 300px;}7. 伪元素法
.container::before{content:'';display: inline-block;height: 100%;vertical-align: middle;}.child{display: inline-block;vertical-align: middle;}💡 面试官追问:
position垂直居中为什么用translateY(-50%)而不是margin-top?
- translateY(-50%) 相对于元素自身高度,不需要知道具体数值 - margin-top 相对于父容器宽度(怪异),且需要知道高度 - translate 触发GPU加速,性能更好 ⚛️ Vue响应式原理·Vue2 vs Vue3
问题:vue响应式原理(vue2.3)
✅ 完整对比:
Vue2响应式(Object.defineProperty)
// 核心实现functiondefineReactive(obj, key, val){// 递归处理嵌套对象observe(val);const dep =newDep();// 依赖收集器 Object.defineProperty(obj, key,{enumerable:true,configurable:true,get(){// 依赖收集if(Dep.target){ dep.depend();}return val;},set(newVal){if(newVal === val)return; val = newVal;// 对新值进行响应式处理observe(newVal);// 触发更新 dep.notify();}});}// 数组处理(需要hack)const arrayMethods = Object.create(Array.prototype);['push','pop','shift','unshift','splice','sort','reverse'].forEach(method=>{const original = arrayMethods[method]; arrayMethods[method]=function(...args){const result =original.apply(this, args);const ob =this.__ob__;// 触发更新 ob.dep.notify();return result;};});Vue2的局限性
// 1. 无法检测属性新增/删除 Vue.set(obj,'newProp', value);// 必须用Vue.set Vue.delete(obj,'prop');// 必须用Vue.delete// 2. 无法直接监听数组索引变化this.arr[0]=1;// 不会触发更新this.arr.splice(0,1,1);// 必须用splice// 3. 初始化时递归遍历所有属性,性能开销Vue3响应式(Proxy)
functionreactive(target){returnnewProxy(target,{get(target, key, receiver){// 依赖收集track(target, key);const value = Reflect.get(target, key, receiver);// 懒响应式:只有访问时才处理嵌套对象if(typeof value ==='object'&& value !==null){returnreactive(value);}return value;},set(target, key, value, receiver){const oldValue = target[key];const result = Reflect.set(target, key, value, receiver);if(oldValue !== value){// 触发更新trigger(target, key);}return result;},deleteProperty(target, key){const hadKey = Reflect.has(target, key);const result = Reflect.deleteProperty(target, key);if(hadKey){trigger(target, key);}return result;}});}Vue3的优势
// 1. 可以监听新增/删除属性const obj =reactive({}); obj.newProp ='value';// ✅ 响应式// 2. 可以监听数组索引变化const arr =reactive([1,2,3]); arr[0]=10;// ✅ 触发更新// 3. 懒响应式,性能更好// 只有访问嵌套对象时才进行响应式处理// 4. 支持Map、Set等const map =reactive(newMap()); map.set('key','value');// ✅ 响应式🏗️ 设计模式·前端常见模式
问题:工作中遇到的设计模式
✅ 前端常用设计模式:
1. 单例模式(Singleton)
// 场景:全局状态管理、全局弹窗classStore{constructor(){if(Store.instance){return Store.instance;}this.state ={}; Store.instance =this;}}// Vuex/Pinia 本质就是单例const store =createPinia();2. 观察者模式(Observer)
// 场景:事件总线、Vue响应式classEventBus{constructor(){this.events ={};}on(event, callback){if(!this.events[event]){this.events[event]=[];}this.events[event].push(callback);}emit(event, data){if(this.events[event]){this.events[event].forEach(cb=>cb(data));}}}// Vue的$on/$emit 就是观察者模式3. 工厂模式(Factory)
// 场景:创建不同类型的组件classButtonFactory{createButton(type){switch(type){case'primary':returnnewPrimaryButton();case'danger':returnnewDangerButton();default:returnnewDefaultButton();}}}4. 策略模式(Strategy)
// 场景:表单验证、动画算法const validators ={required:(value)=>!!value,email:(value)=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),minLength:(value, length)=> value.length >= length };functionvalidate(value, rules){for(const rule of rules){const[name,...args]= rule.split(':');if(!validators[name](value,...args)){returnfalse;}}returntrue;}5. 装饰器模式(Decorator)
// 场景:高阶组件、AOPfunctionwithLogging(Component){return(props)=>{useEffect(()=>{ console.log('组件渲染', Component.name);});return<Component {...props}/>;};}// 使用const LoggedButton =withLogging(Button);6. 代理模式(Proxy)
// 场景:图片懒加载、缓存代理constimageProxy=(src)=>{const img =newImage();const proxy =newProxy(img,{set(target, key, value){if(key ==='src'){// 显示占位图 target.src ='placeholder.jpg';// 真正加载setTimeout(()=>{ target.src = value;},100);}returntrue;}}); proxy.src = src;return proxy;};🎯 CSS选择器优先级
问题:选择器优先级
✅ 完整规则:
1. 优先级计算(权重)
/* 权重计算规则 */!important > 内联样式 > ID选择器 > 类选择器/属性/伪类 > 元素/伪元素 > 通配符 /* 具体数值(256进制) */ - 内联样式:1000 - ID选择器:0100 - 类/属性/伪类:0010 - 元素/伪元素:0001 - 通配符(*):0000 - 继承:无权重 /* 示例 */ #nav .list li a:hover /* 权重:0100 + 0010 + 0001 + 0001 + 0010 = 0122 */2. 特殊情况
/* !important 最高优先级 */.color{color: blue !important;/* 最高 */}/* 相同权重,后面的覆盖前面的 */.title{color: red;}.title{color: blue;}/* 生效 *//* 继承的样式优先级最低 */.parent{color: red;}.child{/* 继承的color优先级为0,会被任何直接样式覆盖 */}3. 实用技巧
/* 增加优先级的方法 */- 重复选择器:.title.title{color: red;}/* 权重加倍 */ - 添加父选择器:.container .title - 使用id:不要滥用 - !important:最后手段 🔧 Git代码冲突解决
问题:git代码提交冲突怎么解决
✅ 完整流程:
1. 冲突产生的原因
# 两人修改同一文件的同一区域 A修改了main.js的第10行并push B也修改了main.js的第10行,然后pull时产生冲突 2. 解决步骤
# 1. 拉取最新代码git pull origin main # 2. 看到冲突提示# Automatic merge failed; fix conflicts and then commit the result.# 3. 查看冲突文件git status # both modified: src/main.js# 4. 打开冲突文件<<<<<<< HEAD 当前分支的修改 ======= 合并进来的修改 >>>>>>> feature-branch # 5. 手动解决冲突# 选择保留哪个,或者合并两者# 删除冲突标记 <<< === >>># 6. 标记为已解决gitadd src/main.js # 7. 完成合并git commit -m "解决冲突"# 8. 推送git push 3. 更优雅的解决方式
# 使用merge工具git mergetool # 使用rebase避免多余合并记录git pull --rebase # 然后逐个解决冲突gitadd.git rebase --continue # 如果解决过程中想放弃git merge --abort # 或git rebase --abort 4. 预防冲突的策略
// 1. 频繁pull git pull --rebase 每天上班第一件事 // 2. 小粒度提交 不要攒一周的代码才提交 // 3. 明确分工 避免多人同时修改同一文件 // 4. 代码审查PR/MR时及早发现潜在冲突 🖱️ 拖拽功能实现
问题:项目中的拖拽功能实现
✅ 完整实现:
1. 原生拖拽API
// HTML5 Drag and Drop<div draggable="true" ondragstart="dragStart(event)"> 可拖拽元素 </div>functiondragStart(e){ e.dataTransfer.setData('text/plain', e.target.id); e.dataTransfer.effectAllowed ='move';}functiondrop(e){ e.preventDefault();const data = e.dataTransfer.getData('text/plain');const element = document.getElementById(data); e.target.appendChild(element);}2. 鼠标事件模拟(更常用)
classDraggable{constructor(element){this.element = element;this.isDragging =false;this.startX =0;this.startY =0;this.initialLeft =0;this.initialTop =0;this.bindEvents();}bindEvents(){this.element.addEventListener('mousedown',this.onMouseDown.bind(this)); document.addEventListener('mousemove',this.onMouseMove.bind(this)); document.addEventListener('mouseup',this.onMouseUp.bind(this));}onMouseDown(e){this.isDragging =true;// 记录初始位置this.startX = e.clientX;this.startY = e.clientY;// 获取元素当前位置const rect =this.element.getBoundingClientRect();this.initialLeft = rect.left;this.initialTop = rect.top;this.element.style.position ='absolute';this.element.style.zIndex ='1000';this.element.style.cursor ='grabbing';// 阻止默认事件(避免选中文本) e.preventDefault();}onMouseMove(e){if(!this.isDragging)return;// 计算移动距离const dx = e.clientX -this.startX;const dy = e.clientY -this.startY;// 设置新位置this.element.style.left =this.initialLeft + dx +'px';this.element.style.top =this.initialTop + dy +'px';// 可选:添加边界限制this.applyBoundary();}onMouseUp(){this.isDragging =false;this.element.style.cursor ='grab';}applyBoundary(){const left =parseInt(this.element.style.left);const top =parseInt(this.element.style.top);const parent =this.element.parentElement;if(parent){const maxLeft = parent.clientWidth -this.element.offsetWidth;const maxTop = parent.clientHeight -this.element.offsetHeight;this.element.style.left = Math.max(0, Math.min(left, maxLeft))+'px';this.element.style.top = Math.max(0, Math.min(top, maxTop))+'px';}}}🖼️ 图片懒加载
问题:图片懒加载(什么情况下加载,什么情况下不加载)
✅ 参考实现:
1. Intersection Observer(推荐)
classLazyLoader{constructor(){this.images = document.querySelectorAll('img[data-src]');this.observer =null;this.init();}init(){// 创建观察者this.observer =newIntersectionObserver((entries)=>{ entries.forEach(entry=>{// 当图片进入视口时加载if(entry.isIntersecting){const img = entry.target;this.loadImage(img);// 加载后停止观察this.observer.unobserve(img);}});},{root:null,// 视口rootMargin:'50px',// 提前50px加载threshold:0.01// 出现1%时触发});// 开始观察this.images.forEach(img=>{this.observer.observe(img);});}loadImage(img){const src = img.dataset.src;if(src){ img.src = src; img.removeAttribute('data-src');// 添加加载完成类 img.addEventListener('load',()=>{ img.classList.add('loaded');});}}}// 使用const lazyLoader =newLazyLoader();2. 什么情况下加载?
// 加载条件:1. 图片进入视口(或即将进入) 2. 浏览器空闲时(预加载) 3. 网络状态良好(4G/WiFi) 4. 用户即将滚动到该位置(预测) // 不加载条件:1. 图片远离视口 2. 网络状态差(2G/弱网) 3. 节省流量模式开启 4.图片被display:none隐藏 3. 优化版本(考虑网络状态)
classSmartLazyLoaderextendsLazyLoader{constructor(){super();this.connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;this.checkNetwork();}checkNetwork(){if(this.connection){// 监听网络变化this.connection.addEventListener('change',this.onNetworkChange.bind(this));// 判断是否应该加载if(this.shouldLoad()){this.startObserving();}else{this.pauseObserving();}}}shouldLoad(){if(!this.connection)returntrue;// 2G网络不预加载if(this.connection.effectiveType.includes('2g')){returnfalse;}// 流量敏感if(this.connection.saveData){returnfalse;}returntrue;}onNetworkChange(){if(this.shouldLoad()){this.startObserving();}else{this.pauseObserving();}}}🏗️ 实现new操作符
问题:实现new操作符
✅ 参考实现:
functionmyNew(constructor,...args){// 1. 创建一个空对象,原型指向构造函数的prototypeconst obj = Object.create(constructor.prototype);// 2. 将构造函数的this指向这个对象,并执行构造函数const result =constructor.apply(obj, args);// 3. 判断返回值// 如果构造函数返回对象,则返回该对象;否则返回创建的对象return(typeof result ==='object'&& result !==null)||typeof result ==='function'? result : obj;}// 测试functionPerson(name, age){this.name = name;this.age = age;// 如果没有return,默认返回this}const p1 =myNew(Person,'Tom',18); console.log(p1);// Person { name: 'Tom', age: 18 } console.log(p1 instanceofPerson);// true// 测试构造函数返回对象的情况functionReturnsObject(name){this.name = name;return{custom:'object'};}const p2 =myNew(ReturnsObject,'Jerry'); console.log(p2);// { custom: 'object' },不是ReturnsObject的实例关键点解析:
// 1. Object.create 相当于const obj ={}; obj.__proto__ = constructor.prototype;// 2. 处理返回值- 如果构造函数返回原始类型(string/number/boolean等),忽略,返回obj - 如果构造函数返回对象/函数,返回该对象 -null是特殊情况(typeofnull==='object'),返回obj 🌳 列表转树·数据变形
问题:列表到树的数据变形
✅ 参考实现:
1. 题目理解
// 输入const list =[{id:1,name:'节点1',parentId:null},{id:2,name:'节点2',parentId:1},{id:3,name:'节点3',parentId:1},{id:4,name:'节点4',parentId:2},{id:5,name:'节点5',parentId:3}];// 输出const tree =[{id:1,name:'节点1',children:[{id:2,name:'节点2',children:[{id:4,name:'节点4',children:[]}]},{id:3,name:'节点3',children:[{id:5,name:'节点5',children:[]}]}]}];2. 一次遍历 + Map
functionlistToTree(list){const map =newMap();const roots =[];// 第一次遍历:建立 id -> node 映射 list.forEach(item=>{ map.set(item.id,{...item,children:[]});});// 第二次遍历:建立父子关系 list.forEach(item=>{const node = map.get(item.id);if(item.parentId ===null|| item.parentId ===undefined){// 根节点 roots.push(node);}else{// 子节点,找到父节点并添加const parent = map.get(item.parentId);if(parent){ parent.children.push(node);}else{// 处理父节点不存在的情况(数据错误) roots.push(node);}}});return roots;}3. 递归版本(适用于小数据)
functionlistToTreeRecursive(list, parentId =null){return list .filter(item=> item.parentId === parentId).map(item=>({...item,children:listToTreeRecursive(list, item.id)}));}4. 进阶要求:排序、过滤
functionlistToTreeAdvanced(list, options ={}){const{ idKey ='id', parentKey ='parentId', childrenKey ='children', sortKey =null, sortOrder ='asc', filter =null}= options;const map =newMap();const roots =[];// 过滤const filteredList = filter ? list.filter(filter): list;// 建立映射 filteredList.forEach(item=>{ map.set(item[idKey],{...item,[childrenKey]:[]});});// 建立关系 filteredList.forEach(item=>{const node = map.get(item[idKey]);const parentId = item[parentKey];if(parentId ===null|| parentId ===undefined){ roots.push(node);}else{const parent = map.get(parentId);if(parent){ parent[childrenKey].push(node);}}});// 排序if(sortKey){constsortFn=(a, b)=>{if(sortOrder ==='asc'){return a[sortKey]> b[sortKey]?1:-1;}else{return a[sortKey]< b[sortKey]?1:-1;}};constsortTree=(nodes)=>{ nodes.sort(sortFn); nodes.forEach(node=>{if(node[childrenKey].length){sortTree(node[childrenKey]);}});};sortTree(roots);}return roots;}5. 应用场景
// 1. 组织架构图// 2. 权限菜单树// 3. 评论楼中楼// 4. 商品分类// 5. 地区选择器🎁 附:字节一面复习清单
| 知识点 | 掌握程度 | 重点方向 |
|---|---|---|
| 输入URL全过程 | ⭐⭐⭐⭐⭐ | DNS、TCP、TLS、HTTP、渲染 |
| 事件循环 | ⭐⭐⭐⭐⭐ | 宏任务/微任务、async/await |
| CSS垂直居中 | ⭐⭐⭐⭐ | 多种方案、优缺点 |
| Vue响应式 | ⭐⭐⭐⭐ | Vue2/3对比、原理实现 |
| 设计模式 | ⭐⭐⭐ | 常见模式、应用场景 |
| 选择器优先级 | ⭐⭐⭐ | 权重计算、特殊情况 |
| Git冲突解决 | ⭐⭐⭐ | 解决流程、预防策略 |
| 拖拽实现 | ⭐⭐⭐ | 原生API、鼠标模拟 |
| 图片懒加载 | ⭐⭐⭐ | Intersection Observer、网络判断 |
| new实现 | ⭐⭐⭐⭐ | 原型链、返回值处理 |
| 列表转树 | ⭐⭐⭐⭐ | 一次遍历、递归、排序过滤 |
📌 最后一句:
木木复盘:虽然分享者没有明确指出是实习还是校招面试,个人感觉这里的大部分八股已经在其他的面经中有遇到了,整体准备充分的话,这场面试应该会比较从容。这也是我提倡大家去复盘面经的原因。