我到底如何使用地图?
这篇文章来自我的个人博客,地址在这里。
它们提前一天左右发布。真有意思。
我经常鼓励我的学生使用数组函数map
、reduce
和,filter
但他们很少能熟练使用,这真的很遗憾,因为它们就像一把装了手电筒的瑞士军刀。这三个函数或许可以帮你省去数千行最令人困惑、最容易出错的代码。让我们先从这三个函数中的“全明星”开始吧map
。
Map 是一种有趣的函数类型,它乍一看非常奇怪,就像有人剥去了你所熟悉和喜爱的 JavaScript,露出了一些古老的外星技术。
array.map(x => x * 5) // What r u even Doing tho!!!!
让我们分解这行代码只是为了获得一个基线。
首先,我想指出箭头函数x => x * 5
(如果您不熟悉箭头函数,请阅读这篇博客文章!我希望能够很好地解释它们。)
函数在这里做什么?这是回调吗?嗯……有点像……但不是。如果你愿意,可以把它想象成一个回调,因为它是一个传递了参数的函数,然后另一个函数决定它的执行……所以在某些方面,它很像一个回调。不过,它并不是一个回调,而是被称为**高阶函数*,这留待以后再写博文。
好的,好的,所以map
接受一个函数作为参数……但是为什么呢?它有什么作用?
好吧,map 只是迭代你的数组,这意味着它会逐个获取数组的每个项目并将其传递给你提供的函数。
所以如果你看到这个
const scores = [90, 80, 25, 50]
const doubleScores = sores.map(x => x * 2)
然后,你就可以确定,doubleScores
计算方法是将分数中的每个项目取整,然后进行运算x => x * 2
。那么,我们得到的结果是什么呢?
嗯,它也必须是一个数组,因为我们需要存储 4 个结果。所以我们知道doubleScores
它会是一个数组。这个数组里的内容是将其他数组的内容翻倍后的结果。
// A way to visualize what map is doing
cosnt scores = [90, 80, 25, 50]
const double = x => x * 2
const doubleScores = [ double(scores[0]),
double(scores[1]),
double(scores[2]),
double(scores[3]) ]
好的,那么 map 是做什么的?
嗯,一种解释是,它允许你接受一个只接受单个项作为参数的函数,比如上面例子中的单个数字。然后,用这个函数处理一个包含多个项的数组。哇……这就像一个口袋for loop
,每个数组都随身携带着它。
这实际上非常棒,因为这意味着我不用编写 for 循环,而是可以编写一些简单的函数来操作单个项目,然后很快就能用它们来转换项目列表。这真的很棒,因为代码中有一些冗余代码和样板代码,可能会掩盖代码的for loops
实际意图。请考虑以下代码。
const students = [ { name: 'Leroy Jenkins' grade: 55 },
{ name: 'Tommy Pickles' grade: 98 },
{ name: 'Mike Tyson' grade: 85 },
{ name: 'Donnie Darko' grade: 90 } ]
// A simple function expecting a single student, and returns true if they pass the class and fail otherwise.
const isPassing = (student) => student.grade >= 65 ? true : false
// Usage with a single student
const tommyPickles = students[1]
const didTommyPass = isPassing(tommyPickles)
// Usage with the entire list
const classResults = students.map(isPassing)
// Extra credit c-c-combo usage with filter
const onlyWinners = students.filter(isPassing) // more on this next week.
这有多巧妙?你能想象在 for 循环中尝试使用这个函数吗?它看起来会很乱,但实际上,它看起来像一行漂亮的声明。Map 赋予我们超能力!
我说它像个口袋for loop
,我是认真的,实际上任何东西都for loop
可以用 map 重写,而且通常结果会简单得多。例如,上面的代码最初写成 for 循环后看起来像这样
const scores = [90, 80, 25, 50]
const doubleScores = []
for (var i = 0; i < scores.length; i++) {
doubleScores.push(scores[i] * 2)
}
呃,什么鬼,不。把地图版本带回来const doubleScores = sores.map(x => x * 2)
哦,是的……好多了。
看出区别了吗?map 版本一行就搞定了,代码简洁多了,而且看起来酷多了……好吧,也许最后一点不太对。不过,更重要的一点是,如果你熟悉 for 循环,就很少需要写map
。其实我已经很久没写 for 循环了,以至于在写上面那个 for 循环的时候,我不得不反复查看 MDN。说实话,我现在不怎么用它们了。