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.
Several ways:
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
, wherever 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 i
and 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: initialization
, condition
, and final-expression
.
Initialization lessons
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.
Condition lessons
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.
Bonus!
Let’s create a function that does a for
loop for us. It eliminates the scoping issues of variables like i
and 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:
Boom! Why all the strange semicolons? Why the weird function notation? Check out my post on weird semicolons and on a simple way to modularize dependencies for some answers to these question. Also, check out John Papa’s AngularJS style guide. It applies specifically to AngularJS, but a lot of the principles translate well into vanilla JavaScript principles.