We use the
for loop generally to cycle through, say, an array of items. We can do something with each item. For example:
The code above obviously just increases
i, starting at 0 and ending at the length of
arr, which gives us the ability to access each of the items of
arr by its index.
How do you declare the loop?
There’s frequently discussion on how to best write a
for loop. There are some performance issues depending on how you write it (see this StackOverflow question), and I think a lot of it comes down to two things at the end: readability and personal style.
There are many other ways to write the loops, but those are some of the more common ones.
Let’s go over all of them, briefly
#1 — The problem with this one is that it might take some browsers longer because we’re “resetting” some variables each time (i.e., each iteration, the loop checks the section where we define the limit, which is oftentimes the length of an array). In fact, we can prove this:
The engine appears to check each statement for every iteration of the loop. We can cache the variables, so in comes:
#2 — This one caches the length, which could give you a little micro-optimized performance boost in some browsers. The first
i definition doesn’t get “re-evaluated” at the end of each iteration. We can prove this too:
As you can see above,
i is only defined once. If it wasn’t, it would increase by itself each iteration, and we wouldn’t see every number of
arr in the output. So it seems we’ve got to a nice, optimized way of writing the loop. But in comes the “personal style” element:
#3 — I like the last one, because it defines everything at the top of the function, much like how I described as a best practice in my post about hoisting. You can see everything easier, and predict what is going to be used, and where. However, this is not the best style to use, if you need to re-define the length, or limit, every iteration (for instance, if you’re removing or adding items to an array). I think it also is very minimalistic and clean.
Why does #3 not throw an error?
The third one is strange, because we start it off with a
; all by its lonesome. Well, I think this can be explained if we accept that the second part of the loop, the
i < // whatever part, looks to define itself by
i might be. The first part, the part where we normally declare and define
i, it just that: a part where we can initialize variables. In fact, we could initialize any variables we wanted. We could even initialize the limit, or length variable, and the array itself! Check it out:
Pretty cool, right? The initialization section of the loop provides us a space to intialize whatever we want; the syntactical benefit is that when a user looks at it, they know that
len are directly tied to that loop. The downside I think, though, is that a beginner might be fooled into thinking that
i only exists in the scope of the
for loop, when in fact, even though
i was initialized as part of the
for loop, it still exists to whatever function scope that it’s inside. We can prove this:
Each of these sections (the first part where we initialize
i, the second part, and the third part) all have names, by the way. They are called:
So what have we learned?
Well, we learned its easier when you call things by their names:
We can use this to declare anything we want, but we don’t have to use it to declare anything
Additionally, although it may be a personal style issue, I think it’s best to declare everything at the top of the function where the
for loop resides, unless you need to redefine something in the
condition section, such as the length of an array.
When it comes to arrays, we’re probably better off caching the length of the array either in the
initialization expression or at the top of the function in which the
for loop resides. This can give some performance benefits. However, we want to keep in mind that in a function where we add or remove things from an array, we might need to redefine the
condition expression of the
for loop every iteration.
Let’s create a function that does a
for loop for us. It eliminates the scoping issues of variables like
len, and it feels a whole lot cleaner. In fact, this function is a simplified version of something that the Underscore.js and jQuery libraries do (jQuery has $.each). You can even see a very complicated polyfill for Array.prototype.forEach on MDN’s page. Here’s out simplified function:
If you want to play around with that function, or just see if it works, open up your Developer Tools (cmd+opt+j on Mac in Chrome), copy and paste, hit enter, and voila.
We could even put it in a module: