When you need a loop
Implicit iteration covers most work: $("li").addClass("x") changes every item without a loop. You need an explicit loop when each element needs different treatment: numbering items, reading each one's value, or deciding something per element.
.each()
<ul>
<li>Apple</li>
<li>Banana</li>
<li>Cherry</li>
</ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("li").each(function (index, element) {
const $item = $(element);
$item.text((index + 1) + ". " + $item.text());
console.log(index, element.tagName, $item.text());
});
</script>0 LI 1. Apple
1 LI 2. Banana
2 LI 3. CherryThe callback receives two arguments:
index: the position, counting from 0.element: the plain DOM element, not a jQuery object. Wrap it with$(element)to use jQuery methods.
Inside a normal function, this is also the current element, so $(this) and $(element) are the same. You will see $(this) in most older code.
Arrow functions and this
Arrow functions do not have their own this. If you use one, this is not the element, so use the second argument instead:
<p>One</p><p>Two</p>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("p").each(function () {
console.log("function this:", $(this).text());
});
$("p").each((i, el) => {
console.log("arrow el:", $(el).text(), "| this is the element?", this === el);
});
</script>function this: One
function this: Two
arrow el: One | this is the element? false
arrow el: Two | this is the element? falseBoth styles are fine. Just do not mix an arrow function with $(this).
Stopping early
break cannot be used inside a callback function. Instead, return false to stop the loop:
<ul>
<li>3</li><li>8</li><li>15</li><li>4</li><li>23</li>
</ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("li").each(function (i) {
const n = Number($(this).text());
console.log("checking", n);
if (n > 10) {
console.log("first number over 10 is at index", i);
return false; // stop here
}
});
</script>checking 3
checking 8
checking 15
first number over 10 is at index 2The loop stopped at 15; 4 and 23 were never checked. Returning true (or nothing) moves on to the next element, like continue.
.map(): collecting values
To build a list of values from a selection, use .map(). Whatever the callback returns is collected. Then call .get() to turn the result into a plain JavaScript array:
<input type="checkbox" name="topic" value="html" checked>
<input type="checkbox" name="topic" value="css">
<input type="checkbox" name="topic" value="jquery" checked>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const chosen = $("input[name=topic]:checked")
.map((i, el) => el.value)
.get();
console.log(Array.isArray(chosen), chosen.length);
console.log(chosen.join(", "));
</script>true 2
html, jqueryThis is the standard way to read every ticked checkbox. Without .get() you would have a jQuery object wrapping strings, which is rarely what you want.
If the callback returns null or undefined, that element is skipped, so .map() can filter and transform in one pass.
$.each() for arrays and objects
.each() (with a dot) loops over a jQuery selection. The utility function $.each() loops over any array or object:
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$.each(["red", "green", "blue"], function (index, colour) {
console.log(index, colour);
});
$.each({ name: "Asha", city: "Pune" }, function (key, value) {
console.log(key, "=", value);
});
</script>0 red
1 green
2 blue
name = Asha
city = PuneNote the argument order: index first, value second, the opposite of the array method forEach((value, index) => ...). For plain arrays, modern JavaScript's forEach or for...of is just as good and more common now; $.each() remains handy for objects and in older code.
Building HTML in a loop
A practical example: turn an array of data into list items.
<ul id="cities"></ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const cities = [{ name: "Pune", pop: 7.4 }, { name: "Jaipur", pop: 4.1 }, { name: "Kochi", pop: 2.1 }];
const $list = $("#cities");
$.each(cities, function (i, city) {
$("<li>").text(city.name + " (" + city.pop + " million)").appendTo($list);
});
console.log($list.children().length, "cities listed");
</script>3 cities listed$("<li>").text(...) creates an element and sets its text safely; the next section covers creating elements in detail.
Common mistakes
- Using
.each()for a change every element shares.$("li").addClass("x")needs no loop. - Calling jQuery methods on
elementwithout wrapping it:element.text()fails; use$(element).text(). - Using
thisinside an arrow function, where it is not the element. - Forgetting
.get()after.map()and then calling array methods such as.join(). - Mixing up argument order between
$.each(index, value)andforEach(value, index).
Exercise
Given several <span class="price"> elements containing numbers, use .each() to add up the prices and log the total. Then use .map().get() to log the prices as an array.
Show one possible answer
<span class="price">120</span> <span class="price">80</span> <span class="price">45</span>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
let total = 0;
$(".price").each(function () {
total += Number($(this).text());
});
console.log(total);
console.log($(".price").map((i, el) => Number($(el).text())).get());
</script>245
[120, 80, 45]The total is 245 and the array is [120, 80, 45].
Key points
- .each(function (index, element) { ... }) runs once per element; this is also the element.
- Return false from an .each() callback to stop the loop early.
- .map() builds a new set from a selection; add .get() to turn it into a plain JavaScript array.
- $.each() loops over ordinary arrays and objects; for arrays, plain forEach and for...of work just as well.