До того, как я начал изучать Javascript, у меня был довольно ограниченный опыт программирования, и большую часть времени я проводил с Ruby. Я не собираюсь приукрашивать свои чувства к JS, это не Ruby; ему серьезно не хватает того сладкого синтаксического сахара, к которому я привык за последние несколько месяцев.

Если оставить в стороне резкие слова, в Javascript есть несколько действительно крутых функций, с которыми я не сталкивался, изучая Ruby, и легче проводить ассоциации с уже известными мне концепциями, чем изучать совершенно новые. Одной из самых интересных концепций, с которыми я столкнулся, были замыкания и обратные вызовы.

Перезвони мне, может быть

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

Чтобы сделать то же самое с помощью JS, мы можем использовать ряд итераторов или функцию более высокого уровня в «классе» Array.prototype, такую ​​как Array.prototype.forEach или Array.prototype.map, которая принимает функцию обратного вызова.

Обратные вызовы похожи на блоки в Ruby, но на них можно ссылаться, а не помещать непосредственно в блок. Давайте посмотрим на сравнение рядом:

# ruby
[].each { |element| element.methods }
// javascript
[].forEach(element => element.functions)

Редко можно увидеть код, фактически извлеченный из блока перечислителя в Ruby, однако это обычная практика с эквивалентом в Javascript. Как рубисты и объектно-ориентированные программисты, мы должны стремиться поддерживать разделение задач в наших методах, записывая небольшие, удобные в сопровождении методы в легко читаемых сегментах, которые «делают» одну вещь. Было приятно писать обратные вызовы в javascript из-за того, как легко заключить каждую функцию.

Вложения Javascript и блоки Ruby

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

Методы Ruby имеют мало общего, но блоки Ruby являются замыканиями. Так же как и процедуры (procs) и лямбда-выражения.

С Procs и Lambdas мы можем хранить блоки в переменных. Их можно создать и вызвать:

Проки ведут себя как блоки, но их можно хранить в переменных. Лямбды — это процедуры, которые ведут себя как методы. Какая разница? Процедуры, как и функции в JS, не будут выдавать ошибку ArgumentError, если в блок будет передано слишком много аргументов. Лямбда-выражения действуют как методы, в том смысле, что они выдают ошибку. Есть еще несколько технических отличий, которые не входят в тему этого поста (где-то там есть шутка о закрытии), но я уверен, что вы можете найти много литературы по этому поводу.

Теперь, когда нам удалось сохранить блок в переменной, давайте сделаем последнюю растяжку:

Это уже не совсем читабельно, но я полагаю, что это немного лучше передает намерение.

Что, если бы мы использовали Унарный & оператор?

Это больше походит на это.