Почему нельзя использовать forEach для реализации some с прерыванием?
Что проверяют
Знаете ли вы, что forEach по спецификации обходит все элементы и игнорирует возвращаемое значение колбэка, и понимаете ли, зачем вообще нужны методы с коротким замыканием.
Как отвечать
У forEach нет механизма выхода. return внутри колбэка завершает только текущий вызов и работает как continue, а break там невозможен синтаксически: это не цикл, а вызов функции для каждого элемента. Результат колбэка отбрасывается, поэтому сообщить о находке можно лишь через внешнюю переменную, и обход всё равно дойдёт до конца.
some устроен иначе: он приводит результат колбэка к булеву значению и при первом истинном прекращает обход, возвращая true. Это и есть короткое замыкание.
let found = false;
items.forEach((x) => { if (x > 3) found = true; }); // дочитает до конца
const found2 = items.some((x) => x > 3); // остановится на первом
const first = items.find((x) => x > 3); // вернёт сам элементЕсли нужен именно выход из перебора, выбор такой: some и every для булева ответа, find и findIndex для элемента, for...of с break для произвольной логики. Единственный способ прервать forEach это бросить исключение, и он плох: исключение в роли потока управления прячет настоящие ошибки.
Про цену стоит сказать честно: на коротких массивах разница неощутима, значение она имеет там, где колбэк делает тяжёлую работу или массив большой.
Где спотыкаются
Верят, что return false прерывает обход. Это привычка из старых библиотек перебора, где колбэк действительно так работал, в стандартном методе значение просто отбрасывается.
Второе: передают в forEach асинхронный колбэк и ждут последовательности. Метод промисы не ждёт, он запустит все вызовы подряд и вернёт undefined, а нужен for...of с await либо Promise.all поверх map.
Третье: заворачивают forEach в блок перехвата и бросают исключение ради выхода. Настоящий сбой внутри колбэка теперь неотличим от штатного прерывания, и отладка превращается в угадайку.