我在想把一个元素插入到列表中的最好方法.

我想出了几种方法:

// setup
let messages = Array.from({ length: 1e5 }, (_, index) => ({ text: `text for message ${index + 1}` }));

第一次测试不会克隆原始列表.

const prependMessage1 = () => {
    messages = [{ text:'test message 1' }, ...messages];
};

prependMessage1();

// 531 ops/s ± 4.61%
// 99.5 % slower
const prependMessage2 = () => {
    messages = [{ text:'test message 2' }].concat(messages);
};

prependMessage2();

// 5.6K ops/s ± 1.49%
// 94.71 % slower
const prependMessage3 = () => {
    messages.unshift({ text: 'text message 3' })
};

prependMessage3();
// 105K ops/s ± 1.25%
// Fastest ✅
const prependMessage4 = () => {
    messages.reverse();
    messages.push({ text: 'text message 4' });
    messages.reverse();
};

prependMessage4();

// 4.9K ops/s ± 1.08%
// 95.3 % slower

我在我的应用中使用了一个状态管理器,它不允许直接改变状态.每个方法都应该返回一个新对象,而不是改变当前的消息列表.现在有趣的是,一旦我开始克隆,这些结果就会改变:

const prependMessage1 = () => {
    const copy = [...messages];
    messages = [{ text:'test message 1' }, ...copy];
};

prependMessage1();

// 472 ops/s ± 3.19%
// 84.57 % slower
const prependMessage2 = () => {
    const copy = [...messages];
    messages = [{ text:'test message 2' }].concat(copy);
};

prependMessage2();

// 3.1K ops/s ± 1.09%
// Fastest ✅
const prependMessage3 = () => {
    const copy = [...messages];
    copy.unshift({ text: 'text message 3' })
    messages = copy;
};

prependMessage3();

// 2.5K ops/s ± 2.28%
// 19.7 % slower
const prependMessage4 = () => {
    const copy = [...messages];
    copy.reverse();
    copy.push({ text: 'text message 4' });
    copy.reverse();
    messages = copy;
};

prependMessage4();

// 1.2K ops/s ± 1.11%
// 61.14 % slower

根据这些测试,是否可以安全地假设我应该使用concat?随着名单的增长,这里似乎有concat场胜利.或者我还遗漏了另一种最佳方式?

推荐答案

是的,看起来concat()英里是最快的.顺便说一句,你不需要复制concat()的消息数组和散布语法--它们会创建一个新的副本.

` Chrome/120
------------------------------------------------------------
concat              1.00x  |  x1000  164  170  174  174  182
Array::toSpliced    1.09x  |  x1000  179  185  187  192  203
for                 1.41x  |  x1000  231  231  236  239  247
Array::unshift      2.71x  |  x1000  444  450  466  472  484
spread              3.94x  |  x1000  646  653  655  658  660
Array.from         16.71x  |   x100  274  280  281  281  281
------------------------------------------------------------
https://github.com/silentmantra/benchmark `
` Firefox/120
-----------------------------------------------------------
Array::toSpliced   1.00x  |  x1000  220  230  244  246  271
concat             1.05x  |  x1000  232  234  234  237  238
Array::unshift     1.38x  |  x1000  303  308  310  312  320
for                1.70x  |  x1000  375  396  398  413  425
spread             3.30x  |  x1000  726  727  727  733  735
Array.from         4.73x  |   x100  104  107  107  108  110
-----------------------------------------------------------
https://github.com/silentmantra/benchmark `

const messages = Array.from({ length: 1e5 }, (_, index) => ({ text: `text for message ${index + 1}` }));

// @benchmark for
const arr = Array(messages.length + 1);
arr[0] = { text:'test message 1' };
for(let i = 0; i < messages.length; i++){
  arr[i + 1] = messages[i];
}
arr;

// @benchmark concat
[{ text:'test message 1' }].concat(messages);

// @benchmark Array::unshift
{
const arr = messages.slice();
arr.unshift({ text:'test message 1' });
arr;
}

// @benchmark spread
[{ text:'test message 1' }, ...messages];

// @benchmark Array.from
Array.from({length: messages.length + 1}, (_, idx) => idx ? messages[idx - 1] : { text:'test message 1' });

// @benchmark Array::toSpliced

messages.toSpliced(0, 0, { text:'test message 1' });

/*@end*/eval(atob('e2xldCBlPWRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3Rvcigic2NyaXB0Iik7aWYoIWUubWF0Y2hlcygiW2JlbmNobWFya10iKSl7bGV0IHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7dC5zcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9naC9zaWxlbnRtYW50cmEvYmVuY2htYXJrL2xvYWRlci5qcyIsdC5kZWZlcj0hMCxkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHQpfX0='));

Javascript相关问答推荐

我的glb文件没有加载到我的three.js文件中

Vue:ref不会创建react 性属性

我可以使用CSS有效地实现最大宽度=100%和最大高度=100%,而无需父母有明确的/固定的宽度和高度,替代方法吗?

康威的生活游戏规则在我的Javascript版本中不起作用.''我做错了什么?

函数返回与输入对象具有相同键的对象

当试图显示小部件时,使用者会出现JavaScript错误.

为什么按钮会随浮动属性一起移动?

使用JQuery单击元素从新弹出窗口获取值

未定义引用错误:未定义&Quot;而不是&Quot;ReferenceError:在初始化&Quot;之前无法访问';a';

提交链接到AJAX数据结果的表单

对路由DOM嵌套路由作出react

如何在Svelte中从一个codec函数中调用error()?

与svg相反;S getPointAtLength(D)-我想要getLengthAtPoint(x,y)

在不扭曲纹理的情况下在顶点着色器中旋转UV

我不知道如何纠正这一点.

未找到用于 Select 器的元素:in( puppeteer 师错误)

为什么我的SoupRequest";被重置为初始值,以及如何修复它?

将字体样式应用于material -UI条形图图例

react :图表负片区域不同 colored颜色

单击子按钮时将活动切换类添加到父分区