Array.map()
Array.map() 根据传递的转换函数,更新给定数组中的每个值,并返回一个相同长度的新数组。它接受一个回调函数作为参数,用以执行转换过程。
let newArray =oldArray.map((value,index,array)=>{
...
});
一个帮助记住 map 的方法:Morph Array Piece-by-Piece(逐个改变数组) 你可以使用 map 代替 for-each 循环,来遍历并对每个值应用转换函数。这个方法适用于当你想更新数组的同时保留原始值。它不会潜在地删除任何值(filter 方法会),也不会计算出一个新的输出(就像 reduce 那样)。map 允许你逐个改变数组。一起来看一个例子:
[1,4,6,14,32,78].map(val =>val *10)
// the result is: [10, 40, 60, 140, 320, 780]
Array.filter()
当我们想要过滤数组的值到另一个数组,新数组中的每个值都通过一个特定检查,Array.filter() 这个快捷实用的方法就派上用场了。 类似搜索过滤器,filter 基于传递的参数来过滤出值。
举个例子,假定有个数字数组,想要过滤出大于 10 的值,可以这样写:
[1,4,6,14,32,78].filter(val =>val >10)
// the result is: [14, 32, 78]
但是 filter 方法,只返回真值。因此如果所有值都执行指定的检查的话,结果的长度会小于等于原始数组。
把 filter 想象成一个漏斗。部分混合物会从中穿过进入结果,而另一部分则会被留下并抛弃。
假设宠物训练学校有一个四只狗的小班,学校里的所有狗都会经过各种挑战,然后参加一个分级期末考试。我们用一个对象数组来表示这些狗狗:
const students =[
{
name:"Boops",
finalGrade:80
},
{
name:"Kitten",
finalGrade:45
},
{
name:"Taco",
finalGrade:100
},
{
name:"Lucy",
finalGrade:60
}
]
如果狗狗们的期末考试成绩高于 70 分,它们会获得一个精美的证书;反之,它们就要去重修。为了知道证书打印的数量,要写一个方法来返回通过考试的狗狗。不必写循环来遍历数组的每个对象,我们可以用 filter 简化代码!
const passingDogs = students.filter((student)=>{
return
student.finalGrade >=70
})
Array.reduce()
reduce() 方法接受一个数组作为输入值并返回一个值。这点挺有趣的。reduce 接受一个回调函数,回调函数参数包括一个累计器(数组每一段的累加值,它会像雪球一样增长),当前值,和索引。reduce 也接受一个初始值作为第二个参数:
let finalVal = oldArray.reduce((accumulator,currentValue,currentIndx
,array)=>{
...
}),initalValue;
来写一个炒菜函数和一个作料清单:
const ingredients = ['wine','tomato','onion','mushroom']
// a cooking function
const cook = (ingredient) => {
return `cooked ${ingredient}`
}
如果我们想要把这些作料做成一个调味汁(开玩笑的),用 reduce() 来归约!
const wineReduction = ingredients.reduce((sauce, item)=>{
return sauce += cook(item) +', '
},'')
// wineReduction = "cooked wine, cooked tomato, cooked onion, cooked mushroom, "
初始值(这个例子中的 '')很重要,它决定了第一个作料能够进行烹饪。这里输出的结果不太靠谱,自己炒菜时要当心。下面的例子就是我要说到的情况:
const wineReduction = ingredients.reduce((sauce, item)=>
{
return sauce += cook(item) + ', '
})
// wineReduction = "winecooked tomato, cooked onion, cooked mushroom, "
最后,确保新字符串的末尾没有额外的空白,我们可以传递索引和数组来执行转换:
const
wineReduction
=
ingredients
.
reduce
((
sauce
,
item
,
index
,
array
)
=>
{
sauce
+=
cook
(
item
)
if
(
index
<
array
.
length
-
1
)
{
sauce
+=
', '
}
return
sauce
},
''
)
// wineReduction = "cooked wine, cooked tomato, cooked onion, cooked mushroom"
可以用三目操作符、模板字符串和隐式返回,写的更简洁(一行搞定!):
const
wineReduction
=
ingredients
.
reduce
((
sauce
,
item
,
index
,
array
)
=>
{
return
(
index
<
array
.
length
-
1
)
?
sauce
+=
`${cook(item)}, `
:
sauce
+=
`${cook(item)}`
},
''
)
// wineReduction = "cooked wine, cooked tomato, cooked onion, cooked mushroom"
Array.prototype.flatMap()
flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 和 深度值1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。
语法
var new_array = arr.flatMap(function callback(currentValue[, index[, array]]) {
// 返回新数组的元素
}[, thisArg])
参数
callback 可以生成一个新数组中的元素的函数,可以传入三个参数:
currentValue 当前正在数组中处理的元素 index可选 可选的。数组中正在处理的当前元素的索引。 array可选 可选的。被调用的 map 数组 thisArg可选 可选的。执行 callback 函数时 使用的this 值。
返回值
一个新的数组,其中每个元素都是回调函数的结果,并且结构深度 depth 值为1。
示例
Map 与 flatMap
var arr1 = [1, 2, 3, 4];
arr1.map(x => [x * 2]);
// [[2], [4], [6], [8]]
arr1.flatMap(x => [x * 2]);
// [2, 4, 6, 8]
// 只会将 flatMap 中的函数返回的数组 “压平” 一层
arr1.flatMap(x => [[x * 2]]);
// [[2], [4], [6], [8]]
let arr = ["今天天气不错", "", "早上好"]
arr.map(s => s.split(""))
// [["今", "天", "天", "气", "不", "错"],[""],["早", "上", "好"]]
arr.flatMap(s => s.split(''));
// ["今", "天", "天", "气", "不", "错", "", "早", "上", "好"]
等价操作
归纳(reduce) 与 合并(concat)
var arr1 = [1, 2, 3, 4];
arr1.flatMap(x => [x * 2]);
// 等价于
arr1.reduce((acc, x) => acc.concat([x * 2]), []);
// [2, 4, 6, 8]