有人能描述一下Javascript中的两种数组存储类型吗?

13

我正在阅读有关V8的文章,该文章来自HTML5Rocks。虽然这篇文章很旧,但我几乎一无所知,这让我感到困扰。我正在逐步学习,但是否有人能帮我理解数组部分?

文章中提到:

数组

为了处理大型和稀疏数组,内部有两种类型的数组存储:

  • 快速元素: 用于紧凑关键字集的线性存储

  • 字典元素: 用于其他情况下的哈希表存储

最好不要导致数组存储从一种类型翻转到另一种类型。

问题:

快速元素的线性存储数组是什么样子的?

字典元素的哈希表数组是什么样子的?

为了预防,如何"从一种类型翻转到另一种类型"?


我认为线性存储数组就是普通的单元素数组,而哈希存储则是对象数组。 - Akshay
1
这篇文章并没有讨论"元素",而是"字典元素"。你对引文的表达不够准确。 - trincot
@trincot 对不起,复制时出现了错误。 - Armeen Moon
1
好的,但是现在你的第一个选项有一个不必要的尾随单词“Dictionary”。 - trincot
2个回答

10

我会稍微采用另一种方式。

2) Dictionary Elements哈希表数组会是什么样子?

JavaScript对象是从字符串到值的映射。例如:

var obj = {
  "name": "Sherlock Holmes",
  "address": "221B Baker Street"
}

V8使用哈希表来表示对象,除非使用了优化的表示方法处理特殊情况。这很像字典使用(单词, 意义)对的方式。

现在,哈希表访问速度很慢,因为最初哈希表中所有键和值都是undefined。插入新键值对时,计算哈希值并将其插入到插入索引处。如果该索引处已经有一个键,则尝试在下一个位置插入,以此类推。

1)Fast Elements线性存储数组会是什么样子?

在V8中,element是一个其键为非负整数(0,1,2等)的属性,即一个简单的线性数组,可以通过数字索引访问其属性。

快速元素存储在一个连续的数组中,例如:

var arr = [1, 2, 3];

它们是一种特殊情况,经过优化以实现更快的访问,因为索引已知且不需要计算。

3)为了预防措施,我怎样才能从一个类型翻转到另一个类型?

对于快速元素,如果您分配的索引远远超出元素数组的末尾,V8可能会将元素降级为字典模式。

参考:http://jayconrod.com/posts/52/a-tour-of-v8-object-representation


1
更新了答案。 - Slartibartfast
不要删除数组元素。这会使数组转换为更慢的内部表示形式。当键集变得稀疏时,V8最终会将元素切换到字典模式,这会更慢。https://jsperf.com/packed-vs-holey-arrays - Ashok kumar
@User528491,他们是一个经过优化以提高速度的特殊情况 - 但仍然是一个哈希表,对吗? - Max Koretskyi

4

先生,我可能会错,但根据您的问题,我观察到的情况如下:

当我们初始化一个数组时,它内部会将键值设为0、1、2...等等。虽然我将带有值的元素推入数组中,但数组并不予考虑。

ex :

var arr = new Array()

arr[0] = 1
arr[1] = 2
arr[2] = "myname";
arr['myname'] = nick;

但是当我执行 arr.length 时,返回的是 3,这意味着它不考虑除数字以外的键。但是如果我写 arr[3] = {myname:'nick'},那么它会将其视为元素。

内部实现上,我认为它通过查找 '{}' 来区分线性数组。


那么,线性数组是a[0] a[1] ... a[20],而哈希表则是a['myname'] = 'nick'? - Armeen Moon
如果它是一个对象而不是数组元素,那么a['myname'] = nick将被视为无效。 - Akshay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接