JS超过Number最大值的数怎么处理?
前端最容易踩的大数坑通常有两类: 金额、计数、ID 这类“看起来是整数”的东西,一旦超过 2^53 - 1(Number.MAX_SAFE_INTEGER),就会开始丢精度; 真的特别大的浮点数,超过 Number.MAX_VALUE 直接变成 Infinity。 原因也很简单:JavaScript 的 Number 用的是 IEEE 754 双精度浮点。它能表示很大的范围,但整数精度只有 53 位。 超出 Number.MAX_VALUE:超出此值的数值会变为 Infinity。 超过安全整数范围:大于 Number.MAX_SAFE_INTEGER 的整数可能会失去精度。 遇到这些问题时,别急着“找一个库来解决”。先想清楚:你要处理的是“大整数”、还是“高精度小数”(比如金融)?两者方案不一样。 使用 BigIntES2020 引入了 BigInt,用来表示任意大小的整数。它的心智模型也很直接:只要是整数,就不会丢精度。 123// 创建一个超过 Number.MAX_SAFE_INTEGER 的整数const bigIntValue = 900719925474...
前端页面性能优化应该从哪些方向来思考?
页面性能优化最容易走偏的一点是:一上来就“上手段”(压缩、上 CDN、拆包),但没有度量闭环。我的习惯是先把指标跑起来(本地 + 线上),再按问题类型逐个拆解:体积、网络、渲染路径、主线程、用户感知,最后再用工程化把基线守住。 一、先谈“怎么量”——关键指标 Core Web Vitals: LCP(Largest Contentful Paint):最大内容绘制时间,衡量首屏主要内容何时可见。 INP(Interaction to Next Paint):交互到下一帧的时延,替代 FID 评估交互响应性。 CLS(Cumulative Layout Shift):累积布局偏移,衡量页面稳定性。 其他常用指标:TTFB、FCP、TTI、TBT、FP/FMP、JS long task 数量等。 小建议:本地 Lighthouse 先摸个底,线上用 RUM(真实用户监控)看真实分布,最好再按设备/网络分层,不然平均值很容易骗你。 二、资源体积优化(越少越好)1. JavaScript:减少、拆分、可缓存 Tree Shaking / Dead ...
何为 Babel Runtime?
第一次在依赖树里看到 babel-runtime/@babel/runtime,很多人会下意识以为它是“又一个 polyfill 包”。但它更像是一套“编译时生成代码的公共工具箱”:把那些会重复出现在每个文件里的 helper 抽出来复用,减少产物体积;同时也能在需要时避免直接往全局对象上打补丁。 什么是 Babel Runtime?Babel Runtime 可以理解成 Babel 的“运行时配套包”,主要做两件事: 复用 helper:比如 class 继承、对象展开、async/await 的一些辅助逻辑。如果每个文件都内联一份 helper,bundle 里会出现大量重复代码。 (可选)避免全局污染:有些能力如果靠 polyfill,会往全局(比如 Promise、Array.prototype)上“补方法”。做业务项目通常问题不大,但写 SDK/组件库时就很容易和别人的环境打架。 通常它会和 transform runtime 插件一起用:编译阶段把“内联 helper”替换成“从 runtime 包里 import”。 说明:Babel ...
如何判断 DOM 元素是否在可视区域?
“怎么判断一个元素在不在可视区域?”这个问题很像“怎么判断你老板在不在工位?”——你当然可以一直探头看(scroll 事件里狂算),但你也可以请前台帮你盯着(IntersectionObserver)。 区别就是:前者你累、页面也累;后者你轻松,浏览器也更愿意配合。 先把需求说清楚:你到底要判断哪一种“可见”?很多 bug 的根源不是 API,用错了,而是你们根本没对齐“可见”的定义。常见有三种: 露个头就算可见:元素只要和视口有交集就算(曝光埋点经常这么干)。 至少可见一半:比如图片懒加载、卡片动画,想更“稳”一点。 完全可见:通常用于“必须完整展示后才算到达”的场景。 后面所有方案,都能支持这三种,只是配置/判断方式不同。 推荐方案:IntersectionObserver(省心 + 省电)如果你能用 IntersectionObserver,就优先用它。 它不是让你在滚动时疯狂算,而是浏览器在合适的时机告诉你:现在它交不交叉、交叉比例是多少。 1) 最小可用示例:露头就算12345678910111213141516171819202122functio...
如何清理源码里面没有被应用的代码
项目迭代久了,最常见的“技术债”之一就是:代码里堆了一堆没人敢删、也没人再用的东西——旧接口、废弃组件、改过几轮后遗留的工具函数、还有 CSS 里躺平的选择器。构建阶段的 Tree Shaking 的确能帮你把一部分“没被引用的导出”从产物里剔掉,但它解决不了“源码越来越难读、越来越不敢改”的问题。想把尸体代码从仓库里清干净,通常要靠静态分析 + IDE 辅助 + 人工确认这套组合拳。 下面按两类说:JS/TS 和 CSS。 清理 JavaScript/TypeScript 代码1. 使用静态分析工具ts-unused-exports / ts-prune 这类工具会扫一遍 TypeScript 工程,列出“导出了但没人用”的东西。它的优势是快,缺点是一定会有误报/漏报(比如动态引用、约定式导出、代码生成),所以输出更像“待处理清单”,别指望一键删干净。 ts-unused-exports该工具会分析你的 TS 源码,并报告所有未被使用的导出。你可以根据报告结果,手动或借助脚本自动删除这些代码。使用示例: 1npx ts-unused...
如何避免使用 Context 时引起整棵挂载树重渲染?
Context 真的是 React 里“又香又容易翻车”的东西:不想层层传 props?用它。结果某个值一变,凡是 useContext 过的组件全都跟着 re-render,一不小心就把页面拖慢。 我这篇想解决的不是“能不能用 Context”,而是“用了以后怎么别把整棵树一起带飞”。下面按一个比较工程化的思路:先搞清楚它为什么会触发渲染,再给出几种最常用、最容易落地的缩小影响范围的方法。 理解 Context 更新导致的重新渲染你可以把 Context 理解成“全局订阅”:组件一旦 useContext(SomeContext),就相当于订阅了这个 Context 的 value。只要 Provider 的 value 变了,这些订阅者都会重新渲染。 关键点在于:React 比较的是 value 的引用是否变化。也就是说,哪怕里面的字段没变,只要你每次 render 都 new 一个对象/数组/函数,引用就变了,订阅者照样会刷新。 优化策略1. 使用 useMemo 缓存 Provider value这是最常见也最“性价比高”的一招:让 Provide...
组件封装应遵循哪些基本准则?
我见过不少组件一开始封得挺开心,后面就开始长出各种 enableXxx、disableYyy、showZzz 开关,最后变成“谁用谁害怕”。组件封装最难的不是写功能,而是把边界画清楚:哪些能力属于组件、哪些应该交给组合;哪些应该做成显式 API、哪些可以隐藏在内部。 下面这些是我自己在写组件(不管 React/Vue 还是别的)时经常会过一遍的 checklist,偏经验总结,尽量可落地。 一、设计目标与基本原则我通常会先问自己三个问题:这个组件解决什么问题?它的“最小好用”长什么样?未来别人会怎么扩展它? 单一职责(Single Responsibility):一个组件只解决一类问题;超出边界的能力通过组合扩展。 显式 API:输入输出清晰,避免“魔法”与隐式副作用;缺省值合理且可覆盖。 可组合性优先:通过组合(children、slots、render props)扩展能力,而非内置过多开关。 受控/非受控双模:同时支持受控(value/onChange)与非受控(defaultValue)用法。 可访问性(A11y)内建:ARIA 语义、...
如何做好代码重构
我对“重构”的定义很朴素:业务行为不变,但你下次改需求不会骂街。 很多人把重构做成了重写:开个大分支,改一堆东西,然后合并时痛苦到怀疑人生。更稳的做法是小步快跑:先把安全网(测试/回归点)搭起来,再一点点把“难维护的结构”拆开。 下面按我在项目里比较常用的套路,聊聊重构的流程、常见手法,以及几个真挺容易踩的坑。 代码重构的整体流程1. 分析和识别代码问题重构前别急着动手,先回答两个问题: 现在这段代码到底哪里痛(改一次要摸很多文件?经常引 bug?性能/可读性问题?) 这次重构的边界在哪(只动某个模块?只抽公共逻辑?还是补齐测试后再拆层?) 常见的“代码异味”(Code Smells)我一般会重点盯这几类: 重复代码:相同或相似的代码片段出现在多个地方。 过长方法:方法体太长,逻辑复杂,难以维护。 过度耦合:模块之间依赖过于紧密,不易独立修改。 命名不规范:变量或方法名称模糊,不易理解其含义。 另外还有个很实用的信号:“改一个小需求,要在脑子里模拟半天才敢下手”。这种地方通常就是重构价值最高的区域。 2. 编写和完善测试用例如果这段代码完全没有测试...
什么是 requestIdleCallback?
你有没有写过这种代码:页面一打开,你顺手就想做点“顺便的事”——埋点、预加载、计算一堆东西、顺手还想把用户最近浏览记录也整理一下。 然后你发现:用户的顺便 = 主线程的噩梦。 requestIdleCallback 的思路很朴素:正事(输入、滚动、动画、渲染)优先,剩下的等浏览器“喘口气”再做。像你在工位被人叫住:“哥你先把线上故障处理了,我这 PPT 不急,等你空了再说。” 先一句话:requestIdleCallback 是啥?requestIdleCallback(cb) 用来注册一个回调:当浏览器主线程出现空闲(idle)时,尽量调用它,让你在“不会影响用户交互”的时间片里做一些不紧急的工作。 几个关键词你得先记住: 它是“尽量”,不是“保证” 它面向的是主线程的空闲时间(不是 Web Worker 那种真并行) 它更适合“可切片、可中断”的任务 为什么会有“空闲”这种东西?浏览器主线程平时主要忙这些: 跑 JS 样式计算 / 布局 / 绘制 处理输入事件(点击、滚动、键盘) 合成与动画调度 如果你在关键路径里塞了一个大计算,用户...
浅析如何做一套前端监控
我见过最“有用”的监控不是把大盘做得多漂亮,而是:线上一报错,你能在 5 分钟内回答三件事——是谁遇到了、在什么页面/什么操作遇到了、怎么复现/怎么修。 这篇不讲大而全的平台选型,按“从 0 落地一套能用的前端监控”来写:错误怎么抓、性能怎么量、用户行为怎么采、数据怎么上报,以及最容易被忽略的隐私合规怎么守住底线。 前端监控的目标与意义做监控前先把目标说清楚,不然很容易变成“什么都采一点,最后没人看”。我通常会把目标分成四类: 稳定性(错误):JS 运行时错误、Promise 未捕获异常、资源加载失败……你需要能“分组 + 定位 + 追踪版本”。 性能体验:首屏与交互是否顺(FCP/LCP/CLS/INP、长任务、请求耗时),以及“哪个页面/哪个接口在拖后腿”。 用户路径:用户做了什么操作后触发问题(点击/跳转/停留),让排障不再靠猜。 安全与合规:采集范围可控、敏感信息不落盘;必要时做脱敏、采样和权限控制。 一句话:监控的价值不在“数据多”,而在“能不能让排障更快、让质量可衡量”。 监控指...
