Comments 36
/здесь недовольное бормотание про преждевременную оптимизацию и вредные советы/
а с for...of
?
Подозреваю, что filter+map не сильно отстает просто потому, что конструкция очень часто встречается и, видимо, очень сильно оптимизирована в V8.
в хромом reduce обогнал даже цикл.
как всегда отличился edge. в нем for...of на 65% тормознее обычного for. *рукалицо*
возможно, современные движки преобразуют подобные простые примеры в обычный цикл. или новые массивы так быстро создаются? правда, не знаю, насколько актуален массив из 3-х элементов.
const processed = characters
.reduce((acc, character) => {
return character.env === 'marvel'
? (acc.push(Object.assign({}, character, { alsoSeenIn: ['Avengers'] })), acc)
: acc;
}, [])
Все равно выходит, что на массивах подобной длины смысла использовать reduce особо нет.
Если писать reduce так как автор, то ни о какой производительности и речи не может быть. Из статьи в статью одна и та же ошибка. Вот такое решение:
reduce((arr, el) => arr.concat(...), [])
в каждой итерации reduce arr.concat создаёт НОВЫЙ МАССИВ! Это бессмысленное перекладывание байтов! Big O такого решения чудовищно! Чем больше наш arr.length, тем чудовищнее будет результат.
https://habr.com/company/ruvds/blog/422091/#comment_19064761
Шипилева на вас нет!
Нельзя сравнивать конструкции языка по скорости, за исключением тех случаев, когда уже совсем критично, но было бы странно иметь такое на фронте.
Основной прикол в том, что если не понимать каких-то фундаментальных отличий, например, что функциональный стиль по определению будет копировать весь массив в отличии от императивного, то завтра могут сделать оптимизацию и все сравнение уже будет не актуально, придется переписывать по всему проекту (ну или в узких местах).
P.S. Ещё раз повторюсь, думаю, что на фронте не должно возникать ситуаций, когда это реально критично. Может какая-то виртуальная реальность или игры, но тогда императивный стиль в помощь.
А чего так завязывать на возврат логическое ответа?!
И если так уж надо логический ответ:
console.log(!!~characters.indexOf('hulk'));
// true
console.log(!!~characters.indexOf('batman'));
// false
filter vs find
В варианте с find потерян один вариант в выборке, значит результат работы кода эквивалентен. А значит подобный пример и замена вообще неуместны.
ИМХО поиск и решение проблем там где их нет. Цель подобных примеров: смотрите у нас появились новые методы, давайте их использовать везде. Может надо просто быть объективней.
Статья ради статьи…
Цель подобных примеров: смотрите у нас появились новые методы, давайте их использовать везде
Мне показалось наоборот.
: Смотрите, у нас появился метод, который проверяет есть ли элемент в массиве! Так давайте indexOf использовать по своему назначению (для получения индекса), а includes по своему (для определения, существует ли такой элемент).
А за вот такое неявное добро
!!~
надо наказывать.
Может надо просто быть объективней.
Как раз и получается, что нужно быть объективнее, и использовать методы по их назначению, а не получать массив элементов через filter только для того, чтобы получить один элемент.
Пример с reduce и map/filter плохой.
Скажите, а вы на полном серьёзе считаете что !!~indexOf
и includes
равно-уместны в реальном коде?
Статья ради статьи…Ну вообще-то ради рекламы)
let values = [3,2,60,4];
let sum = values.reduce((s,v)=>s+v);
//sum = 69
Метод универсальный, но использование его вместо filter/map/some/find — это всё равно, что использовать indexOf вместо includes, против чего выступают в начале статьи.
forEach еще сильнее.
Я немного ошибся с формулировкой, имею ввиду правильнее. Итераций будет столько же.
const processed = [];
characters.forEach((el) => {
if(el.env === 'marvel') {
processed.push(Object.assign({}, characters[i], { alsoSeenIn: ['Avengers'] }));
}
});
но использование reduce через concat или https://habr.com/company/ruvds/blog/422091/#comment_19064761 мне кажется, как минимум не логично, т.к. код с forEach получается точно такой же, а в примере reduce используется тупо для интегрирования, с этой задачей справляется и forEach.
Когда же скорость по настоящему критична, например когда поиск происходит часто и много раз, то имеет смысл просто сразу индексировать массив и находить значения моментально. В случае когда необходимо булево значение вообще использовать Object или Set.
Случаев, когда замена indexOf на includes или filter + map на reduce принесет ощутимую пользовательскому глазу выгоду не так много, к тому же методы разработчиками браузеров постоянно допиливаются и показатели меняются. Можно вдруг обнаружить, что filter + map в ряде случаев быстрее, чем reduce, а простой перебор цикла еще быстрее. Посему для кода использовать что более удобно — например includes использовать просто логичней и красивей, когда нужно булево значение, чем indexOf !== false, а для быстрого поиска использовать индексацию.
С includes все еще есть проблема, что babel не транспайлит его во что-то более менее адекватное.
А это EcmaScript 2016. Поэтому нужно быть очень аккуратным и использовать его только там где вы уверены будет поддержка ES7 (сервер/приложение для вечнозеленых браузеров).
Если можете поясните новичку почему так acc.push(Object.assign({}, character, { alsoSeenIn: ['Avengers'] })
не работае, а вот так (acc.push(Object.assign({}, character, { alsoSeenIn: ['Avengers'] })), acc)
работает? Ведь acc
это массив, но в первом варианте выдает ошибку что push is not a function
. Заранее спасибо)
Всё просто:
// variant 1
return do1(), do2(), do3(), do4(), 5;
// variant 2
do1();
do2();
do3();
do4();
return 5;
Оба участка кода эквивалентны. Автор приведённой вами строки сэкономил символы используя "оператор запятую". Но имейте ввиду, что обычно за такой код "бьют", и никаких лишних мутных запятых в коде быть не должно.
Очередная плохая статья от RUVDS, наверное, они решили что таким способом круто продвигаться. Может у них результат и хороший от этого, но понимаю, почему не переводить интересные статьи.
По сути.
"Замена indexOf() на includes()"
Конечно, якобы второй метод лучше говорит сам за себя, но первый является общепринятым, отсюда, также понятным.
"Использование метода find() вместо метода filter()" и "Замена метода find() на метод some()"
Тут понятно, все зависит от того, что нужно сделать. Странное замечание в общем.
"Использование метода reduce() вместо комбинации методов filter() и map()"
Ну это вообще тупость, чувак явно дома забивает гвозди шуруповёртом (хотя может и шурупы им забивает).
А какая тематика интересна? И какой формат?
В общем присылайте в личку все, что вы считаете интересным для перевода. Достаточно просто ссылки на материал.
Ваши силы бы на перевод оставшийся книг You-Dont-Know-JS
Эффективное использование методов массивов в JavaScript