• Home
  • Explore
  • Detail

数组的快速模式&字典模式

3 views

看下这个问题,哪段代码效率更高:

```js

const arr1 = []

for (let i = 0; i < 10000000; ++i) {

arr1[i] = 0

}

```

```js

const arr2 = []

arr2[10000000 - 1] = 1

for (let i = 0; i < 10000000; ++i) {

arr2[i] = 0

}

```

答案是:左边效率更高,利用了数组的`快速模式`

我们可以测试一下:

```js

console.time("a")

const arr1 = []

for (let i = 0; i < 10000000; ++i) {

arr1[i] = 0

}

console.timeEnd("a")

console.time("b")

const arr2 = []

arr2[10000000 - 1] = 1

for (let i = 0; i < 10000000; ++i) {

arr2[i] = 0

}

console.timeEnd("b")

```

得到打印结果:

```bash

a: 116.369ms

b: 1.008s

```

为什么?

1. V8 内部有多种方式存放 JS 数组

2. 数组从 0 到 length - 1 无空洞,会进入`快速模式`,存放为 array。

3. 数组中间有空洞,会进入`字典模式`,存放为`HashMap`。

> 这是 V8 一个优化策略,保证用最合适的数据结构处理当下场景,如果遇到数据量过大或者是松散结构,就改变为 HashMap,牺牲遍历性能,换取访问性能。

带来的启示:

1. 从 0 开始初始化数组,避免数组进入字典模式。

2. 让数组保持紧凑,比main数组进入字典模式。