Let's fix our reflow problem by creating a node that has not yet been added to the DOM. Then we will append our divs to this node. And finally, we will append this single node to the DOM which should trigger a single reflow.
var $c = $("<div />").addClass("container");
for (var i=0; i<10000; i++) {
$c.append($("<div />").addClass("test-div"));
}
$("BODY").append($c);
This is a little bit better but still not great. Our running time is now 432.524ms. This is still pretty bad, and there is a lot we can do to improve.
The problem here is that we're still creating too many jQuery objects. Even though we've solved the reflow problem, there is a lot of overhead to create a jQuery object. Of course, for a single object the convenience of jQuery far outweighs the minimal performance hit. But if we're dealing with 10,000 elements the inefficiency is more than noticeable.
Let's see what happens when we skip using jQuery altogether and write this in plain JavaScript.
var c = document.createDocumentFragment();
for (var i=0; i<10000; i++) {
var e = document.createElement("div");
e.className = "test-div";
c.appendChild(e);
}
document.body.appendChild(c);
Incredibly, this change reduced our total running time from 432.524ms to 16.237ms. And this makes sense because it actually takes jQuery some time to create the object. Let's see just how long it takes to create a single jQuery object vs. creating the element using vanilla JavaScript.
console.time("jquery div");
var jqDiv = $("<div />");
console.timeEnd("jquery div");
// jquery div: 0.272ms
console.time("js div");
var jsDiv = document.createElement("div");
console.timeEnd("js div");
// js div: 0.006ms
This is a significant difference - 0.006ms vs. 0.272ms. The point of this comparison isn't to say that jQuery is bad but rather that as a developer you should know when to use it and when not to. jQuery provides a lot of functionality that isn't necessary for our purpose so it doesn't make sense to create 10,000 jQuery objects at such a high cost.