← Back to JavaScript series
⚙️
Functional · ES6
Intermediate · Prerequisite: 10_Arrow_Functions

11. Array Higher-Order Functions

`forEach` is for side effects (logging, DOM updates) and returns nothing. `map` returns a new array.

mapfilterreducehigher-order
Duration
~1.5 hours
Level
📊 Intermediate
Prerequisite
🎯 Lecture 10
OUTCOME
`forEach` is for side effects (logging, DOM updates) and returns nothing. `map` returns a new array.

What you'll learn

  • 1Choose between `forEach`, `map`, `filter`, `reduce`, `find`, `some`, `every`.
  • 2Know the callback parameters (element, index, array).
  • 3Build data pipelines with method chaining.
  • 4Prefer a functional style that doesn't mutate the input.
  • 5Use `reduce` safely with the right initial value.

Overview

`forEach` is for side effects (logging, DOM updates) and returns nothing. `map` returns a new array.

Core Concepts

1. forEach and map

`forEach` is for side effects (logging, DOM updates) and returns nothing. `map` returns a new array.

javascript
[1, 2, 3].forEach((x) => console.log(x));
const doubled = [1, 2, 3].map((x) => x * 2); // [2,4,6]

2. filter, find, some, every

Select elements that satisfy a condition.

javascript
[1,2,3,4].filter((x) => x % 2 === 0); // [2,4]
[1,2,3].find((x) => x > 1);            // 2 (first match)
[1,2,3].some((x) => x > 2);            // true
[1,2,3].every((x) => x > 0);           // true

3. reduce

Fold an array down to a single value. Always specify an initial value.

javascript
const sum = [1,2,3,4].reduce((acc, x) => acc + x, 0);
const byLen = ["a","bb","ccc"].reduce((g, w) => {
  (g[w.length] ??= []).push(w);
  return g;
}, {});

4. Chaining

Functional pipelines tend to read very nicely.

javascript
const users = [
  { name: "A", age: 17 },
  { name: "B", age: 22 },
  { name: "C", age: 30 },
];
const result = users
  .filter((u) => u.age >= 18)
  .map((u) => u.name)
  .join(", ");

Examples

FileWhat it covers
`01_map.js`Transform with map
`02_filter.js`filter / find
`03_reduce.js`Sum and grouping
`04_chain.js`filter → map → reduce chain

src/01_map.js

javascript
/**
 * map: transform
 */
"use strict";

const nums = [1, 2, 3, 4];
const squares = nums.map((x) => x * x);
console.log(squares);

const users = [
  { name: "A", age: 20 },
  { name: "B", age: 25 },
];
console.log(users.map((u) => u.name));

src/02_filter.js

javascript
/**
 * filter, find
 */
"use strict";

const nums = [1, 2, 3, 4, 5, 6];
console.log("evens =", nums.filter((x) => x % 2 === 0));

const users = [
  { id: 1, active: false },
  { id: 2, active: true },
  { id: 3, active: true },
];
console.log("first active =", users.find((u) => u.active));
console.log("actives =", users.filter((u) => u.active));

src/03_reduce.js

javascript
/**
 * reduce: sum and groupBy
 */
"use strict";

const nums = [1, 2, 3, 4];
const sum = nums.reduce((acc, x) => acc + x, 0);
console.log("sum =", sum);

const words = ["js", "go", "rust", "py", "c"];
const byLen = words.reduce((g, w) => {
  (g[w.length] ??= []).push(w);
  return g;
}, {});
console.log("byLen =", byLen);

src/04_chain.js

javascript
/**
 * Chaining
 */
"use strict";

const users = [
  { name: "A", age: 17, score: 80 },
  { name: "B", age: 22, score: 95 },
  { name: "C", age: 30, score: 60 },
  { name: "D", age: 25, score: 88 },
];

const avgAdultScore = users
  .filter((u) => u.age >= 18)
  .map((u) => u.score)
  .reduce((acc, s, _i, arr) => acc + s / arr.length, 0);

console.log("avg adult score =", avgAdultScore);

Common Mistakes

  1. Calling `reduce` without an initial value, then hitting TypeError on an empty array.
  2. Using `map` only for side effects and throwing away the result — that's what `forEach` is for.
  3. Forgetting that `filter` accepts any truthy/falsy callback result, not just booleans.
  4. Worrying about chain performance — readability usually wins.
  5. Forgetting `return` inside a callback and ending up with an array of `undefined`.

FAQ

Q1. How do these compare in performance to a `for` loop?

Usually negligible. Optimize for readability first.

Q2. What about `flat` and `flatMap`?

`flat` flattens nested arrays; `flatMap` does map and flatten in one pass.

Q3. How do I run async work with map?

It produces an array of Promises — use `Promise.all(arr.map(...))`.

Practice

  • `homework_01.js` — Compute the average score of an array of students with `reduce`.
  • `homework_02.js` — Total revenue per category from a list of products.

homework/README.md

## homework_01.js — Use `reduce` to compute the average score for an array of students.

text
[ { name:"A", score:80 }, { name:"B", score:90 }, { name:"C", score:70 } ]

## homework_02.js — Return an object with the total price grouped by category.

text
[ { name:"apple", category:"fruit", price:1000 },
  { name:"banana", category:"fruit", price:1500 },
  { name:"milk", category:"dairy", price:2500 } ]
→ { fruit: 2500, dairy: 2500 }

homework/answer/homework_01.js

javascript
/**
 * Homework 1: average score
 */
"use strict";

const students = [
  { name: "A", score: 80 },
  { name: "B", score: 90 },
  { name: "C", score: 70 },
];

const avg = students.reduce((acc, s, _i, arr) => acc + s.score / arr.length, 0);
console.log("avg =", avg); // 80

homework/answer/homework_02.js

javascript
/**
 * Homework 2: total by category
 */
"use strict";

const products = [
  { name: "apple", category: "fruit", price: 1000 },
  { name: "banana", category: "fruit", price: 1500 },
  { name: "milk", category: "dairy", price: 2500 },
];

const totals = products.reduce((g, p) => {
  g[p.category] = (g[p.category] ?? 0) + p.price;
  return g;
}, {});

console.log(totals); // { fruit: 2500, dairy: 2500 }

Next Lecture

[12_Closures_and_Scope](../12_클로저와_스코프/) — Functions and state.

Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub ↗