4

The .map() function in jQuery returns a jQuery object:

var $collection = $(selector).map(extractSomeValue)

Most often, what is desired is a plain array of the mapped values:

var extractedArray = $collection.get()

In fact, ALL the use cases and examples I have found always pair .map() with .get(), including jQuery's own documentation.

What is the use case for working with the $collection as is? Why doesn't .map() simply return the array if that's what everyone uses it for?

EDIT: To be clear, I am referring only to jQuery.fn.map, not jQuery.map (aka $.map), since the latter is well-defined to operate only on non-jQuery objects and sensibly return a plain array.

0

5 Answers 5

4

Imagine you already have a jQuery object that contains a elements with ids as href. Now you want all target elements. This is where .map()can get handy:

var $list = $('a[href^=\\#]');
...
//somewhere else
var $targetElements = $list.map(function() {
       return $(this.href)[0];
});
$targetElements.addClass('newClass');

Or you want to create new elements based on the old ones:

var $links = $('a');
...
var $list = $links.map(function() {
       return $('<li>URL: ' + this.href + '</li>')[0];
});
$list.appendTo($myUl); 

They may be not the most useful examples, I know, but they illustrate my point. You have list of elements and want another list of elements that somehow relate to the original elements. Or you create new elements based on the old ones. Using .map() you get a ready to use jQuery object.

Sign up to request clarification or add additional context in comments.

8 Comments

Hmmm, I don't really see the benefit of using .map() in the top example. $('#mylist > li a').addClass('newClass') should suffice, right?
@ZachL As I wrote: "Imagine you already have a list" and "They may be not the most useful examples" ;)
Well if you already have a list... $list.find("a").addClass('newClass') So map in the example still doesn't seem useful :p
@nzifnab .find() is not the same. Anyway I replaced the example with another one :)
Well it would have been .children('a') then - You knew what I meant :p Your new example and the 2nd example illustrate possible use cases better :)
|
2

The first thing to note, jQuery.fn.map is not the same as jQuery.map, which returns a plain array even if you apply it to a jQuery object.

In jQuery itself they sometimes chain jQuery.fn.map and jQuery.fn.filter. So map over a jQuery collection returns another jQuery collection, and they can call jQuery.filter on it without having to extend the result of map.

I thought it's just a side-effect of the implementation, but no, they do it on purpose, jQuery.fn.map internally calls jQuery.map and pushes the result onto the stack of matched elements.

Off of the top of my head, I can't see a really good use case for this feature. But you can, for example, return 0 or many nodes at once in your map function, and all these node will be put in a nice linear collection:

$elements.map(function() {
    return [document.createElement('div'),
            document.createElement('span')];
});

8 Comments

just curious, but is there any benefit to using the vanilla JS there rather than jQuery? (return [$('<div>'),$('<span>')];)
@ZachL It simply doesn't work the same way with jQuery elements. Instead of a collection of DOM nodes you get a collection of jQuery collections.
Hmmm. Well toying around in the console just now... $('<div/><span/>') seems to have the same return value as [document.createElement('div'), document.createElement('span')]. Maybe that's the equivalent syntax?
@ZachL Maybe they look similar in the console, but they're certainly different values: jsfiddle.net/5dy9n
@ZachL Yes, it's a replacement. Both versions look quite readable. But the map operation, in mathematical sense, is supposed to return the same number of elements as you pass to it. So I wouldn't use this feature in practice, because it's too easy to misunderstand what's really going on.
|
0

Map is useful when you must retrieve some property of a set of selected elements as an [].

For example, lets say I wanted to get the hrefs of the following a elements:

<a href="something1">Something</a>
<a href="something2">Something</a>
<a href="something3">Something</a>
<a href="something4">Something</a>

I would need to use map in this situation:

var arr = $("a").map(function(i,e){
    return e.href;
});

2 Comments

You are confusing $.map and $.fn.map. In this example the returned value is a jQuery object
@charlietfl, not exactly. But, the text and the example don't make sense together
0

I may be confused (as evidenced by multiple edits), but my current understanding is that .map() returns a jQuery Object, which wraps a simple array, and provides other "helper" jQuery methods. It sounds like these helper functions are only really useful if the wrapped array is an array of DOM nodes. $.fn.get() will essentially unrwap the array for you. Therefore, I would think that you would NOT use get(), if your map function retuned actual DOM nodes rather other value types.

An (untested and probably a bit incorrect) example:

var $example = $('#foo').map(function() {
    if ($(this).innerHTML == "bar") {
        return this;
    }
});

From: http://ajpiano.com/when-to-use-jquerys-map-methods/

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!

6 Comments

.map() is not the same as jQuery.map()
ah, true story. Oops. Well then. I'll just leave this here for a while (as it might be useful for others), and then perhaps delete it in a bit. Honestly, I don't really use (or fully understand) map() in either form, and I was just dumping the results of my investigation.
@ZachL, bad idea, please delete it before you forget
How's about this: I deleted the parts of the answer that were $.map() specific. Does any of the above appear incorrect/misleading now?
The original question is, when DON'T you want .get? The use cases for when you DO are plentiful.
|
0

The fact that .map() returns a jQuery object rather than a plain array may be useful when you want to keep using jQuery methods over the new collection. Here is an example (try it in your browser console) :

var $collection = $('#qinfo p:even').map(function () {
    return $(this).text();
});

var ucfirst = $collection.map(function () {
    return this.replace(/^./, function (fst) {
        return fst.toUpperCase();
    });
}).get();

var prefixed = $collection.map(function () {
    return 'prefix-' + this;
}).get();

console.log($collection.get());
console.log(ucfirst);
console.log(prefixed);

However, as mentionned in the comments, I assume that it's mainly a matter of code presentation. That said, .map() allows you to take advantage of function chaining. For that matter, we could go even further by wrapping .map() into a plugin. This way make things more readable and easily reusable :

$.fn.ucfirst = function () {
    return this.map(function () {
        return this.replace(/^./, function (fst) {
            return fst.toUpperCase();
        });
    });
};
$collection.ucfirst().each(function () {
    console.log(this.toString());
});

A thing to note though, .ucfirst() is intended to work with collections of strings, which is out of the scope of the original purpose of jQuery.

5 Comments

This doesn't even try to answer the question!
It does address the question, but the example isn't very convincing. If I wanted to keep calling map I could as easily keep the plain array and use the general form (jQuery.map). I'm more interested in cases where it's more desirable to have a standard jQuery object, a collection of DOM entities, since I couldn't find nor think of any when I asked. zeroflagL provided a couple plausible cases; have you also encountered a practical use of your own?
@SeanGugler I was asking myself the same question for years actually, so, I have to admit I'm not able to be more convincing ^^'
@SeanGugler My last bullet would be to argue that it's mainly a matter of code presentation since using the jQuery object allows to put the subject to the beginning of your sentence. Then, it might be interesting to build some plugins to deal specifically with plain arrays as lodash does with its wrapper object : lodash.com/docs#_.
@SeanGugler I've added a paragraph according to my last comment. Not sure I'm still on-topic though. Anyway, I'm not expecting to be rewarded, I'm just trying to feed the discussion. At least, I hope I'm not likely to be downvoted :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.