共计 1324 个字符,预计需要花费 4 分钟才能阅读完成。
大家都晓得对象是 key-value 的模式,查问效率是 O(1),字典底层构造是哈希数组,那么在 v8 中怎么解决这个 key-value 模式的对象存储呢?
在 v8 中,对象的属性分为快属性和慢属性。
什么是快属性,什么是慢属性
var obj = {};
obj[1] = 'el1';
obj[3] = 'el3';
obj[2] = 'el2';
obj['p1'] = 'pp1';
obj['p3'] = 'pp3';
obj['p2'] = 'pp2';
for (var key in obj) {console.log(key);
}
下面的代码的后果能够看出,如果属性索引是数字,那么查找的时候会依照数字程序查找,如果属性索引是字符串,那么查找的时候会依照先到先出的程序查找,并且遍历的时候先遍历属性索引是数字的属性,后遍历属性索引是字符串的属性。
景象就是下面的景象,那么 v8 是怎么辨别的呢?
假如当初咱们有上面的 Foo
构造函数
关上 Chrome,在 Memory 拍一下以后页面的快照,能够看出 Foo 是分为 elements 和 properties 两个内容,其中 elements 是存储数字索引的属性,properties 是存储字符串索引的属性。
先来看看 elements
var h = new Foo(10, 0);
咱们先不设置字符串索引属性,能够看到,除了在 elements 中存放数据,还在第一层有同样的数据。实际上第一层的数据只是一个指向 elements 中对应数据的一个援用,如下图所示
比照外层和内层的 [1],他们实际上是同一个货色,在外层放一个援用是为了在查找的时候能缩小一步 elements 的查问。能够看到上面的 Distance 内层的是 3,外层的是 2。
在 elements 的存储中,默认是顺序存储,那么查问的效率就是 O(1)。
h[111] = 'ele111';
如果咱们执行以上的代码,会产生什么呢?
elements 中仿佛变成了不是依照顺序存储了,这个时候是一个稠密数组,如果依照顺序存储会导致大量的空间节约。这个例子看不出来多大的变动,再看上面的例子。
var i = new Foo(1000, 0);
能够看出曾经不是依照数字的程序进行排序了,实际上当 elements 中的数量大于等于 20 个的时候,存储的形式变成了 哈希表 ,变为哈希表绝对于稠密数组节俭了大量空间,同时实践上也能做到 O(1) 的查问效率。
再看看 properties
properties 跟 elements 相似,都是在空间和工夫中作出最好的查问计划。
var j = new Foo(0, 10);
当 properties 的数量不大于 10 的时候,全副 properties 间接放在第一层中,缩小一层的查问,晋升效率。
var k = new Foo(0, 13);
当 properties 的数量大于 10 并且不大于 30 的时候,前 10 个属性同样放在外层,剩下的属性放在 properties,应用链表的履行存储,在不多数据的状况下查问速度可观。外层通过援用的模式指向外部对应的属性。
var l = new Foo(0, 30);
当 properties 的数量大于 30 的时候,properties 变得毫无程序可言,实际上存储形式曾经变成了哈希表。这是因为数据量多的时候,链表的查问速度会越来越慢,所以变成了哈希表反对更快的查问