JavaScript 数组的进化与性能分析
发布时间 - 2026-01-11 03:18:12 点击率:次正式开始前需要声明,本文并不是要讲解 JavaScript 数组基础知识,也不会涉及语法和使用案例。本文讲得更多的是内存、优化、语法差异、性能、近来的演进。

在使用 JavaScript 前,我对 C、C++、C# 这些已经颇为熟悉。与许多 C/C++ 开发者一样,JavaScript 给我的第一印象并不好。
Array 是主要原因之一。JavaScript 数组不是连续(contiguous)的,其实现类似哈希映射(hash-maps)或字典(dictionaries)。我觉得这有点像是一门 B 级语言,数组实现根本不恰当。自那以后,JavaScript 和我对它的理解都发生了变化,很多变化。
为什么说 JavaScript 数组不是真正的数组
在聊 JavaScript 之前,先讲讲 Array 是什么。
数组是一串连续的内存位置,用来保存某些值。注意重点,“连续”(continuous,或 contiguous),这很重要。
上图展示了数组在内存中存储方式。这个数组保存了 4 个元素,每个元素 4 字节。加起来总共占用了 16 字节的内存区。
假设我们声明了 tinyInt arr[4];,分配到的内存区的地址从 1201 开始。一旦需要读取 arr[2],只需要通过数学计算拿到 arr[2] 的地址即可。计算 1201 + (2 X 4),直接从 1209 开始读取即可。
JavaScript 中的数据是哈希映射,可以使用不同的数据结构来实现,如链表。所以,如果在 JavaScript 中声明一个数组 var arr = new Array(4),计算机将生成类似上图的结构。如果程序需要读取 arr[2],则需要从 1201 开始遍历寻址。
以上急速 JavaScript 数组与真实数组的不同之处。显而易见,数学计算比遍历链表快。就长数组而言,情况尤其如此。
JavaScript 数组的进化
不知你是否记得我们对朋友入手的 256MB 内存的电脑羡慕得要死的日子?而今天,8GB 内存遍地都是。
与此类似,JavaScript 这门语言也进化了不少。从 V8、SpiderMonkey 到 TC39 和与日俱增的 Web 用户,巨大的努力已经使 JavaScript 成为世界级必需品。一旦有了庞大的用户基础,性能提升自然是硬需求。
实际上,现代 JavaScript 引擎是会给数组分配连续内存的 —— 如果数组是同质的(所有元素类型相同)。优秀的程序员总会保证数组同质,以便 JIT(即时编译器)能够使用 c 编译器式的计算方法读取元素。
不过,一旦你想要在某个同质数组中插入一个其他类型的元素,JIT 将解构整个数组,并按照旧有的方式重新创建。
因此,如果你的代码写得不太糟,JavaScript Array 对象在幕后依然保持着真正的数组形式,这对现代 JS 开发者来说极为重要。
此外,数组跟随 ES2015/ES6 有了更多的演进。TC39 决定引入类型化数组(Typed Arrays),于是我们就有了 ArrayBuffer。
ArrayBuffer 提供一块连续内存供我们随意操作。然而,直接操作内存还是太复杂、偏底层。于是便有了处理 ArrayBuffer 的视图(View)。目前已有一些可用视图,未来还会有更多加入。
var buffer = new ArrayBuffer(8); var view = new Int32Array(buffer); view[0] = 100;
了解更多关于类型化数组(Typed Arrays)的知识,请访问 MDN 文档。
高性能、高效率的类型化数组在 WebGL 之后被引入。WebGL 工作者遇到了极大的性能问题,即如何高效处理二进制数据。另外,你也可以使用 SharedArrayBuffer 在多个 Web Worker 进程之间共享数据,以提升性能。
从简单的哈希映射到现在的 SharedArrayBuffer,这相当棒吧?
旧式数组 vs 类型化数组:性能
前面已经讨论了 JavaScript 数组的演进,现在来测试现代数组到底能给我们带来多大收益。下面是我在 Mac 上使用 Node.js 8.4.0 进行的一些微型测试结果。
旧式数组:插入
var LIMIT = 10000000;
var arr = new Array(LIMIT);
console.time("Array insertion time");
for (var i = 0; i < LIMIT; i++) {
arr[i] = i;
}
console.timeEnd("Array insertion time");
用时:55ms
Typed Array:插入
var LIMIT = 10000000;
var buffer = new ArrayBuffer(LIMIT * 4);
var arr = new Int32Array(buffer);
console.time("ArrayBuffer insertion time");
for (var i = 0; i < LIMIT; i++) {
arr[i] = i;
}
console.timeEnd("ArrayBuffer insertion time");
用时:52ms
擦,我看到了什么?旧式数组和 ArrayBuffer 的性能不相上下?不不不。请记住,前面提到过,现代编译器已经智能化,能够将元素类型相同的传统数组在内部转换成内存连续的数组。第一个例子正是如此。尽管使用了 new Array(LIMIT),数组实际依然以现代数组形式存在。
接着修改第一例子,将数组改成异构型(元素类型不完全一致)的,来看看是否存在性能差异。
旧式数组:插入(异构)
var LIMIT = 10000000;
var arr = new Array(LIMIT);
arr.push({a: 22});
console.time("Array insertion time");
for (var i = 0; i < LIMIT; i++) {
arr[i] = i;
}
console.timeEnd("Array insertion time");
用时:1207ms
改变发生在第 3 行,添加一条语句,将数组变为异构类型。其余代码保持不变。性能差异表现出来了,慢了 22 倍。
旧式数组:读取
var LIMIT = 10000000;
var arr = new Array(LIMIT);
arr.push({a: 22});
for (var i = 0; i < LIMIT; i++) {
arr[i] = i;
}
var p;
console.time("Array read time");
for (var i = 0; i < LIMIT; i++) {
//arr[i] = i;
p = arr[i];
}
console.timeEnd("Array read time");
用时:196ms
Typed Array:读取
var LIMIT = 10000000;
var buffer = new ArrayBuffer(LIMIT * 4);
var arr = new Int32Array(buffer);
console.time("ArrayBuffer insertion time");
for (var i = 0; i < LIMIT; i++) {
arr[i] = i;
}
console.time("ArrayBuffer read time");
for (var i = 0; i < LIMIT; i++) {
var p = arr[i];
}
console.timeEnd("ArrayBuffer read time");
用时:27ms
结论
类型化数组的引入是 JavaScript 发展历程中的一大步。Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,这些是类型化数组视图,使用原生字节序(与本机相同)。我们还可以使用 DataView 创建自定义视图窗口。希望未来会有更多帮助我们轻松操作 ArrayBuffer 的 DataView 库。
JavaScript 数组的演进非常 nice。现在它们速度快、效率高、健壮,在内存分配时也足够智能。
总结
以上所述是小编给大家介绍的JavaScript 数组的进化与性能分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
# js
# 数组进化与性能
# JS性能优化实现方法及优点进行
# js 函数性能比较方法
# javascript for循环性能测试示例
# Java几种常用JSON库性能比较详解
# Javascript三种字符串连接方式及性能比较
# 实现高性能javascript的注意事项
# 原生JS实现图片懒加载之页面性能优化
# JavaScript 性能提升之路(推荐)
# 测量JavaScript函数的性能各种方式对比
# 会有
# 遍历
# 可以使用
# 异构
# 小编
# 上图
# 的是
# 都是
# 链表
# 未来
# 我在
# 还可以
# 我觉得
# 第一个
# 多个
# 在此
# 不太
# 你也
# 和我
# 已有
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何用腾讯建站主机快速创建免费网站?
Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程
Laravel如何集成Inertia.js与Vue/React?(安装配置)
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
英语简历制作免费网站推荐,如何将简历翻译成英文?
Laravel怎么防止CSRF攻击_Laravel CSRF保护中间件原理与实践
Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转
Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】
瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口
如何在腾讯云免费申请建站?
Linux网络带宽限制_tc配置实践解析【教程】
零服务器AI建站解决方案:快速部署与云端平台低成本实践
南京网站制作费用,南京远驱官方网站?
如何选择可靠的免备案建站服务器?
Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧
Laravel如何使用Service Container和依赖注入?(代码示例)
Laravel如何配置Horizon来管理队列?(安装和使用)
在Oracle关闭情况下如何修改spfile的参数
Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复
用yum安装MySQLdb模块的步骤方法
Windows10电脑怎么设置虚拟光驱_Win10右键装载ISO镜像文件
如何用低价快速搭建高质量网站?
香港服务器网站卡顿?如何解决网络延迟与负载问题?
Python结构化数据采集_字段抽取解析【教程】
Laravel Eloquent:优雅地将关联模型字段扁平化到主模型中
中山网站制作网页,中山新生登记系统登记流程?
Laravel怎么实现模型属性的自动加密
东莞市网站制作公司有哪些,东莞找工作用什么网站好?
Zeus浏览器网页版官网入口 宙斯浏览器官网在线通道
高性能网站服务器配置指南:安全稳定与高效建站核心方案
JavaScript如何操作视频_媒体API怎么控制播放
IOS倒计时设置UIButton标题title的抖动问题
html5如何实现懒加载图片_ intersectionobserver api用法【教程】
如何续费美橙建站之星域名及服务?
焦点电影公司作品,电影焦点结局是什么?
网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)
Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】
EditPlus中的正则表达式 实战(2)
Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程
如何在香港服务器上快速搭建免备案网站?
如何快速生成高效建站系统源代码?
,交易猫的商品怎么发布到网站上去?
Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】
如何在万网利用已有域名快速建站?
Laravel如何与Docker(Sail)协同开发?(环境搭建教程)
php静态变量怎么调试_php静态变量作用域调试技巧【解答】
EditPlus中的正则表达式实战(6)
HTML透明颜色代码在Angular里怎么设置_Angular透明颜色使用指南【详解】

