JavaScript 之 数组在内存中的存储方式(连续或不连续)

2023-03-07,,

最近在纠结一个问题,就是数组这个引用类型在JavaScript 中是不是和其他语言一样开辟了一个连续的内存来存储,但是在JS 中每个元素又可以是不同的类型,这就导致了没办法用一个相同大小的存储,所以数组究竟是如何在JS 存储的呢? 难道它是一个“假数组”?

结论:

参考了一些网上的文章,直接上总结吧。

    JS中有快数组和慢数组之分:

    快数组:

    是一种线性的存储方式,内部存储是连续的内存;

    可能需要开辟一大块供其使用,其中还可能有很多空洞,是比较费内存的;

    空间连续的,遍历速度很快;
    慢数组:

    慢数组是一种字典的内存形式,在内存中是零散分配的;

    遍历效率较差;

    【注】:不用开辟大块连续的存储空间,节省了内存,但是由于需要维护这样一个HashTable,其效率会比快数组低,V8中是以Dictionary的结构实现的慢数组;
    快慢数组的转换:(具体参考下面的链接)

    从源码中我们可以得出结论:

    如果快数组扩容后的容量是原来的 3 倍以上,意味着它比 HashTable 形式存储占用更大的内存,快数组会转换为慢数组;
    如果快数组新增的索引与原来最大索引的差值大于 1024,快数组会被转换会慢数组。(之前的例子:[(arr.length + 1026) - (arr.length - 1)] = 1027 > 1024,故 arr 由快数组转为慢数组。)

    类型化数组(Typed Arrays)

    JavaScript 类型化数组是一种类似数组的对象,并提供了一种用于访问原始二进制数据的机制。

    由缓冲和视图两部分: 缓冲是由ArrayBuffer实现,视图时由DataView来实现:

    ArrayBuffer 是一种数据类型,用来表示一个通用的、固定长度的二进制数据缓冲区;(不能直接操作ArrayBuffer内容)
    DataView是创建的一个类型化数组的视图或一个用来描述缓冲数据格式,可以使用它们读写缓冲区中的内容;

    [总]:一块大的连续的内存区域,可以用它来做一些高效的存取操作等。

    var buffer = new ArrayBuffer(4);
    var arr = new Int32Array(buffer);
    for(var i=0; i<LIMIT; i++) arr[i]=i;

参考链接:

JS V8 | 深入理解 JS 数组 —— JS Array在内存上分配的空间是连续的吗
深入理解数组
MDN - 类型化数组

JavaScript 之 数组在内存中的存储方式(连续或不连续)的相关教程结束。

《JavaScript 之 数组在内存中的存储方式(连续或不连续).doc》

下载本文的Word格式文档,以方便收藏与打印。