-
Notifications
You must be signed in to change notification settings - Fork 0
JavaScript forEach Iterators
A dairy farmer has a barn with 24 milking stalls. Every morning and every evening he opens the gate from the pasture to the barn, and his well-trained cows walk into their stalls.
The farmer installs a sensor in each stall to sense if a cow is in the stall. He writes a JavaScript app to count the cows:
var myHerd = [true, true, true, false,
true, true, true, true ,
true, false, true, false,
true, false, false, true ,
true, true, true, true ,
false, false, true, true];
var numCows = 0;
var countCows = function(cow) {
if (cow === true) {
numCows++;
}
};
myHerd.forEach(countCows);
console.log('My herd has ' + numCows + ' cows.');
The program starts by creating an array with 24 stalls. If a cow is in a stall, the value is true. An empty stall has a value of false.
The program then creates a global variable numCows. This needs to be a global variable to be accessible by console.log. Watch out for the Chrome Dev Tools cache remembering variables. (How do you clear the cache?)
Next the program creates a function expression, naming the function variable countCows. The function is very simple. Then it checks if there's a cow in a stall, and if so, increments the number of cows.
Now the program puts it all together. The array myHerd is given the method forEach, which runs the function on each item in the array. The function it runs is countCows.
Lastly console.log prints out the number of cows.
My herd has 17 cows.
Easy, huh? The syntax for forEach is nice and clear. But this doesn't work:
console.log('My herd has ' + myHerd.forEach(countCows) + ' cows.');
This will print:
My herd has undefined cows.
This is because forEach always returns undefined.
var myHerd = [true, true, true, false,
true, true, true, true ,
true, false, true, false,
true, false, false, true ,
true, true, true, true ,
false, false, true, true];
var numCows = 0;
var countCows = function(myHerd) {
myHerd.forEach(function(cow) {
if (cow === true) numCows++;
});
return numCows;
};
var cows = countCows(myHerd);
console.log('My herd has ' + cows + ' cows.');
Note that the two nested functions. The second (nested) function is needed to specify the function that the forEach runs. The return value is outside the inner function.
A new variable cows is declared to run the function, then is used in the printout. This variable isn't necessary but somehow makes the code more reliable.
Note that this example has two functions in addition to the forEach method. The named function countCows take one parameter, the array. The forEach method is nested in the named function. Inside the forEach method is an anonymous function. The anonymous function is almost always used with forEach. The anonymous function takes three parameters: element value, element index, and the array being traversed. In this case we specify the element value (cow), leave the index empty (forEach will supply an iterator), and the array is specified via dot notation. However the following function doesn't work:
var countCows = function(myHerd) {
forEach(function(cow, i, myHerd) {
if (cow === true) numCows++;
});
return numCows;
};
forEach must append an array via dot notation.
This program inputs two arrays and outputs one object, with one array inserting the names and the second array inserting the values of the object.
var array1 = [ "cat", "dog", "fish" ],
array2 = [ "lion", "pointer", "trout" ],
myObject = {};
var animalMatch = function(array1, array2) {
array1.forEach(function(ele, index) {
myObject[ele] = array2[index];
});
return myObject;
};
animalMatch(array1, array2);
console.log(myObject);
The "trick" is that the iterator of the forEach() method can be used to iterate through a second array. I.e., as the forEach is iterating through the first array it's also iterating through the second array. Set up the forEach() method as if it were only iterating through the first array, with the ele variable accessing array1. Then add the second array to the function nested into the forEach method.
console.log(ele) returns cat, dog, fish, i.e., iterates through array1.
Adding properties to an object is easy. For strings you just write myObject["name"] = "value"
What doesn't work is myObject.array1[index] = array2[index];. This doesn't work because forEach has already been told to iterate through array1, in the previous line: array1.forEach(function(ele, index) {. This is telling the forEach() method to iterate through array1, with the variable ele standing in for each element of array1. The non-working code tries to tell the forEach() method to do what it's already been told.
myObject.ele = array2[index]; also doesn't work. It returns Object {ele: "trout"}. Dot notation treats the name as a string, not as a variable name, i.e., functionally the same as myObject["ele"] = array2[index]. The forEach() method iterates through the array, inserting the values from array2. But duplicate names aren't allowed, so only one property remains in the object, with the final value.
Two methods are related to forEach():
-
The every() method tests whether all elements in the array pass the test implemented by the provided function.
-
The some() method tests whether some element in the array passes the test implemented by the provided function.