jQuery appending an array of elements

JavascriptJqueryArraysPerformanceAppend

Javascript Problem Overview


For the purpose of this question lets say we need to append() 1000 objects to the body element.

You could go about it like this:

for(x = 0; x < 1000; x++) {
	var element = $('<div>'+x+'</div>');
	$('body').append(element);
}

This works, however it seems inefficient to me as AFAIK this will cause 1000 document reflows. A better solution would be:

var elements = [];
for(x = 0; x < 1000; x++) {
	var element = $('<div>'+x+'</div>');
	elements.push(element);
}
$('body').append(elements);

However this is not an ideal world and this throws an error Could not convert JavaScript argument arg 0 [nsIDOMDocumentFragment.appendChild]. I understand that append() can't handle arrays.

How would I using jQuery (I know about the DocumentFragment node, but assume I need to use other jQuery functions on the element such as .css()) add a bunch of objects to the DOM at once to improve performance?

Javascript Solutions


Solution 1 - Javascript

You could use an empty jQuery object instead of an array:

var elements = $();
for(x = 0; x < 1000; x++) {
    elements = elements.add('<div>'+x+'</div>');
    // or 
    // var element = $('<div>'+x+'</div>');
    // elements = elements.add(element);
}
$('body').append(elements);

This might be useful if you want to do stuff with newly generated element inside the loop. But note that this will create a huge internal stack of elements (inside the jQuery object).


It seems though that your code works perfectly fine with jQuery 1.8.

Solution 2 - Javascript

You could just call

$('body').append(elements.join(''));

Or you can just create a large string in the first place.

var elements = '';
for(x = 0; x < 1000; x++) {
    elements = elements + '<div>'+x+'</div>';
}
$(document.body).append(elements);

Like you mentioned, probably the most "correct" way is the usage of a DocFrag. This could look like

var elements = document.createDocumentFragment(),
    newDiv;
for(x = 0; x < 1000; x++) {
    newDiv = document.createElement('div');
    newDiv.textContent = x;
    elements.append( newDiv );
}
$(document.body).append(elements);

.textContent is not supported by IE<9 and would need an conditional check to use .innerText or .text instead.

Solution 3 - Javascript

Upgrade to jQuery 1.8, this works as intended:

​$('body')​.append([    '<b>1</b>',    '<i>2</i>'   ])​;​

Solution 4 - Javascript

Since $.fn.append takes a variable number of elements we can use apply to pass the array as arguments to it:

el.append.apply(el, myArray);

This works if you have an array of jQuery objects. According to the spec though you can append an array of elements if you have the DOM elements. If you have an array of html strings you can just .join('') them and append them all at once.

Solution 5 - Javascript

A slight change to your second approach:

var elements = [],
newDiv;
for (x = 0; x < 1000; x++) {
    newDiv = $('<div/>').text(x);
    elements.push(newDiv);
}
$('body').append(elements);

$.append() certainly can append an array: http://api.jquery.com/append/

> .append(content) | content: One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the end of each element in the set of matched elements.

Solution 6 - Javascript

Sometimes, jQuery isn't the best solution. If you have a lot of elements to append to the DOM, documentFragment is a viable solution:

var fragment = document.createDocumentFragment();
for(var i = 0; i < 1000; i++) {
    fragment.appendChild(document.createElement('div'));
}
document.getElementsByTagName('body')[0].appendChild(fragment);

Solution 7 - Javascript

If you're going for raw performance then I would suggest pure JS, though some would argue that your development performance is more important than your site's/program performance. Check this link for benchmarks and a showcase of different DOM insertion techniques.

edit:

As a curiosity, documentFragment proves to be one of the slowest methods.

Solution 8 - Javascript

I would use native Javascript, normally much faster:

var el = document.getElementById('the_container_id');
var aux;
for(x = 0; x < 1000; x++) {
    aux = document.createElement('div');
    aux.innerHTML = x;
    el.appendChild(aux);
}

EDIT:

There you go a jsfiddle with different options implemented. The @jackwander's solution is, clearly, the most effective one.

Solution 9 - Javascript

I know, the question is old, but maybe it helps others.

Or simple use ECMA6 spread operator:

$('body').append(...elements);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGeorge ReithView Question on Stackoverflow
Solution 1 - JavascriptFelix KlingView Answer on Stackoverflow
Solution 2 - JavascriptjAndyView Answer on Stackoverflow
Solution 3 - JavascriptAlexey LebedevView Answer on Stackoverflow
Solution 4 - JavascriptJethro LarsonView Answer on Stackoverflow
Solution 5 - JavascriptDraculaterView Answer on Stackoverflow
Solution 6 - JavascriptjackwandersView Answer on Stackoverflow
Solution 7 - JavascriptMalSuView Answer on Stackoverflow
Solution 8 - JavascriptdavidsView Answer on Stackoverflow
Solution 9 - JavascriptshaedrichView Answer on Stackoverflow