Как стать автором
Обновить

Комментарии 29

Дождались, аллилуйя. После изучения скалы, мне всегда не хватало flatMap в яваскрипте.

А вам что-то мешало его допилить? Он же сравнительно несложный внутри.

менять прототайп массива — не круто, чревато проблемами в будущем.

Какими? Если не втаскивать кривых библиотек которые добавляют в прототип функции с аналогичными именами, то от расширения прототипов Function, Array, String, Number ничего страшного не произойдёт. Исключением является расширения прототипа Object — тут, действительно, не так может пойти очень многое.

Ну вот написал я свое расширение flatMap, а тут разработчики браузеров втащили кривую библиотеку с другой реализацией flatMap.


Сделать их идентичными не так просто из-за заранее неизвестных соглашений об обработке "необычных" типов.

Какими?

Например тем, что вы напишите функцию flat для бесконечной вложенности, а в стандарт войдет реализация только для первого уровня вложенности, и весь ваш код сломается после обновления браузеров.


https://developers.google.com/web/updates/2018/03/smooshgate

Так надо понимать что происходит. Если написать:
Array.prototype.flat = MyFlatFunction;

То после реализации и вхождения в стандарт — всё будет работать как и раньше, никакой код не сломается. Максимум — не будет ускоренной нативной реализации и отлетит сторонний код который положится на реализацию вошедшую в стандарт.
Но расширение прототипов — больно удобная фича чтоб её не использовать в своих проектах где целиком отвечаешь за весь код.
отлетит сторонний код который положится на реализацию вошедшую в стандарт.

Вот именно это и плохо. Если у пользователя перестанет открываться сайт, ему неважно, ваш это был код, или сторонний.

Если у пользователя перестанет открываться сайт, то такой код должен отлететь уже на этапе тестов, а в худшем случае — на стейджинг сервере. Я не призываю переопределять и даже небо и даже Аллаха, только утверждаю что это удобный функционал и на проекте где разработчики отвечают за всю кодовую базу — расширять действительно удобно.
Если у пользователя перестанет открываться сайт, то такой код должен отлететь уже на этапе тестов

Так не получится, потому что не новый код ломается, а уже существующий в проде по причине обновления браузера.

В том и дело, что за код прототипов стандартных объектов вы отвечаете примерно никак. Ладно ещё добавление, типа полифила — можно сначала проверить, что текущий браузер не имеет нативной функции, и только в этом случае запускать свою. Значительно веселее, когда со временем разработчики что-то выпиливают целиком (типа isSameNode) или, ещё хуже, ограничивают область определения.
По мне так допустимо только два способа расширения прототипов: либо явные полифилы для старых браузеров, когда стандартная спецификация уже устаканилась, либо, ну если уж очень хочется своих красивостей, то только с myvendorprefix_ (типа mycool_flatMap).
>После изучения скалы, мне всегда не хватало flatMap в яваскрипте.
Вообще-то, в вашем оригинальном пожелании нет ни слова о прототипе :)
`Array.prototype.{flat,flatMap}` to stage 4, per 2019.01.29 TC39
Можно ли добавить в статью пример практического применения?
На ряде чисел.- не понятна суть этого улучшения. В чем польза?
const persons = [...];
const maleAges = persons.flatMap(p => {
  if (p.male) return [p.age]; else return [];
})
Спасибо! Теперь все ясно. :)

Ну вот, один из моих любимых FizzBuzz-подобных вопросов испортили. :-)


С другой стороны, если кандидат знает такие новшества, это хороший признак, и всегда можно попросить написать без flat().

А в чём похожесть на FizzBuzz? В FizzBuzz проблема в том, что хочется написать «красиво», а тут как раз легко написать «красиво».

В том, что цель одинаковая: отсеять за 3 минуты тех, кто вообще не умеет программировать.


Конечно же, принимается любое корректное решение. Рекурсия или стек, reduce или цикл ручками — не суть важно.

Самого короткого варианта замены не написали:
const ar = [[1,2],[3,4],[5,6]];
ar.reduce((a,b)=>[...a,...b]);
//[1,2,3,4,5,6]
Это если вложенные элементы — гарантированно массивы, конечно. Если нет, то
ar.reduce((a, b) => [...a, ...(Array.isArray(b) ? b : [b])]);

Еще короче


[].concat(...arr)
Вообще шикарно, спасибо. Жаль только, не чейнится — в середину цепочки преобразований не вставить, только в начало.
Не советую использовать spread синтаксис. Spread (...) добавит все значения в стек и передаст как список параметров, что при больших размерах массивов (10^6) сгенерирует stack overflow исключение.
В каких единицах вы указали размер? И на каком объёме ОЗУ тестировать?
Скрытый текст
1'000'000:

10'000'000:
ФФ:

Хром:
Видимо, имелось в виду мое решение: `[].concat(...arr)`.

Оно действительно тормозит на массиве с миллионом элементов.
И правда.
Падает даже на одном миллионе
FF:

Chrome:

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории