- 3.1 Declaring Functions
- 3.2 Higher-Order Functions
- 3.3 Function Literals
- 3.4 Arrow Functions
- 3.5 Functional Array Processing
- 3.6 Closures
- 3.7 Hard Objects
- 3.8 Strict Mode
- 3.9 Testing Argument Types
- 3.10 Supplying More or Fewer Arguments
- 3.11 Default Arguments
- 3.12 Rest Parameters and the Spread Operator
- 3.13 Simulating Named Arguments with Destructuring
- 3.14 Hoisting
- 3.15 Throwing Exceptions
- 3.16 Catching Exceptions
- 3.17 The finally Clause
- Exercises
3.5 Functional Array Processing
Instead of iterating over an array with afor oforfor inloop, you can use theforEachmethod. Pass a function that processes the elements and index values:
arr.forEach((element, index) => { console.log(`${index}: ${element}`) })
The function is called for each array element, in increasing index order.
If you only care about the elements, you can pass a function with one parameter:
arr.forEach(element => { console.log(`${element}`) })
TheforEachmethod will call this function with both the element and the index, but in this example, the index is ignored.
TheforEachmethod doesn’t produce a result. Instead, the function that you pass to it must have some side effect—printing a value or making an assignment. It is even better if you can avoid side effects altogether and use methods such asmapandfilterthat transform arrays into their desired form.
In Section 3.2, “Higher-Order Functions” (page 53), you saw themapmethod that transforms an array, applying a function to each element. Here is a practical example. Suppose you want to build an HTML list of items in an array. You can first enclose each of the items in alielement:
const enclose = (tag, contents) => `<${tag}>${contents}${tag}>` const listItems = items.map(i => enclose('li', i))
Actually, it is safer to first escape&and<characters in the items. Let’s suppose we have anhtmlEscapefunction for this purpose. (You will find an implementation in the book’s companion code.) Then we can first transform the items to make them safe, and then enclose them:
const listItems = items .map(htmlEscape) .map(i => enclose('li', i))
Now the result is an array oflielements. Next, we concatenate all strings with theArray.joinmethod (see Chapter 7), and enclose the resulting string in aulelement:
const list = enclose('ul', items .map(htmlEscape) .map(i => enclose('li', i)) .join(''))
Another useful array method isfilter. It receives apredicatefunction—a function that returns a Boolean (or Boolish) value. The result is an array of all elements that fulfill the predicate. Continuing the preceding example, we don’t want to include empty strings in the list. We can remove them like this:
const list = enclose('ul', items.filter(i => i.trim() !== '').map(htmlEscape) .map(i => enclose('li', i)) .join(''))
This processing pipeline is a good example of a high-level “what, not how” style of programming. What do we want? Throw away empty strings, escape HTML, enclose items inlielements, and join them. How is this done? Ultimately, by a sequence of loops and branches, but that is an implementation detail.