How to create an empty, non-null jQuery object ready for appending?

Your problem here is that there aren’t “null” jQuery objects that can’t be appended to and “empty” ones that can be. You’ve already identified several ways to create an empty one, and while there may be more, it doesn’t matter – what you’re trying to do simply won’t do what you expect it to, no matter how you start off, because…

append() modifies the DOM, not the jQuery object. And an empty jQuery object has no DOM! Tomalak had the right idea, though you may not have understood it.

I’m going to make three observations about jQuery that you’re probably already aware of, but which are useful in understanding the remainder of this answer and therefore may benefit future readers:

  1. A jQuery object is fundamentally a set of DOM elements.
  2. Some jQuery methods operate on the set, and some operate on the nodes in the set.
  3. Some jQuery methods operate only on (or retrieve information only from) the first node added to the set.

With these three observations in mind, let’s consider your example:

// 1. create an empty set somehow (doesn't matter how)
var $new = $();

// 2. iterate over something
$.each( ..., function( ... )
{
  // 3. construct a DOM fragment from HTML, and append it
  $new.append("<sometag>"); 
});

// 4. try to display HTML corresponding to the jQuery object
alert($new.html());  

In this example, step #3 will fail to do anything useful because the purpose of append() is to take whatever DOM elements it is given and append them as children to each DOM element in the set. Since $new is an empty set, there are no elements to append to, and… nothing happens. Step #1 is working just fine – but by creating a set without any DOM elements in it, you’ve set yourself up to fail when you try to use methods that exist to modify the DOM! Reference Observation #2… to modify the set, you need to call a method that actually operates on the set.

Ok, so let’s say we use the set modification method add() instead:

  $new = $new.add("<sometag>");

Now we’re good, right? Each pass through the loop will create a new jQuery object consisting of the previous set + a newly-created element. Well…

…this will just cause step #4 to do something odd. See, html() is one of those methods I mentioned in Observation #3 – it operates only on the first element in the set. So instead of a sequence ("<sometag><sometag><sometag>...") you’re only gonna get a HTML representation of the element created on the first pass through the loop ("<sometag>"). Except… You’re not even going to get that, because html() creates a representation of the element’s children – so what you’re really going to end up with is ""

This was all just a big disappointment: you started off working with the set (Step #1), then tried to operate on the DOM (Step #3), and finished up by trying to pull data from one DOM element (that didn’t exist) (and wouldn’t have had any data if it did) (Step #4).

The solution you finally came up with isn’t terrible – you’re essentially opting to add one root element to the set starting out, and operate entirely on this DOM fragment until you’re done adding new elements and are ready to operate on them. You’ve omitted it from your revised example, but html() would work too, since it would simply dump the contents of your root element.

But just to be complete, I’ll give you a final example that works on the set, starting with an empty jQuery object:

var $new = $();
$.each( [1, 2, 3, 4], function(i, v)
{
  $new = $new.add("<div>");
});

alert($new.length == 4); // true

// alerts: <div></div><div></div><div></div><div></div>
alert($("<div>").append($new).html()); 

Leave a Comment