I am not a javascript expert but thought this was a slam dunk to code until I saw the results. I am looking for help to make this MUCH more efficient.

I have a simple for-loop going over a list of data rows. Typically there are 10 or so but sometimes there might be up to a couple of thousand. With 10 its no problem. With 1200 it takes 34 seconds!!

The code -

           for(let i = 0; i < selectedRows.length; i++) {
                selectedRows[i].checked = event.target.checked;

I am setting the "checked" variable in all rows to true or false. i.e. someone selected the "Check all boxes" checkbox.

As mentioned above, with 1200 rows it takes 34 seconds. When I add timers in like the following -

            for(let i = 0; i < selectedRows.length; i++) {
                console.time('handle checking of box - ' + i);
                selectedRows[i].checked = event.target.checked;
                console.timeEnd('handle checking of box - ' + i);

what is interesting is that the loop starts out fast. It does a row in about 1ms which is what I would expect.

enter image description here

But, as the loop progresses it gets much slower until at the end each row takes 20ms.

enter image description here

Can anyone help me understand why the loop gets slower and slower as well as perhaps a better way of doing this?

  • 3
    Might improve performance by caching const checked = event.target.checked and/or switching to selectedRows.forEach so you don't have to index in every time.
    – Adrian Larson
    Jun 18 at 17:20
  • 2
    I'm not a JS expert either, but the first thing that came to mind is that your browser may be doing 're-flows'/'re-paints' every time you change a checkbox. Perhaps LWC/Aura has a way to mitigate that, but failing that I believe the general approach is to make your modifications to a "document fragment" (i.e. a partial html document), then substitute the existing fragment (with no boxes checked) with the modified fragment (with all boxes checked).
    – Derek F
    Jun 18 at 17:58

Two changes should help you improve performance:

  1. Cache the results of event.target.checked in advance.
  2. Use a forEach loop so you don't have to index in every time.

As you already discovered, the end result should look like:

const checked = event.target.checked;
selectedRows.forEach(row => row.checked = checked);

Kudos to @AdrianLarson. (I would have marked his answer correct if it wasn't a comment!) I looked into forEach and it solved the problem. Not exactly sure technically why forEach is better than using a regular for-loop but its now lightning fast. Here is the code for anyone interested -

        const checked = event.target.checked
        selectedRows.forEach(element => element.checked = checked);

The loop now takes 10ms total which is orders of magnitude quicker.


Not the answer you're looking for? Browse other questions tagged or ask your own question.