JavaScript DOM modification I'm thinking about DOM modification performance.

In a perfect way, we alter each element but DOM modification is really heavy and alter many elements at same time froze the browser. I didn't make any performance tests but I want to know if the second way can be more powerful.

In my head, the first way will ask the browser to refresh the display for each div. So logically, with the second way, the browser will refresh only once per injection. Is that correct?

HTML:

&lt;body&gt;

&lt;header&gt;&lt;/header&gt;

&lt;div id="container"&gt;
    &lt;div id="test1" alt="test1alt"&gt;&lt;/div&gt;
    &lt;div id="test2" alt="test2alt"&gt;&lt;/div&gt;
    &lt;div id="test3" alt="test3alt"&gt;&lt;/div&gt;
    &lt;div id="test4" alt="test4alt"&gt;&lt;/div&gt;
    &lt;div id="test5" alt="test5alt"&gt;&lt;/div&gt;
    &lt;div id="test6" alt="test6alt"&gt;&lt;/div&gt;
    &lt;!--[...200 more div]--&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;script&gt;


JS first way: alter each element

$(document).ready(function() {
    setInterval(function() {
        var value;

        $('#container div').each(function() {
            if(randNum(0, 10) != 1) {
                return true;
            }

            value = randString();

            if($(this).attr('alt') != value) {
                $(this).attr('alt', value);
            }
        });
    }, 100);
});


JS second way: rewrite base HTML and inject when modified

var myDOM = {};

function domConstruct(obj) {
    $('&gt; div', obj).each(function() {
        myDOM[$(this).attr('id')] = $(this).attr('alt');
    });
}
function domAlter(id, value) {
    if(myDOM[id] == value) {
        return;
    }

    myDOM[id] = value;

    return true;
}
function domUpdate(obj) {
    var buf = '';

    $.each(myDOM, function(id, value) {
        buf += '&lt;div id="'+id+'" alt="'+value+'"&gt;&lt;/div&gt;';
    });

    obj.html(buf);
}

$(document).ready(function() {
    domConstruct($('#container'));

    setInterval(function() {
        var inject = false;

        $.each(myDOM, function(id) {
            if(randNum(0, 10) != 1) {
                return true;
            }

            if(domAlter(id, randString())) {
                inject = true;
            }
        });

        if(inject) {
            domUpdate($('#container'));
        }
    }, 100);
});


JS Utils funcs:

function randNum(a, b) {
    var argc = arguments.length;

    if(argc == 1) {
        return 1;   
    }

    if(argc == 0) {
        a = 0;
        b = 2147483647;
    }

    return Math.floor(Math.random() * (b - a + 1))+a;
}
function randString() {
    return Math.random().toString(36).replace(/[^a-z]+/g, '');
}
&lt;/script&gt;
If you have performance issues, then I believe you should first try and profile your script, to identify which function(s) run slowly. There are profilers embedded in most scripting consoles.

Regarding your question: since your code should not trigger any repaint, I believe that method 1 would be fine. Unfortunately, I have not been able to reproduce the issue on my machine, so cannot confirm this answer.

To improve performance, I suppose you could try the following:


Rather than using setInterval, consider chaining setTimeout calls, so that the browser remains responsive.
Try and remove your library, to use native Javascript. It looks like you do not need anything more than getElementById, getElementsByTagName, getAttribute and setAttribute - so should be able to safely eliminate any library overhead.
Possibly cache the retrieval of all the div, as you only need to perform it once.


So basically, try and run the following (untested) on window.onload:

function update() {
    var delay = 100;
    var container = document.getElementById("container");
    var divs = container.getElementsByTagName("div");

    function updateDivs() {
        for (var ii = 0; ii &lt; divs.length; ii++) {
            var div = divs[ii];
            if (randNum(0, 10) == 1) {
                var value = randString();
                if (div.getAttribute("alt") != value) {
                    div.setAttribute("alt", value);
                }
            }
        }
        setTimeout(arguments.callee, delay);
    }

    updateDivs();
}