JavaScript – Loops

To understand conditional statements, we imagined the JavaScript
interpreter following a branching path through your source code. The
looping statements are those that bend that path
back upon itself to repeat portions of your code. JavaScript has four
looping statements: while, do/while, for, and for/in. The subsections below explain each
in turn. One common use for loops is to iterate over the elements of
an array. Iterating Arrays discusses this kind of
loop in detail and covers special looping methods defined by the Array
class.

while

Just as the if statement is
JavaScript’s basic conditional, the while statement is JavaScript’s basic
loop. It has the following syntax:

while (expression)
      statement

To execute a while
statement, the interpreter first evaluates
expression. If the value of the
expression is falsy, then the interpreter skips over the
statement that serves as the loop body
and moves on to the next statement in the program. If, on the other
hand, the expression is truthy, the
interpreter executes the statement and
repeats, jumping back to the top of the loop and evaluating
expression again. Another way to say this
is that the interpreter executes
statement repeatedly
while the expression
is truthy. Note that you can create an infinite loop with the syntax
while(true).

Usually, you do not want JavaScript to perform exactly the
same operation over and over again. In almost every loop, one or
more variables change with each iteration of
the loop. Since the variables change, the actions performed by
executing statement may differ each time
through the loop. Furthermore, if the changing variable or variables
are involved in expression, the value of
the expression may be different each time through the loop. This is
important; otherwise, an expression that starts off truthy would
never change, and the loop would never end! Here is an example of a
while loop that prints the
numbers from 0 to 9:

var count = 0;
while (count < 10) {
    console.log(count);
    count++;
}

As you can see, the variable count starts off at 0 and is incremented
each time the body of the loop runs. Once the loop has executed 10
times, the expression becomes false (i.e., the variable count is no longer less than 10), the
while statement finishes, and the
interpreter can move on to the next statement in the program. Many
loops have a counter variable like count. The variable names i, j,
and k are commonly used as loop
counters, though you should use more descriptive names if it makes
your code easier to understand.

do/while

The do/while loop is like a
while loop, except that the loop
expression is tested at the bottom of the loop rather than at the
top. This means that the body of the loop is always executed at
least once. The syntax is:

do
      statement
  while (expression);

The do/while loop is less
commonly used than its while
cousin—in practice, it is somewhat uncommon to be certain that you
want a loop to execute at least once. Here’s an example of a
do/while loop:

function printArray(a) {
    var len = a.length, i = 0;
    if (len == 0)
        console.log("Empty Array");
    else {
        do {
            console.log(a[i]);
        } while (++i < len);
    }
}

There are a couple of syntactic differences between the
do/while loop and the ordinary
while loop. First, the do loop requires both the do keyword (to mark the beginning of the
loop) and the while keyword (to
mark the end and introduce the loop condition). Also, the do loop must always be terminated with a
semicolon. The while loop doesn’t
need a semicolon if the loop body is enclosed in curly
braces.

for

The for statement provides
a looping construct that is often more convenient than the while statement. The for statement simplifies loops that follow
a common pattern. Most loops have a counter variable of some kind.
This variable is initialized before the loop starts and is tested
before each iteration of the loop. Finally, the counter variable is
incremented or otherwise updated at the end of the loop body, just
before the variable is tested again. In this kind of loop, the
initialization, the test, and the update are the three crucial
manipulations of a loop variable. The for statement encodes each of these three
manipulations as an expression and makes those expressions an
explicit part of the loop
syntax:

for(initialize ; test ; increment)
      statement

initialize,
test, and
increment are three expressions
(separated by semicolons) that are responsible for initializing,
testing, and incrementing the loop variable. Putting them all in the
first line of the loop makes it easy to understand what a for loop is doing and prevents mistakes
such as forgetting to initialize or increment the loop
variable.

The simplest way to explain how a for loop works is to show the equivalent
while loop[5]:

initialize;
  while(test) {
      statement
      increment;
  }

In other words, the initialize
expression is evaluated once, before the loop begins. To be useful,
this expression must have side effects (usually an assignment).
JavaScript also allows initialize to be a
var variable declaration
statement so that you can declare and initialize a loop counter at
the same time. The test expression is
evaluated before each iteration and controls whether the body of the
loop is executed. If test evaluates to a
truthy value, the statement that is the
body of the loop is executed. Finally, the
increment expression is evaluated. Again,
this must be an expression with side effects in order to be useful.
Generally, either it is an assignment expression, or it uses the
++ or -- operators.

We can print the numbers from 0 to 9 with a for loop like the following. Contrast it
with the equivalent while loop
shown in the previous section:

for(var count = 0; count < 10; count++)
    console.log(count);

Loops can become a lot more complex than this simple example,
of course, and sometimes multiple variables change with each
iteration of the loop. This situation is the only place that the
comma operator is commonly used in JavaScript; it provides a way to
combine multiple initialization and increment expressions into a
single expression suitable for use in a for loop:

var i,j;
for(i = 0, j = 10 ; i < 10 ; i++, j--)
    sum += i * j;

In all our loop examples so far, the loop variable has been
numeric. This is quite common but is not necessary. The following
code uses a for loop to traverse
a linked list data structure and return the last object in the list
(i.e., the first object that does not have a next property):

function tail(o) {                          // Return the tail of linked list o
    for(; o.next; o = o.next) /* empty */ ; // Traverse while o.next is truthy
    return o;
}

Note that the code above has no
initialize expression. Any of the three
expressions may be omitted from a for loop, but the two semicolons are
required. If you omit the test
expression, the loop repeats forever, and for(;;) is another way of writing an
infinite loop, like while(true).

for/in

The for/in statement uses
the for keyword, but it is a
completely different kind of loop than the regular for loop. A for/in loop looks like this:

for (variable in object)
      statement

variable typically names a
variable, but it may be any expression that evaluates to an lvalue
(Lvalues) or a var statement that declares a single
variable—it must be something suitable as the left side of an
assignment expression. object is an
expression that evaluates to an object. As usual,
statement is the statement or statement
block that serves as the body of the loop.

It is easy to use a regular for loop to iterate through the elements
of an array:

for(var i = 0; i < a.length; i++)  // Assign array indexes to variable i
    console.log(a[i]);             // Print the value of each array element

The for/in loop makes it
easy to do the same for the properties of an object:

for(var p in o)        // Assign property names of o to variable p
    console.log(o[p]); // Print the value of each property

To execute a for/in
statement, the JavaScript interpreter first evaluates the
object expression. If it evaluates to
null or undefined, the interpreter skips the loop
and moves on to the next statement.[6] If the expression evaluates to a primitive value, that
value is converted to its equivalent wrapper object (Wrapper Objects). Otherwise, the expression is already an
object. The interpreter now executes the body of the loop once for
each enumerable property of the object. Before each iteration,
however, the interpreter evaluates the
variable expression and assigns the name
of the property (a string value) to it.

Note that the variable in the
for/in loop may be an arbitrary
expression, as long as it evaluates to something suitable for the
left side of an assignment. This expression is evaluated each time
through the loop, which means that it may evaluate differently each
time. For example, you can use code like the following to copy the
names of all object properties into an array:

var o = {x:1, y:2, z:3};
var a = [], i = 0;
for(a[i++] in o) /* empty */;

JavaScript arrays are simply a specialized kind of object and
array indexes are object properties that can be enumerated with a
for/in loop. For example,
following the code above with this line enumerates the array indexes
0, 1, and 2:

for(i in a) console.log(i);

The for/in loop does not
actually enumerate all properties of an object, only the
enumerable properties (see Property Attributes). The various built-in methods
defined by core JavaScript are not enumerable. All objects have a
toString() method, for example,
but the for/in loop does not enumerate this
toString property. In addition to
built-in methods, many other properties of the built-in objects are
nonenumerable. All properties and methods defined by your code are
enumerable, however. (But in ECMAScript 5, you can make them
nonenumerable using techniques explained in Property Attributes.) User-defined inherited properties
(see Inheritance) are also enumerated by the
for/in loop.

If the body of a for/in
loop deletes a property that has not yet been enumerated, that
property will not be enumerated. If the body of the loop defines new
properties on the object, those properties will generally not be
enumerated. (Some implementations may enumerate inherited properties
that are added after the loop begins, however.)

Property enumeration order

The ECMAScript specification does not specify the order in
which the for/in loop
enumerates the properties of an object. In practice, however,
JavaScript implementations from all major browser vendors
enumerate the properties of simple objects in the order in which
they were defined, with older properties enumerated first. If an
object was created as an object literal, its enumeration order is
the same order that the properties appear in the literal. There
are sites and libraries on the Web that rely on this enumeration
order, and browser vendors are unlikely to change it.

The paragraph above specifies an interoperable property
enumeration order for “simple” objects. Enumeration order
becomes implementation dependent (and noninteroperable) if:

  • The object inherits enumerable properties;

  • the object has properties that are integer array
    indexes;

  • you have used delete
    to delete existing properties of the object; or

  • you have used Object.defineProperty() (Property Attributes) or similar methods to alter
    property attributes of the object.

Typically (but not in all implementations), inherited
properties (see Inheritance) are enumerated
after all the noninherited “own” properties of an object, but are
also enumerated in the order in which they were defined. If an
object inherits properties from more than one “prototype” (see
Prototypes)—i.e., if it has more than one
object in its “prototype chain”—then the properties of each
prototype object in the chain are enumerated in creation order
before enumerating the properties of the next object. Some (but
not all) implementations enumerate array properties in numeric
order rather than creation order, but they revert to creation
order if the array is given other non-numeric properties as well
or if the array is sparse (i.e., if some array indexes are
missing).


[5] When we consider the continue statement in continue, we’ll see that this while loop is not an exact equivalent
of the for loop.

[6] ECMAScript 3 implementations may instead throw a TypeError
in this case.

Comments are closed.