Iterating: each and map
Most jQuery methods apply to all elements on their own. But sometimes each element needs its own treatment: read its data, count, compare. That is what each() is for.
The each method
<ul id="tasks">
<li>Buy bread</li>
<li class="done">Call Oleg</li>
<li>Write the report</li>
</ul>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
$('#tasks li').each(function (index, element) {
const $item = $(element);
const mark = $item.hasClass('done') ? '[x]' : '[ ]';
console.log(mark, $item.text());
});
</script>The function is called for every item. It receives the index and a plain DOM element, so the element is wrapped in $ to use jQuery methods. The output has three lines with marks.
this inside each
In a function declared with function, this points to the current element. Older code is written exactly like this:
<ul>
<li>Buy bread</li>
<li>Call Oleg</li>
</ul>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
$('li').each(function () {
console.log($(this).text().length);
});
</script>An arrow function has no this of its own, so with it use the second argument, element.
Stopping early
To stop the loop, the function returns false:
<ul>
<li>Buy bread</li>
<li class="done">Call Oleg</li>
<li class="done">Write the report</li>
</ul>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
$('li').each(function (index) {
if ($(this).hasClass('done')) {
console.log('First finished task is number', index + 1); // 2
return false;
}
});
</script>The loop stopped at the second item; the third was not checked.
The map method
map() builds new values from a set. The result is a jQuery object, and get() turns it into a plain array:
<ul>
<li>Buy bread</li>
<li>Call Oleg</li>
</ul>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
const titles = $('li').map(function () {
return $(this).text();
}).get();
console.log(titles.join(', ')); // Buy bread, Call Oleg
</script>The $.each and $.map functions
jQuery also has functions with the same names for plain arrays and objects. Their argument order differs:
| Call | Callback arguments |
|---|---|
$('li').each(fn) | index, element |
$('li').map(fn) | index, element |
$.each(array, fn) | index, value |
$.map(array, fn) | value, index |
More on $.each in the lesson on utility functions. For arrays, the built-in forEach() and map() are more convenient today.
The same in plain JavaScript
<ul>
<li>Buy bread</li>
<li>Call Oleg</li>
</ul>
<script>
const titles = Array.from(document.querySelectorAll('li'), (li) => li.textContent);
console.log(titles.join(', '));
</script>Common mistake
Forgetting get() after map(). Without it you get a jQuery object, not an array, and titles.join throws titles.join is not a function.