jstips 第 00 号技巧:向 JavaScript 数组中插入元素的高效之道——push、unshift、splice 的语义与 jsperf 性能实测
教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载向已有数组中插入元素是日常开发中再常见不过的操作push追加到尾部、unshift插入头部、splice插入中间。本篇以 jstips 项目第 00 号技巧见 _posts/zh_CN/javascript/2015-12-29-insert-item-inside-an-array.md为骨架完整继承原文在移动端与桌面端十余个浏览器环境下的实测性能数据并结合 JavaScript 数组的底层语义length属性、原地修改 vs 返回新数组、稀疏数组逐层剖析每种写法的取舍帮助你在不同场景下写出更快、更符合语义的插入代码。读完本文你将掌握尾部、头部、中间三种插入位置的全部可行写法、各自的副作用差异以及如何用基准测试验证更快的说法。为什么插入元素值得单独研究向数组插入元素看似简单但已知的方法并不代表没有更高效的选择。同样一个追加操作至少存在三种写法var arr [1, 2, 3, 4, 5]; var arr2 []; arr.push(6); // 方式一API 方法 arr[arr.length] 6; // 方式二直接索引赋值 arr2 arr.concat([6]); // 方式三拼接出新数组三种写法都能把6放进数组末尾但它们在是否修改原数组、返回值和执行速度上存在明显差异。jstips 原作者 loverajoel 通过 jsperf 基准测试给出了一个反直觉的结论在这些测试环境中arr[arr.length] 6这种绕开 API、直接索引赋值的写法常常比push更快而concat几乎总是垫底。本文后面会逐项展开这些数据。向数组尾部插入元素三种写法与原理原文给出了尾部插入的三种候选写法。先看它们的语义差别写法是否修改原数组返回值说明arr.push(6)修改新长度数值Array.prototype.push官方 APIarr[arr.length] 6修改被赋的值6依赖length恒为最大索引 1的语义arr2 arr.concat([6])不修改新数组返回拼接后的新数组原数组保持不变为什么arr[arr.length] 6等价于pushJavaScript 数组的length属性总是等于当前最大索引 1对非稀疏数组而言。因此arr.length恰好指向数组末尾的下一个空位arr[arr.length] 6就是在该空位写入新值写入后引擎会自动把length扩展为length 1。这本质上是push的内部实现路径之一也因此两种写法在部分引擎如当时的 Android 4.2.2上性能几乎完全相同。注意arr.concat([6])与前两者不同——它不触碰原数组而是返回一个新数组。原文称两种方法都是修改原始数组指的是push与索引赋值concat应归类为生成新数组方案适合需要保留原数组的不可变风格场景。移动端实测数据jsperf: push-item-inside-an-array以下数据来自原文档是作者在 2015–2016 年各移动端浏览器上的实测单位 ops/sec即每秒操作次数越高越快环境arr.push(6)arr[arr.length] 6arr.concat([6])Androidv4.2.2与索引赋值相同 // 3,319,694 ops/sec3,319,694 ops/sec比前两者慢 50.61%Chrome Mobilev33.0.0慢 66.74%6,125,975 ops/sec慢 87.63%Safari Mobilev9慢 40.19%7,452,898 ops/sec慢 49.78%移动端平均慢 35.64%5,632,856 ops/sec慢 62.67%桌面端实测数据环境arr.push(6)arr[arr.length] 6arr.concat([6])Chromev48.0.2564慢 61.94%21,602,722 ops/sec慢 87.45%Firefoxv4456,032,805 ops/sec慢 0.52%几乎持平慢 87.36%IEv11慢 39.61%67,197,046 ops/sec慢 93.41%Operav35.0.2066.68慢 71.60%30,775,071 ops/sec慢 83.70%Safariv9.0.342,670,978 ops/sec慢 0.80%几乎持平慢 76.07%桌面端平均慢 34.66%42,345,449 ops/sec慢 85.79%从两组数据可以提炼出三个稳定结论concat在几乎全部被测环境中都是最慢的——因为它要分配一块全新的数组并复制所有元素开销天然更高push与索引赋值互有胜负但差距微小Chrome、IE、Opera、Safari 上索引赋值更快Firefox 上push略快差距仅 0.5% 量级汇总平均之后索引赋值以微弱优势胜出移动端平均 5,632,856 ops/sec桌面端平均 42,345,449 ops/sec。需要强调的是这些数字反映的是当时各引擎V8、SpiderMonkey、Chakra 等的实现水平不应视为今天的普适结论——现代引擎对push的优化程度已大不相同。它们的价值在于揭示性能取决于引擎实现细节这一事实以及提供一套可复用的基准测试方法论。向数组头部插入元素unshift 与 concat 的对决头部插入的候选写法如下var arr [1, 2, 3, 4, 5]; arr.unshift(0); // 修改原数组在头部插入 0 [0].concat(arr); // 返回新数组 [0, 1, 2, 3, 4, 5]原数组不变这里有一个容易被忽略的细节原文特别点出unshift修改的是原始数组concat返回的是新数组。两者语义不同不能只按性能数字做选择——如果你的后续代码依赖原数组被就地更新就必须用unshift如果希望保持原数组不变才考虑[0].concat(arr)。移动端实测数据jsperf: unshift-item-inside-an-array环境[0].concat(arr)arr.unshift(0)Androidv4.2.21,808,717 ops/sec慢 97.85%Chrome Mobilev33.0.01,269,498 ops/sec慢 99.86%Safari Mobilev9慢 33.67%3,250,184 ops/sec移动端平均4,972,622 ops/sec慢 64.70%桌面端实测数据环境[0].concat(arr)arr.unshift(0)Chromev48.0.25642,656,685 ops/sec慢 96.77%Firefoxv448,039,759 ops/sec慢 99.72%IEv113,604,226 ops/sec慢 98.31%Operav35.0.2066.684,102,128 ops/sec慢 97.44%Safariv9.0.3慢 15.17%12,356,477 ops/sec桌面端平均6,032,573 ops/sec慢 78.65%与尾部插入相反头部插入的测试结果高度偏向concat在 Chrome、Firefox、IE、Opera、Android 上concat领先unshift多达 96%99%。原因不难理解unshift需要在原地把已有元素全部向后移位本质是 O(n) 的搬移操作而concat可以一次性分配并拷贝出新数组在当时的引擎实现中反而更快。Safari 是唯一例外unshift更快再次说明性能结论必须绑定具体引擎。向数组中间插入元素splice 是最优解中间位置插入只有一种主流写法原文的评价是简单且最高效var items [one, two, three, four]; items.splice(items.length / 2, 0, hello); // 结果[one, two, hello, three, four]splice 参数逐项拆解Array.prototype.splice(start, deleteCount, ...items)的三个关键参数在这里分别是items.length / 2起始插入位置。当length 4时4 / 2 2即在索引 2 处three之前插入当length为奇数如 5时5 / 2 2.5splice 会将小数起始索引按引擎的ToInteger规则取整向下取整为 2插入点会略微偏向左侧0deleteCount 0表示不删除任何已有元素这是纯插入的语义hello要插入的新元素可传入多个值实现批量插入items.splice(2, 0, a, b)。items.length / 2这个写法巧妙地利用了中间位置 长度的一半这一几何直觉让代码无需硬编码索引即可在任意长度数组的中间落点是这段示例最值得借鉴的地方。为什么说 splice 是中间插入的最高效方式从数据结构层面看中间插入无法回避把插入点之后的元素整体后移这一 O(n) 操作任何纯 JS 方案如slice拼接items.slice(0, mid).concat(hello, items.slice(mid))都要付出相同的移位代价还要额外承担多次数组分配与拷贝。而splice由引擎以原生实现直接完成移位与扩容省去了中间临时数组因此是中间插入场景下最直接、最经济的方案。原文作者在多个浏览器与操作系统上复测结论保持一致。三种位置、六种写法语义与副作用速查表目标位置修改原数组返回新数组常用写法性能要点当时实测尾部push、arr[arr.length] 6concat([6])、ES6[...arr, 6]尾部追加用push或索引赋值需保留原数组用concat索引赋值与push相当concat明显更慢头部unshift[0].concat(arr)、ES6[0, ...arr]原地修改用unshift不可变风格用concat多数被测引擎中concat大幅领先unshiftSafari 除外中间splice无高效替代slice拼接更慢splice(mid, 0, item)唯一正解引擎原生实现移位选择原则可以浓缩为一句话先按语义需求是否允许修改原数组筛选写法再在同语义候选之间谈性能。项目上下文这条技巧在 jstips 中的位置本文对应的原始文档是 jstips 项目README.md描述其为 Useful JavaScript tips旨在用不到两分钟的时间分享关于性能、约定、技巧的短小精悍的 JS 知识的第 00 号技巧位列 README.md 技巧列表的起始位置与后续 73 条技巧共同构成一个循序渐进的 JavaScript 技巧库。同仓库中与数组相关的技巧可以与本篇互相印证、串联阅读_posts/en/javascript/2016-02-06-deduplicate-an-array.md讲解数组去重同样区分原始值与对象引用两种语义与本篇的原地修改 vs 新数组互为补充_posts/en/javascript/2017-03-12-3-array-hacks.md介绍 ES6 展开运算符spread operator在数组上的妙用其空位迭代、展开传参、Set 去重三个技巧与插入场景直接相关见下节_posts/en/javascript/2016-05-12-make-easy-loop-on-array.md给数组附加循环游标方法展示了在数组对象上扩展行为的另一种思路。各语言版本的同名文档_posts/es_ES/...、_posts/zh_TW/...内容与中文版一致也印证了这条技巧的社区共识度。如果你希望为项目贡献新的技巧条目可以参考仓库的 POST_TEMPLATE.md 了解文章格式约定。ES6 时代的补充展开运算符让插入更简洁本篇发布于 ES6 普及之前如今同样场景有了更声明式的写法。受 _posts/en/javascript/2017-03-12-3-array-hacks.md 中展开运算符思路的启发现代代码可以这样写const arr [1, 2, 3, 4, 5]; const atEnd [...arr, 6]; // 尾部插入返回新数组 const atHead [0, ...arr]; // 头部插入返回新数组 const atMiddle [...arr.slice(0, 2), hello, ...arr.slice(2)]; // 中间插入语义上展开运算符版本与concat同属返回新数组、不修改原数组的不可变风格且写法更直观性能上展开运算符本质上仍是分配新数组 拷贝元素与concat处于同一量级并不具备超越push/unshift/splice原地写法的优势因此实际选型建议是需要原地修改且追求速度 → 尾部用push/索引赋值、头部用unshift、中间用splice追求不可变风格与代码可读性 → 用展开运算符或concat。如何自行验证一份可复用的基准测试思路原文在结尾鼓励读者自行测试这正是 jsperf 类基准测试的正确姿态——性能结论必须绑定具体引擎与版本。如果你希望在现代环境复测本文结论可以这样做将待比较的写法分别放入独立的函数例如function pushEnd(a) { a.push(6); }与function indexEnd(a) { a[a.length] 6; }用console.time/performance.now()循环执行数十万次对比总耗时在 Chrome、Firefox、Safari 以及移动端真机上分别跑一遍观察结论是否一致注意控制变量确保两种写法操作的是同等规模的数组避免 JIT 优化或 GC 干扰单次测量。小结向数组插入元素这件事远不止会写这么简单尾部push与arr[arr.length] 6性能相当concat因额外分配新数组而明显偏慢头部多数被测引擎中[0].concat(arr)大幅快于unshift但两者语义新数组 vs 原地修改必须先行区分中间splice(items.length / 2, 0, item)是唯一且最高效的正解方法论任何性能结论都应像原文那样注明浏览器版本与测试环境并在自己的目标平台上复测后再做最终决策。掌握了这些写法的语义边界与性能特征你在日常编码中就能根据是否允许修改原数组、插入位置、追求可读性还是极限速度快速选定最合适的方案。赞分享教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载相关推荐jstips 第 00 期向数组中插入元素——尾部、头部、中间三种场景的最优写法与性能实测jstips 第 00 期向数组中插入元素——尾部、头部、中间三种场景的最优写法与性能实测 在 JavaScript 日常开发中向已有数组中插入元素是出现频教程Modern JavaScript Tutorial 数组实战五连操作掌握 push/pop、shift/unshift 与中间元素替换Modern JavaScript Tutorial 数组实战五连操作掌握 push/pop、shift/unshift 与中间元素替换 本篇技术指南以 Mo文档/教程前端JavaScript 数组基础实战用 push、shift、unshift 与中间元素替换完成五步增删改查JavaScript 数组基础实战用 push、shift、unshift 与中间元素替换完成五步增删改查 本文以现代 JavaScript 教程zh.ja文档教程前端上一篇CANN ops-math 算子 aclnnCdistBackward 深度解析两段式接口、反向梯度公式与 AscendC 确定性实现下一篇如何免费解锁WeMod专业版功能终极教程与完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

xberg Java 实战:用 force_ocr 强制 OCR 已含文本层的 PDF 全页面

xberg Java 实战:用 force_ocr 强制 OCR 已含文本层的 PDF 全页面

后端AI 应用NLP 【免费下载链接】xberg Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with …

2026/10/13 13:19:04 阅读更多 →
Chance.js 随机 MAC 地址生成详解:chance.mac() 用法、delimiter 配置与底层实现

Chance.js 随机 MAC 地址生成详解:chance.mac() 用法、delimiter 配置与底层实现

测试 【免费下载链接】chancejs Chance - Random generator helper for JavaScript 项目地址: https://gitcode.com/gh_mirrors/ch/chancejs 点击查看 免费下载 本篇技术指南以 Chance.js 官方文档中的 mac 说明 为骨架,完整讲解 chance.mac() 的调用方…

2026/10/13 17:52:07 阅读更多 →
Helm Charts 中部署 Logstash:基于 stable/logstash Chart 的管道配置与 Kubernetes 实战指南

Helm Charts 中部署 Logstash:基于 stable/logstash Chart 的管道配置与 Kubernetes 实战指南

【免费下载链接】charts ⚠️(OBSOLETE) Curated applications for Kubernetes 项目地址: https://gitcode.com/gh_mirrors/chart/charts 点击查看 免费下载 仓库归档提示:本仓库(Helm Charts 官方仓库)自 2020 年 11 月 13 日起…

2026/10/13 13:35:49 阅读更多 →

最新新闻

基于PSO算法的双微网优化调度MATLAB实现

基于PSO算法的双微网优化调度MATLAB实现

1. 多微网优化调度模型概述 微电网作为分布式能源系统的重要实现形式,其优化调度一直是能源领域的研究热点。当多个微电网通过联络线相互连接时,就形成了多微网系统(Multi-Microgrid System)。这种架构能够实现能源的互补共享&…

2026/10/14 11:36:46 阅读更多 →
Python循环结构详解:从基础到高级优化技巧

Python循环结构详解:从基础到高级优化技巧

1. 循环结构基础概念 循环是编程中最基础也最强大的控制结构之一。简单来说,循环就是让计算机重复执行某段代码,直到满足特定条件为止。想象你在教一个小朋友数数,从1数到100,你不会说"说1,说2,说3...…

2026/10/14 11:36:46 阅读更多 →
Grok Bot从0到1实战:环境搭建、群组接入与任务调试全指南

Grok Bot从0到1实战:环境搭建、群组接入与任务调试全指南

1. 从零理解 Grok Bot:它到底能帮你干什么很多人第一次听到 Grok Bot 这个词,脑子里冒出来的第一个问题就是:它跟普通的聊天机器人有什么区别?我直接说结论——Grok Bot 的核心价值不在于“聊天”,而在于“干活”。它是…

2026/10/14 11:36:46 阅读更多 →
KITTI Raw Data转TUM格式:位姿基准、坐标变换与SLAM评估避坑指南

KITTI Raw Data转TUM格式:位姿基准、坐标变换与SLAM评估避坑指南

简介:面向运行VINS-Fusion等SLAM算法时进行精度比对的开发者,这份资源集中整理了KITTI raw data中00-10序列的groundtruth位姿与时间戳,并给出了可直接使用的TUM格式位姿轨迹。包内还包含各序列对应的轨迹图、数据集sequence说明以及一个转换…

2026/10/14 11:36:46 阅读更多 →
Grok Bot 保姆教程:从环境搭建到拉群协作的完整指南

Grok Bot 保姆教程:从环境搭建到拉群协作的完整指南

1. 从零理解 Grok Bot:它到底能帮你干什么 很多人第一次听到 Grok Bot 这个词,脑子里冒出来的第一个问题就是:这玩意儿跟普通的聊天机器人有什么区别?我直接开个网页对话不就行了吗,为什么还要专门去"装"一个…

2026/10/14 11:36:46 阅读更多 →
Grok Bot 从零搭建实战:群聊自动回复与知识库接入指南

Grok Bot 从零搭建实战:群聊自动回复与知识库接入指南

1. 从零上手 Grok Bot:先搞清楚它到底能干什么很多人第一次听到 Grok Bot 这个词,脑子里浮现的可能是那种满屏代码、需要自己搭服务器、配环境变量的硬核玩意儿。其实不是。Grok Bot 本质上是一个可以接入群聊、自动响应消息、执行特定任务的机器人。你可…

2026/10/14 11:35:45 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →