Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript jQuery Basics Working with jQuery Collections Looping through a jQuery collection

Jack Camp
Jack Camp
6,121 Points

Struggling to understand .each function structure

I'm struggling to understand what this entire extract is exactly doing:

$("a").each(function(index, element){ console.log(index, $(element).attr("href")); });

Could someone possibly tell me what each part is doing? Thank you :D

2 Answers

Okay, let's examine this JQuery code. First thing that you need to know is that when you call $('a') it is like you called document.querySelectorAll('a'); which returns a collection of "a" tags on the page. So if you have 4 a tags on page as a result of $('a') you will get [a, a, a, a]

Next lets examine each function called on the JQuery object holding that collection of 4 a elements. basically in the back of the each method is this basic for loop:

1 for (var index = 0; index < collection.length; index++) {
2    var element = collection[index]; // Returns a tag;
3    callback(index, element); // execute passed function.
4 }

So when you call JQuery method "each" it expects to receive a function to call on each iteration (line 3 in example) and when called that function will receive index of current iteration and actual element from the collection.

At this moment we are currently at:

$("a").each(function callMeOnEachIteration(index, element){}); 

function callMeOnEachIteration(index, element){} will be executed on each iteration and as parameters will be passed index and element from for loop as showed above.

Lets expand function callMeOnEachIteration and make it to output each index to the console first. So now we have following function.

function callMeOnEachIteration(index, element){
    console.log(index);
}

Lets return back to the how each function in JQuery works and see result of calling this function for each a tag in collection.

$("a").each(callMeOnEachIteration); 
// Output: 0
// Output: 1
// Output: 2
// Output: 3

We receive 4 lines of output for each iteration since we started from index 0 and went to the last index in collection which is 3.

for (var index = 0; index < collection.length; index++) 

Now lets continue expanding our callMeOnEachIteration function to output element to the console next to the index.

function callMeOnEachIteration(index, element){
    console.log(index, element);
}

// Lets call again JQuery each method now with updated callback function.

$('a').each(callMeOnEachIteration);
// Output: 0 a
// Output: 1 a
// Output: 2 a
// Output: 3 a

Before we continue to the part of $(element).attr("href") I hope that you understand so far what is going on. If so, lets move on, if not please leave aditional comment to the answer.

Okay now to better understand why in the example we use $(element).attr("href") you need to know that JQuery each method returns actual HTML element as second parameter instead of JQuery object so if you call element.attr("href") you will get an error since element does not have attr method because it is plain javascript object and to access href attribute on plain javascript object you can use element.getAttribute("href"). So to use JQuery method "attr" you need to convert plain javascript element to JQuery object by calling $(element) and now attr function call will return href attribute.

So here is how you could do same thing without converting returned javascript element to JQuery object.

$('a').each(function callMeOnEachIteration(index, element) {
    console.log(index, element.getAttribute("href"));
});

this is the same as:

$("a").each(function callMeOnEachIteration(index, element) { 
    console.log(index, $(element).attr("href")); 
});

Or if you even want to go further you can write down same function using latest ES6 syntax which you will learn eventually.

$('a').each((i, e) => console.log(i, e.href)); // Hope that this will motivate you to get better understanding of Javascript and become great developer 

Keep learning and understand fundamentals, and always wonder what is behind JQuery function, you will learn a lot! Good luck!

Jack Camp
Jack Camp
6,121 Points

Thank you very much! This cleared all my confusion.

My main confusion was on the '$(element)' part of the code as I didn't understand why it needed the jQuery '$' before it but now I get it all. ^^

Andreas Nyström
Andreas Nyström
8,887 Points
// $("a") - grabs all the a-tags
// .each loops through as many a-tags there is
// function (an anonymous function)
// index - what index(number) the anchortag currently being looped over has.
// element, the a-tag itself
// console.log - a command in javascript that writes to the console.
// $(element) - grabs the a-tag again as the "element" is the a-tag itself.
// .attr("href") - gets the href attribute of the a-tags.

$("a").each( function(index, element) { 
  console.log(index, $(element).attr("href")); 
});

If it's still not clear i recommend you looking at some for-loops for understanding the loop itself. If it's hard grabbing something else let me know and I'll try to explain more in detail.

Andreas Nyström
Andreas Nyström
8,887 Points

I realize now I didn't quite explain the .each function.

What it actually does is that the function you pass in after .each is made on every a-tag that it loops over. For example if you have an unordered list like this:

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

And then use this code snippet to loop through the elements and then write whats inside them. The same way you can change the color of the items or do whatever you want with them.

$('li').each( function(index, element) {
  console.log( $(element).text() );
}