- [[#Simple Array Methods (Working with Arrays)|Simple Array Methods (Working with Arrays)]]
- [[#Simple Array Methods (Working with Arrays)#Array Declaration|Array Declaration]]
- [[#Simple Array Methods (Working with Arrays)#Accessing and Changing Items|Accessing and Changing Items]]
- [[#Simple Array Methods (Working with Arrays)#Looping Through Array|Looping Through Array]]
- [[#Simple Array Methods (Working with Arrays)#Mutable vs Immutable Methods|Mutable vs Immutable Methods]]
- [[#Mutable vs Immutable Methods#
slice()|slice()]]
- [[#Mutable vs Immutable Methods#
- [[#Simple Array Methods (Working with Arrays)#Copying an Array with
slice()|Copying an Array withslice()]]- [[#Copying an Array with
slice()#splice()|splice()]] - [[#Copying an Array with
slice()#Removing withsplice()|Removing withsplice()]] - [[#Copying an Array with
slice()#Adding withsplice()|Adding withsplice()]] - [[#Copying an Array with
slice()#reverse()|reverse()]] - [[#Copying an Array with
slice()#concat()|concat()]] - [[#Copying an Array with
slice()#join()|join()]] - [[#Copying an Array with
slice()#toString()|toString()]] - [[#Copying an Array with
slice()#push()|push()]] - [[#Copying an Array with
slice()#pop()|pop()]] - [[#Copying an Array with
slice()#unshift()|unshift()]] - [[#Copying an Array with
slice()#shift()|shift()]] - [[#Copying an Array with
slice()#Changing Array Length|Changing Array Length]] - [[#Copying an Array with
slice()#deleteon Arrays|deleteon Arrays]]
- [[#Copying an Array with
- [[#Simple Array Methods (Working with Arrays)#Sorting Arrays|Sorting Arrays]]
- [[#Sorting Arrays#Default
sort()|Defaultsort()]] - [[#Sorting Arrays#Numeric Sort|Numeric Sort]]
- [[#Sorting Arrays#Default
- [[#Simple Array Methods (Working with Arrays)#Numeric Descending Sort|Numeric Descending Sort]]
- [[#Numeric Descending Sort#Get Highest or Lowest Number|Get Highest or Lowest Number]]
- [[#Simple Array Methods (Working with Arrays)#Quick Method Summary|Quick Method Summary]]
- [[#Simple Array Methods (Working with Arrays)#Core Syntax|Core Syntax]]
- [[#Simple Array Methods (Working with Arrays)#Core Mental Model|Core Mental Model]]
- [[#The
at()Method|Theat()Method]]- [[#The
at()Method#Basic Example|Basic Example]] - [[#The
at()Method#Syntax|Syntax]] - [[#The
at()Method#Getting the Last Array Element|Getting the Last Array Element]] - [[#The
at()Method#Negative Indexes|Negative Indexes]]- [[#Negative Indexes#
at()vs Bracket Notation|at()vs Bracket Notation]]
- [[#Negative Indexes#
- [[#The
at()Method#Usingat()with Strings|Usingat()with Strings]] - [[#The
at()Method#First vs Last Element|First vs Last Element]]- [[#First vs Last Element#Does
at()Change the Array?|Doesat()Change the Array?]]
- [[#First vs Last Element#Does
- [[#The
at()Method#Quick Syntax Summary|Quick Syntax Summary]]- [[#Quick Syntax Summary#Method Summary|Method Summary]]
- [[#The
at()Method#Core Mental Model|Core Mental Model]]
- [[#The
- [[#Looping Arrays:
forEach|Looping Arrays:forEach]]- [[#Looping Arrays:
forEach#Basic Syntax|Basic Syntax]] - [[#Looping Arrays:
forEach#Callback Function Parameters|Callback Function Parameters]] - [[#Looping Arrays:
forEach#Example: Bank Movements|Example: Bank Movements]] - [[#Looping Arrays:
forEach#Whyi + 1?|Whyi + 1?]] - [[#Looping Arrays:
forEach#WhyMath.abs()?|WhyMath.abs()?]] - [[#Looping Arrays:
forEach#forEach()with Arrow Function|forEach()with Arrow Function]] - [[#Looping Arrays:
forEach#forEach()vsfor...of|forEach()vsfor...of]]- [[#
forEach()vsfor...of#for...of|for...of]] - [[#
forEach()vsfor...of#forEach()|forEach()]]
- [[#
- [[#Looping Arrays:
forEach#Main Difference|Main Difference]] - [[#Looping Arrays:
forEach#forEach()Does Not Return Useful Value|forEach()Does Not Return Useful Value]] - [[#Looping Arrays:
forEach#DoesforEach()Mutate the Array?|DoesforEach()Mutate the Array?]] - [[#Looping Arrays:
forEach#thisArginforEach()|thisArginforEach()]] - [[#Looping Arrays:
forEach#Async Warning|Async Warning]] - [[#Looping Arrays:
forEach#Quick Syntax Summary|Quick Syntax Summary]] - [[#Looping Arrays:
forEach#Core Mental Model|Core Mental Model]]
- [[#Looping Arrays:
- [[#forEach With Maps and Sets|forEach With Maps and Sets]]
- [[#forEach With Maps and Sets#
forEach()with Maps|forEach()with Maps]] - [[#forEach With Maps and Sets#Map
forEach()Syntax|MapforEach()Syntax]] - [[#forEach With Maps and Sets#Map Example|Map Example]]
- [[#forEach With Maps and Sets#How It Works|How It Works]]
- [[#forEach With Maps and Sets#
forEach()with Sets|forEach()with Sets]] - [[#forEach With Maps and Sets#Set
forEach()Syntax|SetforEach()Syntax]] - [[#forEach With Maps and Sets#Set Example|Set Example]]
- [[#forEach With Maps and Sets#Why Does Set Have
key?|Why Does Set Havekey?]] - [[#forEach With Maps and Sets#Ignoring Unused Parameters|Ignoring Unused Parameters]]
- [[#forEach With Maps and Sets#Array vs Map vs Set
forEach()|Array vs Map vs SetforEach()]] - [[#forEach With Maps and Sets#Return Value|Return Value]]
- [[#forEach With Maps and Sets#Cannot Break
forEach()|Cannot BreakforEach()]] - [[#forEach With Maps and Sets#Quick Syntax Summary|Quick Syntax Summary]]
- [[#forEach With Maps and Sets#Core Mental Model|Core Mental Model]]
- [[#forEach With Maps and Sets#
- [[#The
map()Method|Themap()Method]]- [[#The
map()Method#Basic Idea|Basic Idea]] - [[#The
map()Method#Example: Convert EUR to USD|Example: Convert EUR to USD]] - [[#The
map()Method#Same Code with Regular Function|Same Code with Regular Function]] - [[#The
map()Method#Howmap()Works Internally|Howmap()Works Internally]] - [[#The
map()Method#map()Callback Parameters|map()Callback Parameters]] - [[#The
map()Method#Example: Movement Descriptions|Example: Movement Descriptions]] - [[#The
map()Method#WhyMath.abs()?|WhyMath.abs()?]] - [[#The
map()Method#Why Use Ternary Operator?|Why Use Ternary Operator?]] - [[#The
map()Method#map()vsfor...of|map()vsfor...of]] - [[#The
map()Method#map()vsforEach()|map()vsforEach()]] - [[#The
map()Method#Doesmap()Mutate the Original Array?|Doesmap()Mutate the Original Array?]] - [[#The
map()Method#Side Effects|Side Effects]] - [[#The
map()Method#Bad Use ofmap()|Bad Use ofmap()]] - [[#The
map()Method#Common Mistake: Forgettingreturn|Common Mistake: Forgettingreturn]] - [[#The
map()Method#Quick Syntax Summary|Quick Syntax Summary]] - [[#The
map()Method#Core Mental Model|Core Mental Model]]
- [[#The
- [[#The
filter()Method|Thefilter()Method]]- [[#The
filter()Method#Basic Idea|Basic Idea]] - [[#The
filter()Method#Example: Get Deposits|Example: Get Deposits]] - [[#The
filter()Method#Howfilter()Works|Howfilter()Works]] - [[#The
filter()Method#Example: Get Withdrawals|Example: Get Withdrawals]] - [[#The
filter()Method#Callback Parameters|Callback Parameters]] - [[#The
filter()Method#filter()vsfor...of|filter()vsfor...of]] - [[#The
filter()Method#filter()Does Not Mutate Original Array|filter()Does Not Mutate Original Array]] - [[#The
filter()Method#filter()Result Length|filter()Result Length]] - [[#The
filter()Method#filter()vsmap()|filter()vsmap()]] - [[#The
filter()Method#filter()vsforEach()|filter()vsforEach()]] - [[#The
filter()Method#Common Mistake: Forgettingreturn|Common Mistake: Forgettingreturn]] - [[#The
filter()Method#Common Mistake: Returning the Value Instead of a Condition|Common Mistake: Returning the Value Instead of a Condition]] - [[#The
filter()Method#Practical Examples|Practical Examples]]- [[#Practical Examples#Get Even Numbers|Get Even Numbers]]
- [[#Practical Examples#Get Long Names|Get Long Names]]
- [[#Practical Examples#Remove Negative Numbers|Remove Negative Numbers]]
- [[#The
filter()Method#Quick Syntax Summary|Quick Syntax Summary]] - [[#The
filter()Method#Core Mental Model|Core Mental Model]]
- [[#The
- [[#The
reduce()Method|Thereduce()Method]]- [[#The
reduce()Method#Basic Idea|Basic Idea]] - [[#The
reduce()Method#The Accumulator|The Accumulator]] - [[#The
reduce()Method#Example: Calculate Balance|Example: Calculate Balance]] - [[#The
reduce()Method#Callback Parameters|Callback Parameters]] - [[#The
reduce()Method#Seeing the Accumulator|Seeing the Accumulator]] - [[#The
reduce()Method#reduce()vsfor...of|reduce()vsfor...of]] - [[#The
reduce()Method#Initial Value|Initial Value]] - [[#The
reduce()Method#What Happens Without Initial Value?|What Happens Without Initial Value?]] - [[#The
reduce()Method#Example: Find Maximum Value|Example: Find Maximum Value]] - [[#The
reduce()Method#Shorter Maximum Version|Shorter Maximum Version]] - [[#The
reduce()Method#Example: Count Deposits|Example: Count Deposits]] - [[#The
reduce()Method#Example: Sum Only Deposits|Example: Sum Only Deposits]] - [[#The
reduce()Method#reduce()vsmap()vsfilter()|reduce()vsmap()vsfilter()]] - [[#The
reduce()Method#Common Mistake: Forgettingreturn|Common Mistake: Forgettingreturn]] - [[#The
reduce()Method#Doesreduce()Mutate the Original Array?|Doesreduce()Mutate the Original Array?]] - [[#The
reduce()Method#Quick Syntax Summary|Quick Syntax Summary]] - [[#The
reduce()Method#Core Mental Model|Core Mental Model]]
- [[#The
Arrays store multiple values in one variable.
const arr = ['a', 'b', 'c', 'd', 'e'];Arrays are indexed from 0.
arr[0]; // 'a'
arr[1]; // 'b'Two common ways:
const dogs = ['Bulldog', 'Beagle', 'Labrador'];
const dogs2 = new Array('Bulldog', 'Beagle', 'Labrador');Most common style:
const dogs = ['Bulldog', 'Beagle', 'Labrador'];[!tip] Tip
Prefer array literal syntax[]. It is shorter and cleaner.
const dogs = ['Bulldog', 'Beagle', 'Labrador'];
console.log(dogs[1]); // Beagle
dogs[0] = 'Bull Terrier';
console.log(dogs);
// ['Bull Terrier', 'Beagle', 'Labrador'][!warning] Important
Even withconst, array contents can still be changed.
constonly prevents reassigning the whole variable.
const dogs = ['A', 'B'];
dogs[0] = 'X'; // allowed
dogs = ['X', 'Y']; // not allowedconst dogs = ['A', 'B'];
for (let i = 0; i < dogs.length; i++) {
console.log(dogs[i]);
}
console.log("dogs.length: " + dogs.length);dogs.length gives the number of elements.
dogs.length;Mutable methods change the original array.
Immutable methods return a new value and keep the original array unchanged.
| Type | Methods |
|---|---|
| Mutable | push(), pop(), shift(), unshift(), splice(), reverse(), sort() |
| Immutable | slice(), concat(), join(), toString() |
[!warning] Warning
Always know whether a method changes the original array or not.
slice() extracts a part of an array without changing the original.
const arr = ['a', 'b', 'c', 'd', 'e'];
console.log(arr.slice(2));
// ['c', 'd', 'e']
console.log(arr.slice(2, 4));
// ['c', 'd']
console.log(arr.slice(-2));
// ['d', 'e']
console.log(arr.slice(1, -2));
// ['b', 'c']
console.log(arr.slice());
// ['a', 'b', 'c', 'd', 'e']Syntax:
array.slice(startIndex, endIndex);[!important] Important
TheendIndexis not included.
arr.slice(2, 4);Means:
start at index 2
stop before index 4
const arrCopy = arr.slice();Same result using spread:
const arrCopy = [...arr];[!tip] Tip
Useslice()or spread when you want a shallow copy of an array.
splice() removes or adds elements and changes the original array.
const arr = ['a', 'b', 'c', 'd', 'e'];
arr.splice(2);
console.log(arr);
// ['a', 'b']Syntax:
array.splice(startIndex, deleteCount, item1, item2);const arr = ['a', 'b', 'c', 'd', 'e'];
arr.splice(1, 2);
console.log(arr);
// ['a', 'd', 'e']Explanation:
start at index 1
remove 2 elementsSo it removes:
'b', 'c'[!warning] Warning
splice()mutates the original array.
const dogs = ['Bulldog', 'Beagle', 'Labrador'];
dogs.splice(2, 0, 'Pug', 'Boxer');
console.log(dogs);
// ['Bulldog', 'Beagle', 'Pug', 'Boxer', 'Labrador']Explanation:
2 → start at index 2
0 → remove nothing
'Pug', 'Boxer' → add these items
reverse() reverses the array and changes the original.
const arr = ['a', 'b', 'c', 'd', 'e'];
arr.reverse();
console.log(arr);
// ['e', 'd', 'c', 'b', 'a'][!danger] Be Careful
reverse()mutates the original array.
Modern immutable version:
const reversed = arr.toReversed();concat() joins arrays and returns a new array.
const arr = ['a', 'b', 'c'];
const arr2 = ['j', 'i', 'h'];
const letters = arr.concat(arr2);
console.log(letters);
// ['a', 'b', 'c', 'j', 'i', 'h']Same result with spread:
const letters = [...arr, ...arr2];[!tip] Tip
concat()does not change the original arrays.
join() converts an array into a string.
const letters = ['a', 'b', 'c', 'd'];
console.log(letters.join('-'));Output:
a-b-c-d
Syntax:
array.join(separator);Examples:
letters.join(''); // abcd
letters.join(' '); // a b c d
letters.join('-'); // a-b-c-dtoString() converts array elements into a comma-separated string.
const dogs = ['Bulldog', 'Beagle', 'Labrador'];
console.log(dogs.toString());Output:
Bulldog,Beagle,Labrador
[!info] Note
join()gives more control because you can choose the separator.
dogs.join(' * ');
// Bulldog * Beagle * Labradorpush() adds an element to the end.
const dogs = ['Bulldog', 'Beagle'];
dogs.push('Chihuahua');
console.log(dogs);
// ['Bulldog', 'Beagle', 'Chihuahua'][!warning] Warning
push()mutates the original array.
pop() removes the last element.
const dogs = ['Bulldog', 'Beagle', 'Chihuahua'];
const removed = dogs.pop();
console.log(removed); // Chihuahua
console.log(dogs); // ['Bulldog', 'Beagle'][!tip] Tip
pop()returns the removed element.
unshift() adds an element to the beginning.
const dogs = ['Beagle', 'Labrador'];
dogs.unshift('Chihuahua');
console.log(dogs);
// ['Chihuahua', 'Beagle', 'Labrador']shift() removes the first element.
const dogs = ['Chihuahua', 'Beagle', 'Labrador'];
const removed = dogs.shift();
console.log(removed); // Chihuahua
console.log(dogs); // ['Beagle', 'Labrador']const dogs = ['Bulldog', 'Beagle', 'Labrador', 'Pug'];
dogs.length = 2;
console.log(dogs);
// ['Bulldog', 'Beagle']This cuts the array to only 2 elements.
[!danger] Be Careful
Changing.lengthdirectly mutates the array and can delete items.
const dogs = ['Bulldog', 'Beagle', 'Labrador'];
delete dogs[0];
console.log(dogs);
// [empty, 'Beagle', 'Labrador'][!warning] Warning
Avoid usingdeleteon arrays.
It leaves an empty hole instead of properly removing the element.
Better:
dogs.splice(0, 1);const dogs = ['Labrador', 'Beagle', 'Bulldog'];
dogs.sort();
console.log(dogs);
// ['Beagle', 'Bulldog', 'Labrador']sort() sorts strings alphabetically.
[!warning] Warning
sort()mutates the original array.
Default sort does not work properly for numbers.
const numbers = [10, 2, 5, 100];
numbers.sort();
console.log(numbers);
// [10, 100, 2, 5]Because JavaScript sorts them like strings.
Correct numeric ascending sort:
numbers.sort(function (a, b) {
return a - b;
});
console.log(numbers);
// [2, 5, 10, 100]Shorter arrow version:
numbers.sort((a, b) => a - b);numbers.sort((a, b) => b - a);Output:
[100, 10, 5, 2]
[!tip] Remember
Ascending:
(a, b) => a - bDescending:
(a, b) => b - aconst x = [10, 5, 100, 2];
x.sort((a, b) => a - b);
const lowest = x[0];
const highest = x[x.length - 1];
console.log(lowest); // 2
console.log(highest); // 100[!info] Better Later
For just finding min/max, methods likeMath.min()andMath.max()are usually cleaner.
| Method | Meaning | Mutates Original? |
|---|---|---|
slice() |
Extract copy of part | No |
splice() |
Add/remove items | Yes |
reverse() |
Reverse order | Yes |
concat() |
Join arrays | No |
join() |
Convert array to string | No |
toString() |
Convert to comma string | No |
push() |
Add to end | Yes |
pop() |
Remove from end | Yes |
unshift() |
Add to start | Yes |
shift() |
Remove from start | Yes |
sort() |
Sort array | Yes |
arr.slice(start, end);
arr.splice(start, deleteCount, item1, item2);
arr.reverse();
arr.concat(otherArray);
arr.join(separator);
arr.push(item);
arr.pop();
arr.unshift(item);
arr.shift();
arr.sort();
arr.sort((a, b) => a - b);Array methods help you add, remove, copy, join, reverse, and sort array data.
Most important difference:
slice → copies part of array
splice → changes original array
[!success] Remember
When learning array methods, always ask:
Does this method mutate the original array?
at() is an ES2022 method used to get an element from an array or character from a string using an index.
It is especially useful for getting the last element.
const arr = [23, 11, 64];
console.log(arr[0]); // 23
console.log(arr.at(0)); // 23Both give the same result.
arr[0]
arr.at(0)Both mean:
Get the element at index 0
array.at(index);
string.at(index);Example:
arr.at(0);
arr.at(1);
arr.at(-1);[!important] Important
Indexing still starts from0.
const arr = [23, 11, 64];
arr.at(0); // 23
console.log(arr[-1]); // 11
console.log(arr.at(-1)); // 64Before at():
console.log(arr[arr.length - 1]);Another older way:
console.log(arr.slice(-1)[0]);Modern way:
console.log(arr.at(-1));Output:
64
arr.at(-1) means get the last element.
Negative indexes count from the end.
const arr = [23, 11, 64];
arr.at(-1); // 64
arr.at(-2); // 11
arr.at(-3); // 23Mental model:
[23, 11, 64]
-3 -2 -1
[!tip] Tip
Use.at(-1)when you want the last item. It is cleaner thanarr[arr.length - 1].
arr[0]; // works
arr.at(0); // worksBut with negative indexes:
arr[-1]; // undefined
arr.at(-1); // last element[!warning] Warning
Bracket notation does not support negative indexes.
const arr = [23, 11, 64];
console.log(arr[-1]); // undefined
console.log(arr.at(-1)); // 64at() also works on strings.
console.log('jonas'.at(0)); // j
console.log('jonas'.at(-1)); // sThis is useful for getting characters.
const name = 'jonas';
name.at(0); // first character
name.at(-1); // last characterconst arr = [23, 11, 64];
const first = arr.at(0);
const last = arr.at(-1);
console.log(first); // 23
console.log(last); // 64[!success] Clean Pattern
Use this pattern often:
arr.at(0); // first element
arr.at(-1); // last elementNo.
const arr = [23, 11, 64];
arr.at(-1);
console.log(arr); // [23, 11, 64]at() only reads a value. It does not mutate the original array.
[!info] Note
at()is an immutable/read-only method.
const arr = [23, 11, 64];
arr.at(0); // 23
arr.at(1); // 11
arr.at(-1); // 64
arr.at(-2); // 11
arr[arr.length - 1]; // old way for last element
arr.slice(-1)[0]; // old way for last element
arr.at(-1); // modern wayFor strings:
'jonas'.at(0); // j
'jonas'.at(-1); // s| Code | Meaning |
|---|---|
arr.at(0) |
First element |
arr.at(1) |
Second element |
arr.at(-1) |
Last element |
arr.at(-2) |
Second last element |
str.at(0) |
First character |
str.at(-1) |
Last character |
at() gets an item by position.
The special benefit is negative indexing:
arr.at(-1)Means:
Give me the last element
[!success] Remember
Usearr.at(-1)instead ofarr[arr.length - 1]for cleaner code.
forEach() is an array method that runs a callback function once for each array element.
const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];
movements.forEach(function (movement) {
console.log(movement);
});array.forEach(function (element) {
// code to run for each element
});Arrow function version:
array.forEach(element => {
// code to run for each element
});[!important] Important
forEach()does not create a new array. It simply loops over the existing array.
forEach() can give the callback 3 values:
array.forEach(function (element, index, array) {
// code
});| Parameter | Meaning |
|---|---|
element |
Current item |
index |
Current index |
array |
Full original array |
Example:
movements.forEach(function (mov, i, arr) {
console.log(mov, i, arr);
});[!tip] Tip
The names do not matter. The order matters.
movements.forEach(function (a, b, c) {
// a = element
// b = index
// c = full array
});const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];
movements.forEach(function (mov, i) {
if (mov > 0) {
console.log(`Movement ${i + 1}: You deposited ${mov}`);
} else {
console.log(`Movement ${i + 1}: You withdrew ${Math.abs(mov)}`);
}
});Output:
Movement 1: You deposited 200
Movement 2: You deposited 450
Movement 3: You withdrew 400
Movement 4: You deposited 3000
Movement 5: You withdrew 650
Movement 6: You withdrew 130
Movement 7: You deposited 70
Movement 8: You deposited 1300Array indexes start from 0.
i = 0 → Movement 1
i = 1 → Movement 2
i = 2 → Movement 3So we use:
i + 1to display human-friendly numbering.
Withdrawals are negative numbers:
-400
-650
-130But we want to display them as positive values:
Math.abs(-400); // 400[!tip] Tip
Math.abs()removes the negative sign.
movements.forEach((mov, i) => {
if (mov > 0) {
console.log(`Movement ${i + 1}: You deposited ${mov}`);
} else {
console.log(`Movement ${i + 1}: You withdrew ${Math.abs(mov)}`);
}
});This is the same logic, just shorter syntax.
for (const [i, movement] of movements.entries()) {
if (movement > 0) {
console.log(`Movement ${i + 1}: You deposited ${movement}`);
} else {
console.log(`Movement ${i + 1}: You withdrew ${Math.abs(movement)}`);
}
}movements.forEach(function (movement, i) {
if (movement > 0) {
console.log(`Movement ${i + 1}: You deposited ${movement}`);
} else {
console.log(`Movement ${i + 1}: You withdrew ${Math.abs(movement)}`);
}
});| Feature | forEach() |
for...of |
|---|---|---|
| Works on arrays | Yes | Yes |
| Works on strings/maps/sets | No, arrays only | Yes |
Can use break |
No | Yes |
Can use continue |
No | Yes |
| Callback style | Yes | No |
[!warning] Warning
You cannot break out of aforEach()loop early.
movements.forEach(function (mov) {
if (mov < 0) break; // Error
});Use for...of if you need break or continue.
const result = movements.forEach(function (mov) {
return mov * 2;
});
console.log(result); // undefinedforEach() always returns:
undefined[!important] Important
UseforEach()for actions like logging, updating UI, or running code for each item.
Usemap()when you want a new transformed array.
forEach() itself does not mutate the array.
const nums = [1, 2, 3];
nums.forEach(num => {
console.log(num);
});
console.log(nums); // [1, 2, 3]But you can mutate the array inside the callback if you write code that changes it.
const nums = [1, 2, 3];
nums.forEach((num, i, arr) => {
arr[i] = num * 2;
});
console.log(nums); // [2, 4, 6][!warning] Warning
Avoid mutating arrays insideforEach()unless you clearly intend to.
Syntax:
array.forEach(callbackFunction, thisArg);Example:
const account = {
owner: 'Jonas',
currency: 'EUR',
};
movements.forEach(function (mov) {
console.log(`${this.owner}: ${mov} ${this.currency}`);
}, account);Here:
this → account
[!info] Note
thisArgis rarely used in modern JavaScript. Arrow functions are often cleaner, but arrow functions do not get their ownthis.
array.forEach(async function (item) {
await someAsyncTask(item);
});[!danger] Be Careful
forEach()does not wait for promises.
For async loops, preferfor...ofwithawait.
for (const item of array) {
await someAsyncTask(item);
}array.forEach(function (element) {
// use element
});
array.forEach(function (element, index) {
// use element and index
});
array.forEach(function (element, index, array) {
// use element, index, and full array
});
array.forEach((element, index) => {
// arrow function version
});forEach() means: “Do this once for every element.”
array.forEach(callback);JavaScript automatically calls the callback like this:
callback(element, index, array);[!success] Remember
forEach()is good for performing actions, not for creating new arrays.
For creating new arrays, usemap().
forEach() can be used not only on arrays, but also on Maps and Sets.
It runs a callback function once for each item.
A Map stores data as:
key → value
Example:
const currencies = new Map([
['USD', 'United States dollar'],
['EUR', 'Euro'],
['GBP', 'Pound sterling'],
]);map.forEach(function (value, key, map) {
// code
});Parameter order:
| Parameter | Meaning |
|---|---|
value |
Current value |
key |
Current key |
map |
Full Map |
[!warning] Warning
InMap.forEach(), the order is:value, key, mapNot
key, value.
const currencies = new Map([
['USD', 'United States dollar'],
['EUR', 'Euro'],
['GBP', 'Pound sterling'],
]);
currencies.forEach(function (value, key, map) {
console.log(`${key}: ${value}`);
});Output:
USD: United States dollar
EUR: Euro
GBP: Pound sterling
For this entry:
['USD', 'United States dollar']JavaScript passes:
value → 'United States dollar'
key → 'USD'
map → full currencies map
So this line:
console.log(`${key}: ${value}`);becomes:
console.log(`USD: United States dollar`);A Set stores unique values.
const currenciesUnique = new Set(['USD', 'GBP', 'USD', 'EUR', 'EUR']);
console.log(currenciesUnique);Output:
Set(3) {'USD', 'GBP', 'EUR'}Duplicates are removed automatically.
[!tip] Remember
A Set has only values, no real keys.
set.forEach(function (value, key, set) {
// code
});But in a Set:
value === keyBecause Sets do not have keys.
const currenciesUnique = new Set(['USD', 'GBP', 'USD', 'EUR', 'EUR']);
currenciesUnique.forEach(function (value, key, set) {
console.log(`${key}: ${value}`);
});Output:
USD: USD
GBP: GBP
EUR: EUR
Sets do not actually need keys.
But JavaScript keeps the same callback structure as Maps and Arrays for consistency.
function (value, key, set)In Sets:
key = value
[!info] Note
For Sets, the second parameter exists only to keep the API consistent with Maps.
If you do not need key, use _.
currenciesUnique.forEach(function (value, _, set) {
console.log(value);
});Here:
_
means:
I know this parameter exists, but I am not using it.
[!tip] Tip
_is a common convention for ignored parameters.
| Collection | Callback Parameters |
|---|---|
| Array | (element, index, array) |
| Map | (value, key, map) |
| Set | (value, value, set) |
Examples:
array.forEach(function (element, index, array) {});
map.forEach(function (value, key, map) {});
set.forEach(function (value, key, set) {});Main difference:
Arrays use an index, Maps use a key, Sets repeat the value.
forEach() returns:
undefined
Example:
const result = currencies.forEach(function (value, key) {
return `${key}: ${value}`;
});
console.log(result); // undefined[!warning] Warning
Do not useforEach()when you need a returned result.
Use it when you want to perform an action for each item.
You cannot use break or continue inside forEach().
currencies.forEach(function (value, key) {
if (key === 'EUR') break; // Error
});Use for...of instead:
for (const [key, value] of currencies) {
if (key === 'EUR') break;
console.log(`${key}: ${value}`);
}[!important] Important
Usefor...ofwhen you needbreakorcontinue.
const currencies = new Map([
['USD', 'United States dollar'],
['EUR', 'Euro'],
['GBP', 'Pound sterling'],
]);
currencies.forEach(function (value, key, map) {
console.log(`${key}: ${value}`);
});const currenciesUnique = new Set(['USD', 'GBP', 'USD', 'EUR']);
currenciesUnique.forEach(function (value, _, set) {
console.log(value);
});forEach() means: run this function once for each item.
For Maps:
value + key
For Sets:
value only
[!success] Remember
MapforEach()gives:value, key, mapSet
forEach()gives:value, value, set
![[Media/Pasted image 20260608215802.png]]
map() is an array method that creates a new array by transforming every element of an existing array.
const movements = [200, 450, -400, 3000, -650];const newArray = oldArray.map(function (element) {
return transformedElement;
});Arrow function version:
const newArray = oldArray.map(element => transformedElement);[!important] Important
map()always returns a new array with the same length as the original array.
const movements = [200, 450, -400, 3000, -650];
const eurToUsd = 1.1;
const movementsUSD = movements.map(mov => mov * eurToUsd);
console.log(movements);
console.log(movementsUSD);Output:
[200, 450, -400, 3000, -650]
[220, 495, -440, 3300, -715]
The original array is unchanged.
movements // original array
movementsUSD // new transformed arrayconst movementsUSD = movements.map(function (mov) {
return mov * eurToUsd;
});Same result as:
const movementsUSD = movements.map(mov => mov * eurToUsd);[!tip] Tip
Arrow functions are commonly used withmap()because they are short and clean.
For every element, JavaScript runs the callback.
movements.map(mov => mov * eurToUsd);This means:
200 → 200 * 1.1 → 220
450 → 450 * 1.1 → 495
-400 → -400 * 1.1 → -440
3000 → 3000 * 1.1 → 3300
-650 → -650 * 1.1 → -715
Final result:
[220, 495, -440, 3300, -715]
map() can give the callback 3 values:
array.map(function (element, index, array) {
return something;
});| Parameter | Meaning |
|---|---|
element |
Current item |
index |
Current index |
array |
Full original array |
Example:
movements.map(function (mov, i, arr) {
return `Movement ${i + 1}: ${mov}`;
});[!warning] Warning
The order matters:
element, thenindex, thenarray.
const movements = [200, 450, -400, 3000, -650];
const movementsDescriptions = movements.map((mov, i) => {
return `Movement ${i + 1}: You ${
mov > 0 ? 'deposited' : 'withdrew'
} ${Math.abs(mov)}`;
});
console.log(movementsDescriptions);Output:
[
'Movement 1: You deposited 200',
'Movement 2: You deposited 450',
'Movement 3: You withdrew 400',
'Movement 4: You deposited 3000',
'Movement 5: You withdrew 650'
]Withdrawals are negative:
-400
-650
But we want to display:
400
650
So we use:
Math.abs(mov)
Example:
Math.abs(-400); // 400mov > 0 ? 'deposited' : 'withdrew'Meaning:
if mov > 0 → deposited
else → withdrew
So this:
`You ${mov > 0 ? 'deposited' : 'withdrew'} ${Math.abs(mov)}`
creates different text depending on the value.
Using for...of:
const movementsUSDFor = [];
for (const mov of movements) {
movementsUSDFor.push(mov * eurToUsd);
}
console.log(movementsUSDFor);Using map():
const movementsUSD = movements.map(mov => mov * eurToUsd);
console.log(movementsUSD);Both can create the same result.
But map() is cleaner when transforming an array.
[!success] Best Use
Usemap()when you want to transform every item into a new array.
| Method | Purpose | Returns |
|---|---|---|
map() |
Transform array | New array |
forEach() |
Perform action | undefined |
Example with map():
const doubled = [1, 2, 3].map(num => num * 2);
console.log(doubled); // [2, 4, 6]Example with forEach():
const result = [1, 2, 3].forEach(num => num * 2);
console.log(result); // undefined[!warning] Warning
Do not useforEach()if your goal is to create a new array. Usemap().
No.
const nums = [1, 2, 3];
const doubled = nums.map(num => num * 2);
console.log(nums); // [1, 2, 3]
console.log(doubled); // [2, 4, 6]map() is immutable by default.
A side effect means changing something outside the function.
Example of side effect:
const arr = [1, 2, 3];
function sideEffect() {
arr.pop();
}
sideEffect();
console.log(arr); // [1, 2]Here, the function changes the original array.
[!warning] Warning
Avoid side effects insidemap().
map()should usually return transformed values, not mutate existing data.
const nums = [1, 2, 3];
nums.map(num => {
console.log(num);
});This works, but it is not ideal because we are not using the returned array.
Better:
nums.forEach(num => {
console.log(num);
});[!tip] Rule
Usemap()when you need a new array.
UseforEach()when you only want to do something.
With curly braces, you need return.
Wrong:
const doubled = [1, 2, 3].map(num => {
num * 2;
});
console.log(doubled); // [undefined, undefined, undefined]Correct:
const doubled = [1, 2, 3].map(num => {
return num * 2;
});
console.log(doubled); // [2, 4, 6]Or shorter:
const doubled = [1, 2, 3].map(num => num * 2);[!important] Important
Arrow functions without{}return automatically.
Arrow functions with{}need explicitreturn.
array.map(function (element) {
return newValue;
});array.map(function (element, index, array) {
return newValue;
});array.map(element => newValue);array.map((element, index) => {
return newValue;
});map() transforms an array into a new array.
old array
↓ map()
new array
Example:
[1, 2, 3]
↓ num * 2
[2, 4, 6]
[!success] Remember
map()means:
take every item, transform it, and put the result into a new array.
filter() is an array method that creates a new array containing only the elements that pass a condition.
const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];const newArray = oldArray.filter(function (element) {
return condition;
});Arrow function version:
const newArray = oldArray.filter(element => condition);[!important] Important
filter()keeps an element only if the callback returnstrue.
Deposits are positive values.
const deposits = movements.filter(function (mov) {
return mov > 0;
});
console.log(deposits);Output:
[200, 450, 3000, 70, 1300]
Here:
mov > 0
means:
keep only positive numbers
movements.filter(mov => mov > 0);JavaScript checks each element:
200 → true → keep
450 → true → keep
-400 → false → remove
3000 → true → keep
-650 → false → remove
Final result:
[200, 450, 3000, 70, 1300]
[!tip] Mental Model
filter()asks each element:
Should I keep you or remove you?
Withdrawals are negative values.
const withdrawals = movements.filter(mov => mov < 0);
console.log(withdrawals);Output:
[-400, -650, -130]
Here:
mov < 0
means:
keep only negative numbers
filter() can receive 3 parameters:
array.filter(function (element, index, array) {
return condition;
});| Parameter | Meaning |
|---|---|
element |
Current item |
index |
Current index |
array |
Full original array |
Example:
const deposits = movements.filter(function (mov, i, arr) {
return mov > 0;
});[!warning] Warning
The order matters:
element, thenindex, thenarray.
Using for...of:
const depositsFor = [];
for (const mov of movements) {
if (mov > 0) {
depositsFor.push(mov);
}
}
console.log(depositsFor);Using filter():
const deposits = movements.filter(mov => mov > 0);
console.log(deposits);Both give the same result.
But filter() is cleaner and more declarative.
[!success] Best Use
Usefilter()when you want to select some elements from an array.
const movements = [200, 450, -400, 3000];
const deposits = movements.filter(mov => mov > 0);
console.log(movements); // [200, 450, -400, 3000]
console.log(deposits); // [200, 450, 3000]filter() returns a new array and leaves the original unchanged.
So filter() is immutable.
The new array can be:
shorter than original
same length as original
empty
Example:
const nums = [1, 2, 3];
nums.filter(num => num > 10);Output:
[]
Because no element passed the condition.
| Method | Purpose | Result |
|---|---|---|
map() |
Transform every element | Same length array |
filter() |
Keep selected elements | Same or shorter array |
Example:
const nums = [1, 2, 3, 4];
const doubled = nums.map(num => num * 2);
const greaterThanTwo = nums.filter(num => num > 2);
console.log(doubled); // [2, 4, 6, 8]
console.log(greaterThanTwo); // [3, 4][!tip] Remember
map()changes values.
filter()selects values.
| Method | Purpose | Returns |
|---|---|---|
forEach() |
Performs an action | undefined |
filter() |
Selects elements | New array |
Wrong use:
const deposits = [];
movements.forEach(mov => {
if (mov > 0) deposits.push(mov);
});Better:
const deposits = movements.filter(mov => mov > 0);Wrong:
const deposits = movements.filter(mov => {
mov > 0;
});
console.log(deposits); // []Why?
Because with {}, arrow functions need an explicit return.
Correct:
const deposits = movements.filter(mov => {
return mov > 0;
});Shorter correct version:
const deposits = movements.filter(mov => mov > 0);[!warning] Warning
If you use{}in an arrow function, writereturn.
This works, but can be confusing:
const result = movements.filter(mov => mov);This keeps truthy values and removes falsy values like:
0
false
''
null
undefined
NaN
Better for clarity:
const deposits = movements.filter(mov => mov > 0);[!important] Important
filter()expects a condition that becomestrueorfalse.
const numbers = [1, 2, 3, 4, 5, 6];
const even = numbers.filter(num => num % 2 === 0);
console.log(even); // [2, 4, 6]const names = ['Jonas', 'Martha', 'Adam', 'Alexandria'];
const longNames = names.filter(name => name.length > 5);
console.log(longNames); // ['Martha', 'Alexandria']const values = [10, -5, 20, -3];
const positiveValues = values.filter(value => value > 0);
console.log(positiveValues); // [10, 20]array.filter(function (element) {
return condition;
});array.filter(function (element, index, array) {
return condition;
});array.filter(element => condition);array.filter((element, index) => {
return condition;
});filter() creates a new array with only the elements that pass a test.
old array
↓ filter()
new smaller/same array
Example:
[200, -400, 3000, -650]
↓ mov > 0
[200, 3000]
[!success] Remember
filter()means:
keep this element if the condition is true.
reduce() is an array method used to reduce an entire array into one single value.
That single value can be:
number
string
object
array
boolean
Most common use: calculating totals.
const result = array.reduce(function (accumulator, currentValue) {
return updatedAccumulator;
}, initialValue);Arrow function version:
const result = array.reduce((accumulator, currentValue) => {
return updatedAccumulator;
}, initialValue);Short version:
const result = array.reduce((acc, cur) => acc + cur, 0);[!important] Important
reduce()returns one final value, not an array.
The accumulator is like a snowball.
It starts with an initial value, then keeps growing as the loop continues.
const movements = [200, 450, -400, 3000];const balance = movements.reduce((acc, cur) => acc + cur, 0);Here:
acc → accumulator / running total
cur → current array element
0 → initial value of acc
const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];
const balance = movements.reduce((acc, cur) => acc + cur, 0);
console.log(balance);Output:
3840
Explanation:
0 + 200 = 200
200 + 450 = 650
650 + -400 = 250
250 + 3000 = 3250
3250 + -650 = 2600
2600 + -130 = 2470
2470 + 70 = 2540
2540 + 1300 = 3840
[!tip] Mental Model
reduce()keeps carrying one value forward until the array ends.
reduce() can receive 4 callback parameters:
array.reduce(function (accumulator, currentValue, index, array) {
return updatedAccumulator;
}, initialValue);| Parameter | Meaning |
|---|---|
accumulator |
Running result |
currentValue |
Current element |
index |
Current index |
array |
Full original array |
[!warning] Warning
The order matters:
accumulator, thencurrentValue, thenindex, thenarray.
const balance = movements.reduce(function (acc, cur, i) {
console.log(`Iteration ${i}: ${acc}`);
return acc + cur;
}, 0);
console.log(balance);This helps you see how the accumulator changes each round.
Using for...of:
let balance2 = 0;
for (const mov of movements) {
balance2 += mov;
}
console.log(balance2);Using reduce():
const balance = movements.reduce((acc, cur) => acc + cur, 0);
console.log(balance);Both do the same thing.
[!success] Best Use
Usereduce()when you want to calculate one final value from an array.
const balance = movements.reduce((acc, cur) => acc + cur, 0);The 0 is the initial value of the accumulator.
acc starts as 0
Then each element is added to it.
[!important] Important
Always provide an initial value. It makes your code safer and easier to understand.
const balance = movements.reduce((acc, cur) => acc + cur);If no initial value is given:
acc starts as the first array element
cur starts as the second array element
This can work, but it is less clear.
[!warning] Warning
If the array is empty and there is no initial value,reduce()throws an error.
[].reduce((acc, cur) => acc + cur); // ErrorSafe version:
[].reduce((acc, cur) => acc + cur, 0); // 0const max = movements.reduce((acc, mov) => {
if (acc > mov) {
return acc;
} else {
return mov;
}
}, movements[0]);
console.log(max);Output:
3000
Here:
acc → current maximum
mov → current movement
The function keeps whichever value is bigger.
const max = movements.reduce((acc, mov) => {
return acc > mov ? acc : mov;
}, movements[0]);Even shorter:
const max = movements.reduce((acc, mov) => (acc > mov ? acc : mov), movements[0]);[!tip] Tip
For max/min, use the first element as the initial value:
movements[0]Because the maximum should be compared with real array values.
const depositCount = movements.reduce((count, mov) => {
return mov > 0 ? count + 1 : count;
}, 0);
console.log(depositCount);This counts how many positive values exist.
mov > 0 → increase count
else → keep count same
const totalDeposits = movements.reduce((sum, mov) => {
return mov > 0 ? sum + mov : sum;
}, 0);
console.log(totalDeposits);This adds only positive movements.
| Method | Purpose | Returns |
|---|---|---|
map() |
Transform every element | New array |
filter() |
Keep selected elements | New array |
reduce() |
Reduce array to one value | Single value |
Example:
const nums = [1, 2, 3, 4];
const doubled = nums.map(num => num * 2);
const greaterThanTwo = nums.filter(num => num > 2);
const total = nums.reduce((acc, num) => acc + num, 0);
console.log(doubled); // [2, 4, 6, 8]
console.log(greaterThanTwo); // [3, 4]
console.log(total); // 10[!tip] Remember
map()changes values.
filter()selects values.
reduce()calculates one final value.
Wrong:
const balance = movements.reduce((acc, cur) => {
acc + cur;
}, 0);
console.log(balance); // undefined or wrong resultCorrect:
const balance = movements.reduce((acc, cur) => {
return acc + cur;
}, 0);Or shorter:
const balance = movements.reduce((acc, cur) => acc + cur, 0);[!warning] Warning
With{}in an arrow function, you must writereturn.
No.
const nums = [1, 2, 3];
const total = nums.reduce((acc, num) => acc + num, 0);
console.log(nums); // [1, 2, 3]
console.log(total); // 6reduce() does not change the original array unless you manually mutate something inside it.
So reduce() is normally immutable.
array.reduce(function (accumulator, currentValue) {
return updatedAccumulator;
}, initialValue);array.reduce(function (accumulator, currentValue, index, array) {
return updatedAccumulator;
}, initialValue);array.reduce((acc, cur) => acc + cur, 0);array.reduce((acc, cur) => {
return acc + cur;
}, 0);reduce() takes many values and turns them into one value.
array
↓ reduce()
single value
Example:
[200, 450, -400]
↓ add all
250
[!success] Remember
reduce()means:
keep updating the accumulator until one final result is left.