Во все тяжкие (Циклы в библиотеках JavaScript)

Я был достаточно удивлён, когда обнаружил несовпадения в поведении наиболее популярных библиотек JavaScript, в том, как они обрабатывают циклы each и forEach. В этой статье сравниваются:

Цикл forEach, встроенный в JavaScript

Библиотеки JavaScript важны (например, jQuery, Lo-Dash, Underscore), но в случае функциональных циклов (forEach и each) они становятся причиной путаницы (цикл for можно прервать при помощи break). Рассмотрим пример применения нативного для JavaScript метода forEach:

[1,2].forEach(function(v){
  alert(v);
  return false;
})

Этот код покажет два окошка alert. Попробуйте сами на JSFiddle.

Такое поведение вполне ожидаемо, потому как на каждой итерации мы вызываем функцию заново. В отличие от кода for (var i=0; i<arr.length; i++) {}, где нет никаких функций и итераторов.

Однако, в Lo-Dash и jQuery похожий код разрывает цикл!

Прерываемый цикл each в Lo-Dash

При использовании Lo-Dash подобный код с each вызовет только один alert:

_.each([1,2],function(v){
  alert(v);
  return false;
})

Попробуйте сами запустить этот код на JSFiddle.

Прерываемый цикл each в jQuery

У jQuery похожее поведение, следующий код вызовет только первый alert:

$.each([1,2],function(i, v){
  alert(v);
  return false;
})

Попробуйте сами на JSFiddle.

Неразрывный цикл each в Underscore.js

Чтобы всё усложнить, Underscore.js и Backbone.js остаются верными духу нативного forEach в JavaScript.

В Underscore.js each проходит по всем элементам и не прерывается:

_.each([1,2],function(v){
  alert(v);
  return false;
})

Попробуйте на JSFiddle.

Неразрывный цикл forEach в Underscore.js

Просто ради приличия я проверил также forEach() в underscore. Он, ожидаемо, ведёт себя так же, как нативный forEach(): два вызова alert!

Код с применением forEach() библиотеки Underscore:

_.forEach([1,2],function(i, v){
  alert(v);
  return false;
})

Проверьте сами на JSFiddle.

Разница между Lo-Dash и Underscore, которая может поломать ваш код

Итог этой короткой статьи: Lo-Dash не то же самое, что Underscore, при условии, что не используется особая версия, совместимая с Underscore. Спасибо Джону-Дэвиду Далтону (@jdalton), что обратил на это моё внимание:

@azat_co Всё верно, Lo-Dash не эквивалентная замена, если только не используется билд Lo-Dash.underscore.js (на него есть ссылка на главной). То же и в cdnjs. — Джон-Дэвид Далтон (@jdalton) 22 ноября 2013

P.S.: forEach в Underscore.js лучше совместим с браузерами, чем нативный forEach, потому что последний был относительно недавно добавлен в API JavaScript и не поддерживается более старыми браузерами.