JavaScript系列 -> 数组在内存中的存储方式(连续或不连续)

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

结论:

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

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

    • 快数组:
      是一种线性的存储方式,内部存储是连续的内存;
      可能需要开辟一大块供其使用,其中还可能有很多空洞,是比较费内存的;
      空间连续的,遍历速度很快;
    • 慢数组:
      慢数组是一种字典的内存形式,在内存中是零散分配的;
      遍历效率较差;
      【注】:不用开辟大块连续的存储空间,节省了内存,但是由于需要维护这样一个HashTable,其效率会比快数组低,V8中是以Dictionary的结构实现的慢数组;
    • 快慢数组的转换:(具体参考下面的链接)
      从源码中我们可以得出结论:
      • 如果快数组扩容后的容量是原来的 3 倍以上,意味着它比 HashTable 形式存储占用更大的内存,快数组会转换为慢数组;
      • 如果快数组新增的索引与原来最大索引的差值大于 1024,快数组会被转换会慢数组。(之前的例子:[(arr.length + 1026) - (arr.length - 1)] = 1027 > 1024,故 arr 由快数组转为慢数组。)
  2. 类型化数组(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;
    

参考链接:

posted @ 2022-06-13 18:58  77工作室  阅读(1130)  评论(0编辑  收藏  举报