404 Not Found

404 Not Found


nginx

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.

HTML
<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.

HTML
<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:

HTML
<script>
let nums = [1, 2, 3, 4, 5];
let sum = nums.reduce((acc, cur) => acc + cur, 0);  // 15
</script>

What the parameters mean:

💡 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

HTML
<!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>
▶ Try it Yourself

find and findIndex

If nothing is found, find returns undefined and findIndex returns -1.

HTML
<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:

HTML
<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

HTML
<!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>
▶ Try it Yourself

some and every

HTML
<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:

HTML
<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:

HTML
<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>
💡 Destructuring keeps code concise. When a function returns multiple values, wrapping them in an array and destructuring is a common pattern.

Chaining Methods

Higher-order methods return new arrays, so you can chain them one after another:

HTML
<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

HTML
<!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>
▶ Try it Yourself

Example: Spread Operator and Destructuring

HTML
<!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>
▶ Try it Yourself

📖 Summary

  1. map transforms each element into a new array, filter keeps matching elements, reduce accumulates into a single value
  2. find returns the first matching element, findIndex returns the first matching index
  3. sort defaults to string ordering — for numbers, always pass a comparator: (a, b) => a - b
  4. some checks if any element matches, every checks if all elements match
  5. The spread operator ... copies and merges arrays; destructuring extracts elements into variables
  6. Higher-order methods return new arrays and can be chained for concise, readable code

❓ FAQ

Q What's the difference between map and forEach?
A 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.
Q Why does sort modify the original array?
A It's a historical design choice. sort is an in-place operation — it rearranges elements rather than returning a new array. To preserve the original, copy first: [...arr].sort(...).
Q Can I omit the initial value in reduce?
A Yes — if omitted, the first element becomes the initial value and iteration starts from the second. But an empty array without an initial value will throw an error, so always provide one for safety.

📝 Exercises

  1. Given the array [3, 8, 12, 5, 9, 17, 4], use filter to keep numbers greater than 7, then map to double them. Output the result.
  2. Use reduce to count occurrences of each word in an array like ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']{ apple: 3, banana: 2, cherry: 1 }.
  3. Given an array of students (with name and score), use chaining to: filter passing students → sort by score descending → extract names into a new array. Display the result on the page.
100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏