上半部分代码块:
javascript复制代码
ini
const arr1 = [];
for (let i = 0; i < 1000000; ++i) {
arr1[i] = 1;
}
下半部分代码块:
javascript复制代码
ini
const arr2 = [];
arr2[1000000 - 1] = 1;
for (let i = 0; i < 1000000; ++i) {
arr2[i] = 1;
}
总结:
- 上半部分代码效率更高,因为它利用了数组的快速模式。
- 下半部分代码 由于先设置了
arr2[1000000 - 1]
,导致数组失去了快速模式的优势,降低了效率。
测试代码:
javascript复制代码
ini
// 测试代码
console.time('a');
const arr1 = [];
for (let i = 0; i < 1000000; ++i) {
arr1[i] = 1;
}
console.timeEnd('a');
console.time('b');
const arr2 = [];
arr2[1000000 - 1] = 1;
for (let i = 0; i < 1000000; ++i) {
arr2[i] = 1;
}
console.timeEnd('b');
JS运行机制:
浏览器 | 内核 | JS解析引擎 |
---|---|---|
Chrome | 早期 WebKit,现目前 Blink | V8 |
Mozilla Firefox | Gecko | SpiderMonkey |
Edge | Chromium | Chakra / V8 |
Safari | Webkit | JavascriptCore |
补充说明:
- 比较主流的JS引擎是V8,这里假设是跑在Chrome或Node上,用的是V8引擎。
- V8引擎利用隐藏类(Hidden Class)的方式来存放JS对象,并且数组有快速模式(Fast Mode)和字典模式(Dictionary Mode)。
- 在快速模式下,数组的索引是连续的,并且类型是一致的,这样可以提高访问和赋值的效率。
- 一旦数组的索引不连续(如
arr2[1000000 - 1] = 1
),数组就会失去快速模式的优势,转而使用字典模式,效率降低。 - 因此,左边代码生成的数组保持在快速模式,而右边代码生成的数组由于索引不连续而失去了快速模式的优势,导致左边代码性能更好。
- 指导代码编写习惯:定义数组时,尽可能保持索引连续,避免使用非连续索引赋值。