forEach() vs for-of vs for-in loops

Here’s a brief summary of the differences between forEach(), for-in, and for-of loops to keep handy as reference.

forEach()

The forEach() prototype* method, introduced in ES5, executes a provided callback function (a function passed to another function as an argument) once for each value in Array, Map (made up of key-value pairs), Set, NodeList (an array-like object often returned by Document.querySelectorAll()), or HTMLCollection (an array-like object often returned by Document.getElementsByClassName()) objects, in ascending order.

myArray.forEach(function (value) {
// Do stuff
});

It takes a function callback as a parameter, with the current value being processed in the array as its argument. (There are also three optional arguments: the current index value, the array forEach() is being applied to, and a value to use as this [the reference Object].)

It’s somewhat more succinct than the classic for loop (which has been around for much longer). However, you can’t use the statements break to exit the loop, continue to skip an iteration, or return to return a value (and exit the loop). It returns undefined.

To use forEach() to loop over a NodeList or HTMLCollection object, note that you’ll need to first convert it to an Array object using Array.from().

*A prototype is something all JavaScript objects inherit properties (variables in an object) and methods (functions in an object) from. For instance, Array objects inherit from Array.prototype.

Read More
Array.prototype.forEach()
Set.prototype.forEach()
Map.prototype.forEach()
NodeList.prototype.forEach()

for-in

A for-in statement creates a loop that iterates over all non-Symbol, enumerable properties of an object, sometimes in an arbitrary order.

for (property in object) {
// Do stuff
}

What Are Enumerable Properties?
Objects are collections of properties, and each property has its own set of internal properties that are not user accessible but are used by the JavaScript engine. They are denoted with double square brackets: [[Property]].

Every object has an [[Enumerable]] property attribute that holds a boolean value of either true or false, which you can determine with the propertyIsEnumerable() method. If the value is true, the object is enumerable and therefore (assuming it’s not a Symbol) will be iterated over in a for-in loop.

In addition to enumerable properties with an [[Enumerable]] value of false, shadowed properties, meaning those overridden by same-name properties of descendant objects (properties closer to the object in the prototype chain take precedence over prototypes’ properties) will not be iterated over.

Use Cases Include…

  • String object properties. This is what it was designed for.
  • Array objects, but this is probably not a good idea: For one, it can sometimes loop in an arbitrary order. Two, the value assigned to an index will be a string; if you wanted to do arithmetic, you’d be doing string arithmetic (e.g., 5 + “5” = “55”).
  • String* objects. Each character in a string has an index, which is an enumerable property in the form of an integer.

*JavaScript automatically converts between String objects and string primitives; thus, you can call any of the helper methods of the String object on a string primitive.

Read More
for…in
Object.prototype.propertyIsEnumerable()

for-of

Introduced in ES6, a for-of statement creates a loop that iterates over iterable objects (see below for clarification) in iterable order. A common use is looping through values in an array, but it also works on most array-like objects.

for (item of iterable) {
// Do stuff
}

It has considerable benefits over for-in and forEach():

  • Unlike forEach(), you can use break, continue, and return
  • Two key advantages over for-in: one, it visits indices of an array in numeric (ascending) order, and two, indices of arrays are not converted to strings, so you can perform arithmetic

If you want to loop over an object’s properties, either use for-in (this is its purpose), or you can alternatively use the method Object.keys().

What’s an Iterable Object?

Not sure what an “iterable object” is? Well, ES6 added two protocols: the iterable and iterator protocols, which are key to understanding this.

Iterable Protocol
The iterable protocol allows JavaScript objects to define or customize their iteration behavior.

To be considered iterable, an object must implement the @@iterator method: either it or one of the objects up its prototype chain must contain a property with an @@iterator key, which is available via the constant Symbol.iterator.

At the beginning of the execution of a for-of loop, an object’s @@iterator method is called with zero arguments, returning an iterator object that is used to obtain the values to be iterated over.

Iterator Protocol
The iterator protocol defines a standard way to produce a sequence of values (either finite or infinite).

An iterator is an object that conforms to the iterator protocol. This is achieved by providing a next() method, which has zero arguments and returns an object with two properties:

  1. value: the data representing the next value in the sequence of values within the object
  2. done: a boolean representing whether the iterator has finished going through the sequence of values

Iterable Objects

  • Built-in iterables: String, Array, TypedArray, Map and Set objects (these are built-in because each of their prototype objects implements an @@iterator method)
  • NodeList objects
  • Generator objects (all iterators created by generators are also iterables, as generators assign the Symbol.iterator property by default)
  • Array-like arguments
  • User-defined iterables (these can be created by defining a method with a key of Symbol.iterator to conform to the iterable protocol and, to comply to the iterator protocol as well, having it return an object with a method called next() with two properties, value and done)

Read More
for…of
Symbol.iterator
Iteration protocols

aspiring web developer | nataliecardot.com