Что ж, поскольку статья прошлой недели имела такой успех (кстати, спасибо всем за лайки и ретвиты), я подумал, что должен продолжить с того места, где остановился!
Итак, в прошлый раз мы говорили о map
, filter
и reduce
, о том, как они работают и как выглядят за кулисами.
На этот раз мы поговорим о составлении этих функций или их объединении в цепочку.
Опять же, мы посмотрим, как это выглядит с помощью наших самодельных функций, чтобы почувствовать это, а затем сделаем это с «настоящими» функциями JS.
Коротко и мило. Хороший. Давайте взломать.
У нас был массив:
let nums = [1,2,3,4,5,6,7,8,9];
Используя наши последние функции, мы будем отображать его, добавляя по одному к каждому, фильтровать его до чисел больше 5, а затем уменьшать то, что осталось, до суммы этих значений. Ожидается в общей сложности 40. Я думаю… (быстрые расчеты, понимаете).
Вот оно:
let ourMapResults = map(nums, addOne); // [ 2, 3, 4, 5, 6, 7, 8, 9, 10 ] let ourFilterResults = filter(ourMapResults, moreThanFive); // [ 6, 7, 8, 9, 10 ] let ourReduceResults = reduce(0, ourFilterResults); // 40
Ура, и правда, ХУЗЗА.
И, как и ожидалось, это прекрасно работает. Это довольно просто.
— Итак, что такое говядина? вы можете обнаружить, что спрашиваете (вы делаете, верно?).
Во-первых, вы создаете все эти новые переменные только для того, чтобы иметь возможность передать их следующей функции в цепочке. Они не будут использоваться снова, они не будут выполнять свою жизненную цель как переменные. Или что-то. Вы бы не хотели этого для своих переменных, не так ли?
Кроме того, каждый элемент в цепочке выполняет только одно действие. Легко следить за тем, что происходит.
Кроме того, это ОЧЕНЬ простой пример. Эти цепочки могут продолжаться очень долго и могут стать очень сложными. У вас будут дополнительные переменные повсюду, ваша кодовая база будет (вероятно) намного больше, менее ремонтопригодна и намного менее понятна.
Вероятно, есть много других причин, по которым он лучше, но посмотрите — сегодня воскресное утро. Прекрати меня придирать!
В любом случае - теперь давайте поступим "настоящим" способом:
let reduceResults = nums.map(addOne) .filter(n => n > 5) .reduce((sum, num) => sum + num, 0) // 40
На что следует обратить внимание при этом:
let reduceResults = nums.map(addOne) .filter(n => n > 5) .reduce((sum, num) => sum + num, 0)
используются значения. Во-первых, это выглядит довольно странно:
let reduceResults = nums.map(addOne)
addOne
ему ничего не передается. На самом деле это просто:
let reduceResults = nums.map(eachNumber => addOne(eachNumber))
map
просматривает массив и передает каждое значение заданной функции (помните, что это всего лишь цикл for
).
Каждая функция после нее берет результат предыдущей в цепочке и вводит его:
// n = nums.map(addOne) .filter(n => n > 5) /* * It is worth noting here that the name of n can be anything. It is * generally shortened as much as possible, but this is where it is * made, you can call it what you want! */ .filter(numberOfMagicBeans => numberOfMagicBeans > 5)
Кстати, некоторые из вас могут быть знакомы с PHP и его конкатенацией точек (здесь я думаю о вас, Берт):
“this” . ” is” , “a” . “string”
Это может помочь думать о цепочке функций, чтобы они работали аналогичным образом:
"nums.map(addOne)" . "filter(n => n > 5)" . "reduce((sum, num) => sum + num, 0)"
Все, что вы на самом деле делаете с точкой, — это снова и снова обращаетесь к методам, хранящимся в объекте JS array prototype
. Помните:
nums.map(addOne) // nums is an array (array.prototype.map) thatNewArray.filter(n => n > 5) // (array.prototype.filter) newerArray.reduce((sum, num) => sum + num, 0) // (array.prototype.reduce)
Кроме того, не позволяйте стрелочным функциям ES6 сбивать вас с толку.
Они облегчают чтение таких цепочек, но следите за тем, как они связываются с this
, если у вас есть какой-либо объектно-ориентированный код.
На самом деле, все, что мы говорим, это то,
nums.filter(function (number) { return number > 5; }
filter
может показаться немного сложным из-за всех знаков равенства и угловых скобок (особенно если мы проверяли >=
, а не только >
)!
Итак, поехали. Хорошие, красиво составленные функции.
Как и раньше, вы можете попробовать это в своем собственном терминале — скопируйте и вставьте, должно работать так же.
Если у вас есть какие-либо вопросы, напишите мне.
Может быть, будет больше (если я смогу придумать тему…).