Victor Ferreira
Victor Ferreira

Reputation: 6449

Which is better for performance, elements in DOM or in Javascript object?

In terms of performance, is it better to have 20 elements (with their children) in the DOM tree or everything stored in a Javascript object?

Case 1:

<html>
    <body>
        <div id='el1'>
            <span>...</span>
            ...
        </div>
        <div id='el2'>            
            <p>...</p>
            ...
        </div>
        <div id='el3'>            
            <img src="" alt="" />
            <br/>
        </div>
        <div id='el4'>
            <section></section>
            ...
        </div>
        ...
    </body>
</html>

Case 2:

var OBJ = {};
OBJ.el1 = $("<div id='el1'><span>...</span>...</div>");
OBJ.el2 = $("<div id='el1'><p>...</p>...</div>");
OBJ.el3 = $("<div id='el1'><img src="" alt="" /><br/>...</div>");
OBJ.el4 = $("<div id='el1'><section></section>...</div>");
....

My application should only show one of these elements at once. Will it perform better if I just leave them in DOM tree and change their style, or is it preferably to store them in a Javascript object and remove and append them when needed?

How could I test it?

@edit Extra info to consider:

1- all elements were written in the HTML document and then removed and stored in javascript objects when page was loaded.

2- Everytime the active element changes, I have change the DOM structure by removing the current active element and then appending the new one to it.

@EDIT 2: after some tests

The idea is: someone will write the HTML elements to DOM and then Javascript must show/hide only one of these elements at once. These elements have their own children. It may be a Full Page website or a Web App.

I created 2 test cases:

1- Elements will be removed and then re-appended several times by Javascript. So they will be stored in a Javascript object until it's summoned

2- Elements will be in DOM, I'll hide and show them (jQuery functions, but further tests will change the CSS directly) when needed.

<html>
<head>
    <script src='https://code.jquery.com/jquery-1.11.3.min.js'></script>
</head>
<body>
    <!-- I USED 15 ELEMENTS IN MY TEST, BUT THE CODE IS TOO LONG -->
    <script>
    var OBJ1 = {};
    var OBJ2 = new Array();
    var ACTIVE;
    var BODY = $(document.body);
    var T1, T2, DELTA;

    $(function(){
        T1 = new Date().getTime();
        /*
        //TEST 1: Javascript
        var _this,id;
        $('div').each(function(){
            _this = $(this);
            id = _this.attr('id');
            OBJ1[id] = _this;
            _this.remove();
        });

        var c;
        for (var i = 0; i < 10000; i++) {
            for(var k in OBJ1){
                c = OBJ1[k];
                if(ACTIVE) ACTIVE.remove();
                BODY.append(c);
                ACTIVE = c;
            }
        }*/

        //TEST 2: DOM
        var _this,id;
        $('div').each(function(){
            _this = $(this);
            id = _this.attr('id');
            OBJ2.push(id);
        });

        var c;
        for (var i = 0; i < 10000; i++) {
            for(var k=0,l=OBJ2.length;k<l;k++){
                c = $('#'+OBJ2[k]);
                if(ACTIVE) ACTIVE.hide();
                c.show();
                ACTIVE = c;
            }
        }

        T2 = new Date().getTime();
        DELTA = T2 - T1;
        console.log('It took '+DELTA+' milliseconds');
    });
    </script>        
</body>

I created 5 generic elements with some Lorem Ipsum and Lorem Pixel content and them copied/pasted them 3 times, making 15 1st-level elements.

For 1000 times I hide and revealed each one of the 15 elements. Ran the test 3 times each.

Case 1 (winner so far): 5.2s, 4.75s, 4.85s

Case 2: 21.5s, 21.5s, 20s

@edit 3: changing Case 2 method

Changing the second case from hide()/show() to css() makes a high increase in performance.

//TEST 2: DOM
        var _this,id;
        $('div').each(function(){
            _this = $(this);
            _this.css('display','none');
            id = _this.attr('id');
            OBJ2.push(id);
        });

        var c;
        for (var i = 0; i < 15000; i++) {
            for(var k=0,l=OBJ2.length;k<l;k++){
                c = $('#'+OBJ2[k]);
                if(ACTIVE) ACTIVE.css('display','none');
                c.css('display','block');
                ACTIVE = c;
            }
        }

Also increase the loop to 15k.

Case 1: Around 6.5s

Case 2: Around 2.5s

Upvotes: 4

Views: 1801

Answers (3)

DraskyVanderhoff
DraskyVanderhoff

Reputation: 115

I think the only dom elements you might want to apply lazy rendering are those that require media content like image, audio, video,etc. For those, search for a lazy loading js library that load the content of that element when you show that element. Also you could leave the element loaded into the page and hidden, but maybe if there are too many media elements it might be a bad use of memory.

Lastly, you could use React.js for this since it's main job is to dinamically render the diff between two dom trees, this might give some great improvements in scenarios where you are rendering the same dom element but with slightly different content. You probably knew about this, is there any reason why you decided to go full vainilla.js on this ?

Upvotes: 0

Rudolf
Rudolf

Reputation: 1886

Javascript is a very fast language, however the DOM is a huge bottleneck. So having the data in a Javascript object will be much faster, but you will have to render the active element to the DOM on your own (Instead of just making it visible).

I wouldn't worry about the DOM being slow for a few dozen elements, but if you have lots of elements or are trying to perform computations/filters on them, definitely go for Javascript.

Upvotes: 0

David Li
David Li

Reputation: 1290

Definitely leave it in the DOM tree. I would just use show/hide methods to show which one you want.

I would only use the JS method if there was a dynamic changing value that should be reflected in the element, but if they are all static, changing the DOM tree is much more performance heavy rather than just a CSS style change.

You can test this by writing both, then using a jsperf to compare.

Upvotes: 5

Related Questions