adam j. sontag

slightly more like a website than before

When To Use jQuery's .map Methods

Have you ever written a bit of jQuery code that looks like this?

1
2
3
4
5
var pee = [];
$(".poo").each(function() {
  pee.push(this.id);
});
pee.join();

Or even worse, this?

1
2
3
4
5
6
7
var pee = "", poo = $(".poo");
poo.each(function(i,elem) {
  pee += this.id;
  if (i < poo.length) {
    pee += ",";
  }
});

If you are are doing Array.push or string concatenation inside of a loop, then what you want to be doing is using jQuery’s map methods, which exist for the explicit purpose of creating a new array of values based on an existing set, like so:

1
2
3
var pee = $(".poo").map(function() {
 return this.id;
}).get().join();

There are a few caveats, however. Let’s start with that .get() at the end.

When you use jQuery.fn.map, the result is a jQuery object - an array of values with a set of functions made available by jQuery. Usually the array contains DOM nodes, but after using $.fn.map, it’s just an array of arbitrary values. Most people are familiar with using .get(index) to access the DOM node at a selected index, but when .get() is called with no arguments, it returns the entire underlying array. This means you can’t call jQuery methods on it anymore, but you can call Array.join, or any other Array method, which was probably the reason you wanted an array to begin with. So go out and .get() it!

jQuery.fn.map vs jQuery.map

Just like jQuery provides an iterator for jQuery objects (jQuery.fn.each) and a “generic” iterator for any array or object (jQuery.each), there are also two flavours of .map. jQuery.fn.map, illustrated above, works on actual jQuery objects, while [jQuery.map] (http://api.jquery.com/jQuery.map/)works on vanilla Arrays - and ONLY arrays. In all versions of jQuery prior to 1.7, you couldn’t jQuery.map on a plain Object. Additionally, jQuery.map returns an array, not a jQuery object, so there is no need to call .get() after using it.

Also, for some bizarre, cruel reason, the arguments to the function supplied jQuery.fn.map and jQuery.map are NOT consistent with each other. The function signature for effin’ map, the one on the jQuery prototype, is function(index,element), consistent with other iterating functions on the jQuery prototpye, whereas the generic jQuery.map’s signature is function(element,index), for parity with native Array.prototype.map implementations .

When might you use jQuery.map? Consider this stupid useful acronymify example:

1
2
3
4
5
6
7
function acronymify(str) {
    return jQuery.map(str.split(" "),function(s) {
        return s.charAt(0);
    }).join("");
}
acronymify("Cash Rules Everything Around Me");
// --> "CREAM"

So, to answer the oft-asked question, “How do I know whether to use .each() or .map()?” If you are iterating over a set for the purpose of creating a new array or string based on the values in that set, use .map(). If you are iterating just because you need to do something to each item in a set, or because you want to create an object, use .each().

PS. We talked about this at length in episode 13 of yayQuery!

Comments