发布时间:2026/8/26 2:09:38
前端面试必考7类手写代码实战解析 1. 前端面试手写代码实战指南作为一名经历过京东等大厂面试的前端工程师我深知手写代码环节的重要性。这篇文章将详细解析京东等一线互联网公司前端面试中最常考的7类手写题包含完整实现、核心原理和电商场景应用。这些题目在我参与的面试中出现的频率高达90%掌握它们能显著提升面试通过率。2. 防抖与节流电商高频场景应用2.1 防抖(debounce)实现与原理防抖的核心思想是在事件频繁触发时只有当事件停止触发一段时间后才会执行处理函数。这在电商网站的搜索联想场景中尤为重要。/** * 防抖函数完整实现 * param {Function} fn - 需要防抖的函数 * param {number} delay - 延迟时间(毫秒) * param {boolean} immediate - 是否立即执行 */ function debounce(fn, delay 300, immediate false) { let timer null; return function(...args) { const context this; // 清除已有定时器保证唯一性 if (timer) clearTimeout(timer); if (immediate) { // 立即执行模式 const callNow !timer; // timer为null表示可以立即执行 timer setTimeout(() { timer null; // delay后重置timer }, delay); if (callNow) { fn.apply(context, args); } } else { // 非立即执行模式 timer setTimeout(() { fn.apply(context, args); }, delay); } }; }关键点说明闭包保存timer状态是防抖实现的核心apply确保函数执行时的this指向正确。2.2 京东实际应用场景搜索框联想用户输入时每按一个键都会触发搜索使用防抖可以避免频繁请求商品筛选条件变化价格区间滑动时实时筛选无限滚动加载滚动停止后再触发加载避免重复请求按钮防重复点击支付按钮等关键操作防止重复提交2.3 节流(throttle)的实现方案节流与防抖的区别在于节流保证在一定时间间隔内至少执行一次而防抖只在停止触发后执行一次。// 时间戳版首次立即执行 function throttle(fn, delay 300) { let lastTime 0; return function(...args) { const now Date.now(); if (now - lastTime delay) { fn.apply(this, args); lastTime now; } }; } // 定时器版最后一次也会执行 function throttleTimer(fn, delay 300) { let timer null; return function(...args) { const context this; if (!timer) { timer setTimeout(() { fn.apply(context, args); timer null; }, delay); } }; }3. 深拷贝的完整解决方案3.1 基础深拷贝实现深拷贝是前端面试必考题京东二面特别关注循环引用的处理。function deepClone(obj, map new WeakMap()) { // 处理基本类型和null if (typeof obj ! object || obj null) { return obj; } // 处理循环引用 if (map.has(obj)) { return map.get(obj); } // 初始化目标对象 let target Array.isArray(obj) ? [] : {}; map.set(obj, target); // 缓存已拷贝对象 // 处理Symbol属性 const symKeys Object.getOwnPropertySymbols(obj); if (symKeys.length) { symKeys.forEach(symKey { if (typeof obj[symKey] object obj[symKey] ! null) { target[symKey] deepClone(obj[symKey], map); } else { target[symKey] obj[symKey]; } }); } // 拷贝常规属性 for (let key in obj) { if (obj.hasOwnProperty(key)) { target[key] deepClone(obj[key], map); } } return target; }3.2 特殊类型处理完整的深拷贝还需要考虑以下特殊情况Date对象需要new Date(obj.getTime())RegExp对象需要new RegExp(obj.source, obj.flags)Function可以直接返回原函数还是需要克隆DOM元素通常直接返回原元素原型链是否需要保持原型关系4. Promise核心实现4.1 基础Promise实现class MyPromise { constructor(executor) { this.status pending; this.value undefined; this.reason undefined; this.onFulfilledCallbacks []; this.onRejectedCallbacks []; const resolve (value) { if (this.status ! pending) return; this.status fulfilled; this.value value; this.onFulfilledCallbacks.forEach(fn fn()); }; const reject (reason) { if (this.status ! pending) return; this.status rejected; this.reason reason; this.onRejectedCallbacks.forEach(fn fn()); }; try { executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { // 处理值穿透 onFulfilled typeof onFulfilled function ? onFulfilled : v v; onRejected typeof onRejected function ? onRejected : err { throw err }; const promise2 new MyPromise((resolve, reject) { if (this.status fulfilled) { setTimeout(() { try { const x onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); } else if (this.status rejected) { setTimeout(() { try { const x onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); } else { this.onFulfilledCallbacks.push(() { setTimeout(() { try { const x onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }); this.onRejectedCallbacks.push(() { setTimeout(() { try { const x onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }); } }); return promise2; } } function resolvePromise(promise2, x, resolve, reject) { // 避免循环引用 if (promise2 x) { return reject(new TypeError(Chaining cycle detected for promise)); } // 防止多次调用 let called false; if ((typeof x object x ! null) || typeof x function) { try { const then x.then; if (typeof then function) { then.call( x, y { if (called) return; called true; resolvePromise(promise2, y, resolve, reject); }, r { if (called) return; called true; reject(r); } ); } else { resolve(x); } } catch (e) { if (called) return; called true; reject(e); } } else { resolve(x); } }4.2 Promise扩展方法面试官可能会要求实现Promise.all、Promise.race等静态方法MyPromise.all function(promises) { return new MyPromise((resolve, reject) { const result []; let count 0; promises.forEach((p, i) { p.then( value { result[i] value; if (count promises.length) { resolve(result); } }, reason { reject(reason); } ); }); }); }; MyPromise.race function(promises) { return new MyPromise((resolve, reject) { promises.forEach(p { p.then(resolve, reject); }); }); };5. 函数柯里化与偏函数5.1 基础柯里化实现function curry(fn) { return function curried(...args) { if (args.length fn.length) { return fn.apply(this, args); } else { return function(...args2) { return curried.apply(this, args.concat(args2)); }; } }; } // 使用示例 function sum(a, b, c) { return a b c; } const curriedSum curry(sum); console.log(curriedSum(1)(2)(3)); // 6 console.log(curriedSum(1, 2)(3)); // 6 console.log(curriedSum(1)(2, 3)); // 65.2 京东实际应用场景参数复用电商中的折扣计算函数延迟执行表单验证规则组合动态生成函数根据用户权限生成不同的操作函数6. 前端性能监控实战6.1 核心性能指标FP (First Paint)首次绘制时间FCP (First Contentful Paint)首次内容绘制LCP (Largest Contentful Paint)最大内容绘制FID (First Input Delay)首次输入延迟CLS (Cumulative Layout Shift)累计布局偏移6.2 性能指标获取代码// 获取FP/FCP new PerformanceObserver((entryList) { const entries entryList.getEntries(); entries.forEach(entry { if (entry.name first-paint) { console.log(FP:, entry.startTime); } else if (entry.name first-contentful-paint) { console.log(FCP:, entry.startTime); } }); }).observe({ type: paint, buffered: true }); // 获取LCP new PerformanceObserver((entryList) { const entries entryList.getEntries(); const lastEntry entries[entries.length - 1]; console.log(LCP:, lastEntry.startTime); }).observe({ type: largest-contentful-paint, buffered: true }); // 获取CLS let clsValue 0; new PerformanceObserver((entryList) { const entries entryList.getEntries(); entries.forEach(entry { if (!entry.hadRecentInput) { clsValue entry.value; } }); console.log(CLS:, clsValue); }).observe({ type: layout-shift, buffered: true });6.3 京东性能优化实践LCP优化关键图片预加载使用WebP格式关键CSS内联非关键JS延迟加载CLS优化图片和视频设置固定宽高避免在现有内容上方插入动态内容使用transform动画代替影响布局的属性FID优化减少主线程长任务优化第三方脚本使用Web Worker处理复杂计算7. 电商业务常用工具函数7.1 数组去重高级实现// 支持对象去重 function unique(arr, key) { if (!key) { return [...new Set(arr)]; } const map new Map(); return arr.filter(item { const keyValue item[key]; if (!map.has(keyValue)) { map.set(keyValue, true); return true; } return false; }); } // 使用示例 const products [ { id: 1, name: iPhone }, { id: 2, name: iPad }, { id: 1, name: iPhone 13 } ]; console.log(unique(products, id)); // 输出: [{id:1,name:iPhone}, {id:2,name:iPad}]7.2 金额格式化增强版function formatMoney(cent, options {}) { const { prefix ¥, decimal 2, thousand ,, isNegativeRed true } options; let amount cent / 100; const isNegative amount 0; amount Math.abs(amount); let [integer, fraction] amount.toFixed(decimal).split(.); integer integer.replace(/\B(?(\d{3})(?!\d))/g, thousand); let result ${prefix}${integer}; if (decimal 0) { result .${fraction}; } if (isNegative) { result -${result}; if (isNegativeRed) { result span stylecolor:red${result}/span; } } return result; } // 使用示例 console.log(formatMoney(123456)); // ¥1,234.56 console.log(formatMoney(-123456, { isNegativeRed: false })); // -¥1,234.567.3 手机号/邮箱脱敏工具function maskInfo(str, type phone) { const patterns { phone: { regex: /(\d{3})\d{4}(\d{4})/, replacement: $1****$2 }, email: { regex: /(\w{1,3})[\w.-]*([\w-]\.)[\w-]{2,4}/, replacement: $1***$2 }, idCard: { regex: /(\d{4})\d{10}(\w{4})/, replacement: $1**********$2 } }; const { regex, replacement } patterns[type] || patterns.phone; return str.replace(regex, replacement); } // 使用示例 console.log(maskInfo(13812345678)); // 138****5678 console.log(maskInfo(testexample.com, email)); // tes***example.com8. 面试准备建议手写代码练习每天至少手写3个核心函数注意边界条件性能优化理解每个性能指标背后的优化原理能举例说明电商场景熟悉常见业务逻辑的实现方式代码规范注意变量命名、代码格式和注释调试能力能解释每行代码的作用和可能的问题在实际面试中面试官不仅关注代码能否运行更关注实现思路、边界条件处理和性能考虑。建议在实现完基础功能后主动讨论可能的优化空间和替代方案。

相关新闻

2026/8/26 2:04:38

GFS-VL:融合3D VLM稠密知识与少样本校准的点云分割新思路

CVPR 2025 的三维点云分割工作不少,但把 3D VLM 的稠密知识引入少样本分割,并专门做校准的框架,GFS-VL 是比较值得关注的一个。它的目标很明确:在每一类只有少量标注样本的情况下,让模型仍然能对点云做高质量分割。这个…

2026/8/26 2:04:38

锁相放大器原理详解:从相敏检测到数字解调实现

第一次接触锁相放大器(Lock-in Amplifier)是在做光电检测实验的时候。当时要测一个被强背景光完全淹没的微弱反射信号,示波器上能看到的就是一片随机抖动的噪声,普通万用表接上去读数根本没有意义。导师把一台锁相放大器放到桌上&…

2026/8/26 2:04:38

2026-08-25 GitHub 热点项目精选

/* 全局样式 */* { margin: 0; padding: 0; box-sizing: border-box; }body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;max-width: 900px; margin: 0 auto; padding: 30px 20px; line-height: 1.7; color: #2d3748;backgro…

2026/8/26 4:44:44

SQL LIMIT 分页查询实战:从基础语法到深度优化与性能陷阱

1. 从“只取前几条”到“精准分页”:LIMIT 的两种形态如果你刚开始接触SQL,或者在工作中需要处理数据查询,那么LIMIT这个关键字几乎是你绕不开的第一道坎。它看起来很简单,不就是“限制一下返回的行数”嘛。但就是这么一个简单的命…

2026/8/26 4:44:44

C++面试核心:从语法到系统设计的深度准备指南

1. 从“最全”到“最有用”:一份C面试指南的自我修养每次看到“最全”、“BAT大厂面试总结”这样的标题,我都会下意识地皱一下眉头。倒不是说这些资料不好,而是它们往往给人一种错觉:只要背下这份“题库”,就能轻松通关…

2026/8/26 4:44:44

LeetCode面试经典150题Python解析与刷题指南

1. 项目背景与核心价值作为一名经历过多次技术面试的老兵,我深知算法题在面试中的分量。最近在整理自己的刷题笔记时,发现LeetCode上的"面试经典150题"被众多求职者奉为圭臬。这套题目精选了高频出现的算法题型,覆盖了数据结构与算…

2026/8/26 4:44:44

大学生网络安全实习指南:从入门到实战

1. 大学生网络安全实习现状与价值网络安全行业近年来呈现爆发式增长态势,根据最新行业报告显示,全球网络安全人才缺口已突破300万。对于在校大学生而言,安全实习不仅是进入这个朝阳产业的敲门砖,更是将理论知识转化为实战能力的关…

2026/8/26 4:44:44

自制电机测功机:从方案选型到实测验证的完整指南

过去半年我一直在做小型无刷电机的性能摸底评测,手头攒了各种渠道弄来的电机,从几十瓦的云台无刷电机到几百瓦的电动自行车轮毂电机都有。标称参数一个比一个漂亮,但实际跑起来到底什么水平,不上设备测根本说不清楚。要给电机做性…

2026/8/26 4:39:44

C++进阶:定位new与模板编程的内存控制与泛型设计

1. 从“内存复用”到“类型泛化”:C进阶路上的两块硬骨头干了这么多年C,我越来越觉得,这门语言就像一座冰山。你学个语法、写个循环,那只是看到了水面上的十分之一。真正让程序健壮、高效且优雅的,是水面下那些复杂而精…

2026/8/25 1:04:19

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/25 11:48:27

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/25 16:56:43

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/26 0:04:32

Python random 模块常用函数详解:从入门到实战

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要: 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数(random()、unifor…

2026/8/26 1:19:35

JSON总结

JSON概念 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,主要用于跟服务器进行交换数据。它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C、C#、Java、JavaScr…

2026/8/26 1:19:35

保存连接sse 是什么原理,为什么不会一直请求

“保持连接”用的是 SSE(Server-Sent Events),本质是一个没有马上结束的 HTTP 请求。 过程是: 拷贝机发送一次请求: GET /api/code-sync/events服务器返回: Content-Type: text/event-stream但不关闭响应&…

2026/8/24 13:42:17

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/24 18:13:48

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/25 1:08:14

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…