我试图在给定索引的数组中插入一个元素。很自然,我发现自己倾向于JavaScript提供的原生方法。然而,当我尝试实现相同的结果,但这次使用自定义逻辑时,我发现了一些性能差异。所以,我的问题是,你认为这重要吗?更频繁地使用自定义逻辑有意义吗?此外,如果你知道在数组中插入元素的更快方法,请分享。
设置:
使用Array.prototype.slice、Array.prototype.push和Array.prototype.concat的初始代码:
// Params:
const arr = [1, 2, 3, 4];
const index = 3;
const newItem = 5;
// Steps:
// 1. Create new array from the original one at given index
let start = arr.slice(0, index);
// 2. Add new item to the copy
start.push(newItem);
// 3. Get the rest of the original array
let end = arr.slice(index);
// 4. Print the merged array
console.log(start.concat(end));
对循环使用的自定义方法:
// Params:
const arr = [1, 2, 3, 4];
const index = 3;
const newItem = 5;
// Steps:
// 1. Create new array from the original one at given index
let copy = [];
for (let i = 0; i < index; i++) {
copy[copy.length] = arr[i];
}
// 2. Add new item to the copy
copy[index] = newItem;
// 3. Get the rest of the original array
let rest = [];
for (let i = index; i < arr.length; i++) {
rest[rest.length] = arr[i];
}
// 4. Merge the two arrays
for (let i = 0; i < rest.length; i++) {
copy[copy.length] = rest[i];
}
// 5. Print the merged array
console.log(copy);
此外,这是一个链接到基准,我创建了:https://measurethat.net/Benchmarks/ShowResult/317820
总之,结果是:
- JavaScript方法:101170.7 Ops/sec
- 自定义方法:105695.0 Ops/sec
乍一看,差异可能没有那么大,但当我们考虑到每日负荷时,我相信在某些情况下可能会很显著。不管怎样,告诉我你觉得怎么样?这是一场公平的战斗,还是我应该以不同的方式处理这种情况?
您的基准测试存在以下几个问题:
-
它还测量设置代码和
console.log
的性能。尤其是在这样一个紧密的循环中登录可能会非常慢。您可以使用例如。https://jsbench.me/将设置代码放在基准代码之外。 -
数组太小,无法显示有意义的差异。
如果我调出设置代码,删除日志记录,将数组大小增加到1000,并在索引500处插入一个元素,那么您的自定义方法大约慢15%(Firefox 102,Intel i7 920上的Arch Linux x86_64(。
还有一个更好的内置方法:Array.splice
。它在适当的位置修改阵列,因此不需要复制第一部分(除非增长需要重新分配阵列(。但如果你需要副本(比如公平的基准(:
const copy = Array.from(arr);
copy.splice(index, 0, newItem);
这种方法是三种方法中速度最快的,更重要的是,也是可读性最强的。