JS 箭头函数在数组高阶函数 (`map`, `filter`, `reduce`) 中的简洁应用

嘿,大家好!今天咱们来聊聊 JavaScript 箭头函数,特别是它们在数组高阶函数 map, filter, 和 reduce 中的那些让人心情舒畅的应用。准备好了吗?咱们开始咯!

开场白:箭头函数,简洁的代名词

JavaScript 的箭头函数,自从 ES6 闪亮登场以来,就以其简洁的语法赢得了无数程序员的芳心。它就像一个代码界的“断舍离”大师,把冗余的部分统统砍掉,留下的只有核心逻辑。尤其是在处理数组的时候,箭头函数配合 map, filter, reduce 这三大神器,简直是效率飞升,代码颜值暴涨!

第一幕:map – 变身大法好

map 方法,顾名思义,就是“映射”。它会遍历数组中的每一个元素,并对每个元素应用一个函数,然后返回一个包含所有新元素的新数组。想象一下,你有一堆苹果,你想把它们都削皮,map 就像一个自动削苹果机,输入一堆苹果,输出一堆削好皮的苹果。

箭头函数来救场:

没有箭头函数的时候,咱们可能要这么写:

const numbers = [1, 2, 3, 4, 5];

const squaredNumbers = numbers.map(function(number) {
  return number * number;
});

console.log(squaredNumbers); // 输出: [1, 4, 9, 16, 25]

嗯,中规中矩,但是……略显臃肿。有了箭头函数,瞬间瘦身成功:

const numbers = [1, 2, 3, 4, 5];

const squaredNumbers = numbers.map(number => number * number);

console.log(squaredNumbers); // 输出: [1, 4, 9, 16, 25]

看到了吗?function 关键字没了,return 也没了,甚至连括号 () 都省略了!如果你的函数体只有一个表达式,箭头函数就能帮你省掉 return 关键字,简直是懒人福音。

更复杂的例子:

假设我们有一个对象数组,每个对象都有 nameage 属性,我们想提取所有人的名字,并放在一个新的数组里。

const people = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 35 }
];

// 使用箭头函数提取名字
const names = people.map(person => person.name);

console.log(names); // 输出: ['Alice', 'Bob', 'Charlie']

是不是感觉代码变得更加简洁易懂了?

第二幕:filter – 筛选小能手

filter 方法的作用是“过滤”。它会遍历数组中的每一个元素,并根据你提供的条件(一个返回布尔值的函数)来决定是否保留该元素。如果条件为真,则保留;否则,就过滤掉。你可以把它想象成一个筛子,只有符合条件的“沙子”才能漏下去。

箭头函数来帮忙:

还是先看看没有箭头函数的版本:

const numbers = [1, 2, 3, 4, 5, 6];

const evenNumbers = numbers.filter(function(number) {
  return number % 2 === 0;
});

console.log(evenNumbers); // 输出: [2, 4, 6]

然后是箭头函数版本:

const numbers = [1, 2, 3, 4, 5, 6];

const evenNumbers = numbers.filter(number => number % 2 === 0);

console.log(evenNumbers); // 输出: [2, 4, 6]

又是瞬间清爽!

进阶用法:

让我们回到之前的 people 数组,这次我们想筛选出所有年龄大于 28 岁的人。

const people = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 35 }
];

// 使用箭头函数筛选年龄大于 28 岁的人
const olderPeople = people.filter(person => person.age > 28);

console.log(olderPeople); // 输出: [{ name: 'Alice', age: 30 }, { name: 'Charlie', age: 35 }]

第三幕:reduce – 终极聚合者

reduce 方法的功能是“归约”或者“累积”。它会将数组中的所有元素“合并”成一个单一的值。你可以把它想象成一个搅拌机,把各种食材放进去,最终搅拌成一杯混合果汁。

reduce 接收两个参数:

  1. 一个“reducer”函数,它接收两个参数:
    • accumulator (累加器): 累积计算的结果。在第一次调用 reducer 函数时,其值等于 initialValue(如果提供了 initialValue),否则等于数组中的第一个元素。
    • currentValue (当前值): 数组中正在处理的元素。
  2. 一个可选的 initialValue (初始值): 作为 accumulator 的初始值。

箭头函数来秀一下:

首先,不用箭头函数的写法:

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce(function(accumulator, currentValue) {
  return accumulator + currentValue;
}, 0); // 0 是 initialValue

console.log(sum); // 输出: 15

然后,箭头函数版本:

const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);

console.log(sum); // 输出: 15

再次简化!

更强大的应用:

假设我们有一个商品数组,每个商品都有 nameprice 属性,我们想计算所有商品的总价。

const products = [
  { name: 'Apple', price: 1 },
  { name: 'Banana', price: 0.5 },
  { name: 'Orange', price: 0.75 }
];

// 使用箭头函数计算总价
const totalPrice = products.reduce((accumulator, product) => accumulator + product.price, 0);

console.log(totalPrice); // 输出: 2.25

实战演练:组合拳!

现在,让我们把 map, filter, 和 reduce 结合起来,看看箭头函数是如何让代码更加优雅的。

假设我们有一个数字数组,我们想:

  1. 筛选出所有大于 2 的数字。
  2. 将筛选后的数字都平方。
  3. 计算平方后的数字的总和。

没有箭头函数的传统写法:

const numbers = [1, 2, 3, 4, 5];

const filteredNumbers = numbers.filter(function(number) {
  return number > 2;
});

const squaredNumbers = filteredNumbers.map(function(number) {
  return number * number;
});

const sum = squaredNumbers.reduce(function(accumulator, currentValue) {
  return accumulator + currentValue;
}, 0);

console.log(sum); // 输出: 50

箭头函数版本:

const numbers = [1, 2, 3, 4, 5];

const sum = numbers
  .filter(number => number > 2)
  .map(number => number * number)
  .reduce((accumulator, currentValue) => accumulator + currentValue, 0);

console.log(sum); // 输出: 50

看到了吗?箭头函数让整个过程变得像流水线一样清晰流畅!代码可读性大大提高。

各种情况下的写法总结:

为了方便大家查阅,我把箭头函数在 map, filter, reduce 中的常见写法总结成一个表格:

函数 语法 示例
map array.map(element => expression) const numbers = [1, 2, 3]; const squares = numbers.map(number => number * number); // squares: [1, 4, 9]
map array.map((element, index) => expression) const numbers = [1, 2, 3]; const indexedSquares = numbers.map((number, index) => number * number + index); // indexedSquares: [1, 5, 11]
map array.map((element, index, array) => expression) const numbers = [1, 2, 3]; const modifiedNumbers = numbers.map((number, index, arr) => number + arr[0]); // modifiedNumbers: [2, 3, 4] // 每个元素都加上数组的第一个元素
filter array.filter(element => condition) const numbers = [1, 2, 3, 4]; const evens = numbers.filter(number => number % 2 === 0); // evens: [2, 4]
filter array.filter((element, index) => condition) const numbers = [1, 2, 3, 4]; const greaterThanIndex = numbers.filter((number, index) => number > index); // greaterThanIndex: [1, 2, 3, 4] // 筛选出大于其索引的数字
filter array.filter((element, index, array) => condition) const numbers = [1, 2, 3, 4]; const firstOccurrence = numbers.filter((number, index, arr) => arr.indexOf(number) === index); // firstOccurrence: [1, 2, 3, 4] // 筛选出首次出现的元素 (用于去重)
reduce array.reduce((accumulator, currentValue) => expression, initialValue) const numbers = [1, 2, 3]; const sum = numbers.reduce((acc, num) => acc + num, 0); // sum: 6
reduce array.reduce((accumulator, currentValue, currentIndex) => expression, initialValue) const numbers = [1, 2, 3]; const sumWithIndex = numbers.reduce((acc, num, index) => acc + num + index, 0); // sumWithIndex: 9 // 累加每个元素及其索引
reduce array.reduce((accumulator, currentValue, currentIndex, array) => expression, initialValue) const numbers = [1, 2, 3]; const concatenatedString = numbers.reduce((acc, num, index, arr) => acc + num + (index === arr.length - 1 ? "" : ", "), ""); // concatenatedString: "1, 2, 3" // 将数字数组转换为逗号分隔的字符串

注意事项:

  • this 的指向: 箭头函数没有自己的 this,它会继承外层作用域的 this。这在某些情况下非常方便,但也需要注意,避免出现意外情况。
  • 没有 arguments 对象: 箭头函数没有自己的 arguments 对象,如果你需要访问函数的所有参数,可以使用 rest 参数(...args)。
  • 不能用作构造函数: 箭头函数不能使用 new 关键字来创建实例,因为它没有自己的 thisprototype
  • 复杂逻辑: 虽然箭头函数很简洁,但如果你的函数体包含复杂的逻辑,建议还是使用传统的 function 关键字,以提高代码的可读性。
  • 代码风格: 始终保持一致的代码风格。如果你在一个项目中使用了箭头函数,尽量在所有适合的地方都使用它,以保持代码的统一性。

总结:

箭头函数是 JavaScript 中一个非常强大的特性,它能让你的代码更简洁、更易读。尤其是在配合 map, filter, 和 reduce 这些数组高阶函数使用时,效果更加明显。掌握箭头函数的使用,绝对能提升你的编程效率和代码质量!

希望今天的讲座对你有所帮助。下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注