检查每个循环性能的宽度和内部设置宽度

时间:2018-07-31 09:20:59

标签: javascript performance performance-testing

我下面有两段代码

代码段1

const doubleWidth = (element) => {
  const width = element.offsetWidth;
  element.style.width = `${width * 2}px`;
};
button.addEventListener('click', (event) => {
  boxes.forEach(doubleWidth);
});

代码段2

button.addEventListener('click', (event) => {
  var widths = boxes.map(item => item.offsetWidth);
  boxes.forEach((element, index) => {
         element.style.width = `${widths[index] * 2}px`;
  });
});

与片段2(只有18.4ms)相比,片段1有48ms的时间。为什么会这样?

毕竟,我仍然分别进行两项计算和设置操作(哪些是强行回流)。

这是完整的代码-https://codepen.io/kushalmahajan/pen/mjXVqp?editors=0010

更新-所以,让我解释一下

在代码片段1中,我每次都会看到诸如计算,重置,计算,重置...之类的模式

在代码段2中。事实并非如此。

请根据渲染管道为您提供答案

2 个答案:

答案 0 :(得分:0)

摘录1中的

每次执行2条命令:

const width = element.offsetWidth;
element.style.width = `${width * 2}px`;

在摘录2中 每次只执行1条命令:

element.style.width = `${widths[index] * 2}px`;

因此,我认为将执行时间增加一倍以上是很自然的。取决于执行以下命令所需的时间:

const width = element.offsetWidth;

为了在2个代码段之间进行合理的比较,我建议从循环中删除以上命令,并检查在这种情况下执行代码段1需要多长时间。

我希望有帮助。

答案 1 :(得分:0)

我不确定原因,但是很明显,如果您先存储offsetWidth,则使用forEachmap的性能无关紧要:{{3 }}。

您可以看到我对三种组合进行了计时:

  1. forEach,并立即获取offsetWidth并设置width
  2. forEach,首先存储offsetWidth和相应的元素,然后在第二个forEach中设置宽度
  3. map,先存储offsetWidth,然后在width循环中的元素上设置forEach

选项 2。 3。在性能上基本相同。从这一点来看,我想说获得offsetWidth和设置width的组合是一个性能瓶颈。真的不能告诉你更多,对不起!


window.onload = () => {
    const boxes = Array.from(document.querySelectorAll('.box'));

    document.getElementById('double-sizes-forEach')
    .addEventListener('click', (event) => {
        console.time('Double Sizes ForEach');

        boxes.forEach((element, index) => {
        const width = element.offsetWidth;
        element.style.width = `${width * 2}px`;
        });

        console.timeEnd('Double Sizes ForEach');
    });

    document.getElementById('double-sizes-forEach-2')
    .addEventListener('click', (event) => {
        console.time('Double Sizes ForEach 2');

        let a = [];
        boxes.forEach((element, index) => {
        a.push([element, element.offsetWidth]);
        });
        a.forEach(([e, w]) => {
        e.style.width = `${w * 2}px`; 
        });

        console.timeEnd('Double Sizes ForEach 2');
    });

    document.getElementById('double-sizes-map')
    .addEventListener('click', (event) => {
        console.time('Double Sizes Map');

        var widths = boxes.map(item => item.offsetWidth);
        boxes.forEach((element, index) => {
            element.style.width = `${widths[index] * 2}px`;
        });

        console.timeEnd('Double Sizes Map');
    });
};

输出:

Double Sizes ForEach: 12.341064453125ms
Double Sizes ForEach 2: 0.539794921875ms
Double Sizes Map: 0.590087890625ms

注释:

第二篇文章认为,您应该始终将更改样式(例如,设置width)和进行测量(例如,获取offsetWidth)分开,以免发生布局问题。似乎也是代码中的问题。