JavaScript Arrays Advanced
In the previous lesson, you learned basic array operations. Now let's level up with array "power moves" — higher-order methods. These let you do more with less code and are essential skills in modern JavaScript development.
map — Transform Each Element
map runs a function on every element and returns a new array — the original stays unchanged. Think of it as an assembly line: each element goes in, gets transformed, and comes out as part of a new product.
<script>
let prices = [10, 20, 30];
let doubled = prices.map(p => p * 2); // [20, 40, 60]
</script>
The callback receives three arguments: (element, index, originalArray). Most of the time you only need the first one.
filter — Keep What Passes
filter keeps elements that pass a test and returns a new array — the original is untouched. Like a security checkpoint: items that meet the criteria go through; the rest get filtered out.
<script>
let scores = [45, 80, 92, 55, 78, 98];
let passed = scores.filter(s => s >= 60); // [80, 92, 78, 98]
</script>
Elements where the callback returns true are kept; those returning false are discarded.
reduce — Accumulate Into One Value
reduce "compresses" an array into a single value. The most common use case is summing:
<script>
let nums = [1, 2, 3, 4, 5];
let sum = nums.reduce((acc, cur) => acc + cur, 0); // 15
</script>
What the parameters mean:
acc(accumulator): the running total, carried over from the previous iterationcur(current): the current element- The second argument
0is the initial value for the accumulator
reduce seems tricky at first, but its essence is simple: step by step, compress the array into one value. Summing, finding the max, counting occurrences — reduce handles them all.
Example: Combining map, filter, and reduce
<!DOCTYPE html>
<html>
<body>
<h2>map / filter / reduce</h2>
<div id="output"></div>
<script>
let products = [
{ name: 'Laptop', price: 999, category: 'Electronics' },
{ name: 'T-Shirt', price: 19, category: 'Clothing' },
{ name: 'Mouse', price: 39, category: 'Electronics' },
{ name: 'Jeans', price: 49, category: 'Clothing' },
{ name: 'Keyboard', price: 79, category: 'Electronics' }
];
let html = '<strong>All Products:</strong><br>';
products.forEach(p => html += `${p.name} - $${p.price} (${p.category})<br>`);
let electronics = products.filter(p => p.category === 'Electronics');
html += '<br><strong>Electronics (filter):</strong><br>';
electronics.forEach(p => html += `${p.name} - $${p.price}<br>`);
let names = products.map(p => p.name);
html += '<br><strong>Product Names (map):</strong>' + names.join(', ') + '<br>';
let total = products.reduce((sum, p) => sum + p.price, 0);
html += '<br><strong>Total Price (reduce):</strong>$' + total;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
find and findIndex
find— returns the first element that matchesfindIndex— returns the index of the first match
If nothing is found, find returns undefined and findIndex returns -1.
<script>
let users = [
{ name: 'Alice', age: 20 },
{ name: 'Bob', age: 17 },
{ name: 'Charlie', age: 25 }
];
users.find(u => u.age > 22); // { name: 'Charlie', age: 25 }
users.findIndex(u => u.age < 18); // 1 (Bob's index)
</script>
sort — Order Elements
sort arranges the array in place (it modifies the original!). By default it sorts as strings, which trips up many beginners:
<script>
let nums = [10, 1, 21, 2];
nums.sort(); // [1, 10, 2, 21] ← String sort! "10" < "2"
// Correct: numeric sort requires a comparator function
nums.sort((a, b) => a - b); // [1, 2, 10, 21] ← Ascending
nums.sort((a, b) => b - a); // [21, 10, 2, 1] ← Descending
</script>
sort mutates the original array! To keep the original intact, copy first: [...arr].sort(...).
Example: Sorting Student Scores
<!DOCTYPE html>
<html>
<body>
<h2>Student Score Ranking</h2>
<div id="output"></div>
<script>
let students = [
{ name: 'Alice', score: 72 },
{ name: 'Bob', score: 95 },
{ name: 'Charlie', score: 88 },
{ name: 'Diana', score: 61 },
{ name: 'Eve', score: 95 }
];
let html = '<strong>Original Order:</strong><br>';
students.forEach(s => html += `${s.name} - ${s.score}<br>`);
let byScore = [...students].sort((a, b) => b.score - a.score);
html += '<br><strong>Sorted by Score (Descending):</strong><br>';
byScore.forEach((s, i) => {
let medal = i === 0 ? '🥇' : i === 1 ? '🥈' : i === 2 ? '🥉' : '';
html += `${medal} ${s.name} - ${s.score}<br>`;
});
let topStudents = students.filter(s => s.score >= 90);
html += '<br><strong>90 and Above (filter):</strong><br>';
topStudents.forEach(s => html += `${s.name} - ${s.score}<br>`);
let found = students.find(s => s.name === 'Charlie');
html += `<br><strong>Find "Charlie" (find):</strong>${found ? found.score : 'Not found'}`;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
some and every
some— does at least one element pass the test? (returns a boolean)every— do all elements pass the test? (returns a boolean)
<script>
let scores = [60, 75, 82, 90];
scores.some(s => s >= 90); // true — someone scored 90+
scores.some(s => s === 100); // false — no one got a perfect score
scores.every(s => s >= 60); // true — everyone passed
</script>
some asks "is there anyone who...", while every asks "does everyone...". One checks for existence; the other checks for completeness.
Spread Operator (...)
The spread operator ... "unpacks" an array. It's commonly used for copying and merging:
<script>
let a = [1, 2, 3];
let b = [...a]; // Copy: [1, 2, 3] (new array, not a reference)
let c = [...a, 4, 5]; // Merge: [1, 2, 3, 4, 5]
let d = [0, ...a, 4]; // Insert: [0, 1, 2, 3, 4]
let x = [1, 2], y = [3, 4];
let z = [...x, ...y]; // [1, 2, 3, 4]
</script>
Destructuring Assignment
Extract values from an array and assign them to variables by position:
<script>
let [a, b, c] = [1, 2, 3];
// a = 1, b = 2, c = 3
let [first, ...rest] = [1, 2, 3, 4, 5];
// first = 1, rest = [2, 3, 4, 5]
let [name, score] = ['Alice', 95];
// name = 'Alice', score = 95
</script>
Chaining Methods
Higher-order methods return new arrays, so you can chain them one after another:
<script>
let result = students
.filter(s => s.score >= 60) // First, filter passing students
.map(s => s.name) // Then, extract names
.sort(); // Finally, sort
</script>
Example: Chaining to Process Data
<!DOCTYPE html>
<html>
<body>
<h2>Method Chaining</h2>
<div id="output"></div>
<script>
let employees = [
{ name: 'Alice', dept: 'Engineering', salary: 8000 },
{ name: 'Bob', dept: 'Sales', salary: 5000 },
{ name: 'Charlie', dept: 'Engineering', salary: 12000 },
{ name: 'Diana', dept: 'Sales', salary: 6500 },
{ name: 'Eve', dept: 'Engineering', salary: 10000 },
{ name: 'Frank', dept: 'Marketing', salary: 5500 }
];
let html = '<strong>All Employees:</strong><br>';
employees.forEach(e => html += `${e.name} | ${e.dept} | $${e.salary}<br>`);
let techHighSalary = employees
.filter(e => e.dept === 'Engineering')
.filter(e => e.salary >= 9000)
.map(e => `${e.name}($${e.salary})`);
html += '<br><strong>Engineering High Earners (chained filter+map):</strong><br>' + techHighSalary.join(', ');
let avgSalary = employees
.filter(e => e.dept === 'Engineering')
.map(e => e.salary)
.reduce((sum, s) => sum + s, 0);
let count = employees.filter(e => e.dept === 'Engineering').length;
html += `<br><br><strong>Engineering Avg Salary:</strong>$${(avgSalary / count).toFixed(0)}`;
let allAbove3k = employees.every(e => e.salary > 3000);
let has12k = employees.some(e => e.salary >= 12000);
html += `<br><br><strong>All salaries > $3000?</strong>${allAbove3k ? 'Yes' : 'No'}`;
html += `<br><strong>Anyone earns ≥ $12000?</strong>${has12k ? 'Yes' : 'No'}`;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
Example: Spread Operator and Destructuring
<!DOCTYPE html>
<html>
<body>
<h2>Spread Operator & Destructuring</h2>
<div id="output"></div>
<script>
let a = [1, 2, 3];
let b = [...a];
b.push(4);
let html = `<strong>Copying with Spread:</strong><br>`;
html += `Original array a: [${a}]<br>`;
html += `Copy b: [${b}]<br>`;
html += `Modifying b does not affect a<br><br>`;
let x = [1, 2], y = [3, 4];
let merged = [...x, ...y, 5];
html += `<strong>Merged Array:</strong>[${merged}]<br><br>`;
let [first, second, ...rest] = [10, 20, 30, 40, 50];
html += `<strong>Destructuring:</strong><br>`;
html += `first = ${first}<br>`;
html += `second = ${second}<br>`;
html += `rest = [${rest}]<br><br>`;
let scores = [85, 92, 78, 95, 60];
let [highest, ...others] = [...scores].sort((a, b) => b - a);
html += `<strong>Destructuring + Sort:</strong><br>`;
html += `Highest = ${highest}<br>`;
html += `Others = [${others}]`;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
📖 Summary
maptransforms each element into a new array,filterkeeps matching elements,reduceaccumulates into a single valuefindreturns the first matching element,findIndexreturns the first matching indexsortdefaults to string ordering — for numbers, always pass a comparator:(a, b) => a - bsomechecks if any element matches,everychecks if all elements match- The spread operator
...copies and merges arrays; destructuring extracts elements into variables - Higher-order methods return new arrays and can be chained for concise, readable code
❓ FAQ
map and forEach?map returns a new array; forEach returns undefined. Use map when you need the result, forEach when you just want to perform an action. Don't manually push inside forEach — that's what map is for.sort modify the original array?sort is an in-place operation — it rearranges elements rather than returning a new array. To preserve the original, copy first: [...arr].sort(...).reduce?📝 Exercises
- Given the array
[3, 8, 12, 5, 9, 17, 4], usefilterto keep numbers greater than 7, thenmapto double them. Output the result. - Use
reduceto count occurrences of each word in an array like['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']→{ apple: 3, banana: 2, cherry: 1 }. - Given an array of students (with
nameandscore), use chaining to: filter passing students → sort by score descending → extract names into a new array. Display the result on the page.



