Почему передача больших анонимных функций в качестве аргументов другим функциям так широко принята в JavaScript?

27

У меня есть мнение (которое, я уверен, некоторые поделятся), что передача анонимных функций, которые содержат более нескольких строк кода, в качестве аргументов для других функций сильно влияет на читабельность и самодокументирование до такой степени, что, как мне кажется, это будет гораздо лучше для любого, кто использует код для объявления именованной функции. Или, по крайней мере, присвойте эту анонимную функцию переменной, прежде чем объявить основную функцию

Однако многие библиотеки JavaScript (jQuery, d3.js / NVD3.js) просто для того, чтобы привести пару примеров, используют большие функции таким образом.

Почему это так широко распространено в JavaScript? Это культурная вещь, или есть какие-то преимущества, которые я упускаю, которые сделали бы использование более предпочтительным, чем объявление именованной функции?

Адам Копли
источник
1
Вероятно, это связано с использованием замыканий . Это также может быть связано с нежеланием показывать действительную функцию внешнему миру (именно поэтому она анонимна).
Роберт Харви
3
@RobertHarvey Другими словами, это обходной путь для JavaScript, не имеющий публичного и частного ?
Мейсон Уилер
2
Во многих местах большая анонимная функция выглядит больше как блок и, как правило, чувствует себя довольно хорошо, когда вы привыкнете к ней. Общие правила даже поддерживают ощущение блока.
5
@MasonWheeler: Это зависит от вашей точки зрения. Схема или ECMAScript программист может сказать , что publicи privateобходные пути для не имеющих надлежащего закрытия.
Йорг Миттаг
1
@ JörgWMittag Ура для Racket, официального языкового спонсора XKCD 927!
Мейсон Уилер

Ответы:

23

Три основные причины, которые я могу придумать:

  1. Доступ к родительской области
  2. Конфиденциальность
  3. Сокращение имен, определенных в более высоких областях

Доступ к родительской области: определения встроенных функций позволяют встроенному коду иметь доступ к переменным, определенным в родительских областях. Это может быть очень полезно для многих вещей и может уменьшить объем или сложность кода, если все сделано правильно.

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

Конфиденциальность: код внутри встроенного анонимного определения является более закрытым и не может быть вызван другим кодом.

Сокращение имен, определенных в более высоких областях: это наиболее важно при работе в глобальной области, но встроенное анонимное объявление не требует определять новый символ в текущей области. Поскольку Javascript изначально не требует использования пространств имен, разумно избегать определения более глобальных символов, чем это требуется минимально.


От редакции. Кажется, что это стало культурным явлением в Javascript, когда объявление чего-то анонимно встроенным почему-то считается «лучше», чем определение функции и ее вызов, даже если доступ к родительской области не используется. Я подозреваю, что это было первоначально из-за глобальной проблемы загрязнения пространства имен в Javascript, затем, возможно, из-за проблем конфиденциальности. Но теперь это превратилось в нечто культурное, и вы можете увидеть это во многих открытых частях кода (например, тех, которые вы упоминаете).

В таких языках, как C ++, большинство из них, вероятно, сочли бы нереальной практикой иметь одну гигантскую функцию, которая распространяется на многие страницы / экраны. Конечно, C ++ имеет встроенное пространство имен, не обеспечивает родительский доступ к области и имеет функции конфиденциальности, поэтому его можно полностью мотивировать удобочитаемостью / возможностью сопровождения, тогда как Javascript должен использовать выражение кода для достижения конфиденциальности и доступа к родительской области. Таким образом, JS, похоже, мотивируется в другом направлении, и это становится чем-то культурным в языке, даже когда вещи, которые мотивировали это направление, не нужны в конкретном случае.

jfriend00
источник
Поскольку разработчик C ++ недавно перешел на JS для большей части моей работы, этот ответ имеет большой смысл, особенно точка «доступа к родительской области» - он действительно способен значительно упростить ваш код. Одна нитка - C ++ обеспечивает доступ к родительской области в лямбдах C ++ 11 :) Определенно +1, хотя.
Командующий Кориандр Саламандра
8

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

Во-первых, они используются для пространств имен и определения области блоков. До недавнего времени в JavaScript отсутствовали модули или какой-либо другой механизм пространства имен, который привел к использованию анонимных функций для предоставления этих функций через шаблон модуля. Называть эти функции абсолютно бесполезно. В меньшем масштабе, из-за отсутствия в Scople блока JavaScript до недавнего времени, подобный шаблон использовался для имитации области блока; наиболее заметно в теле петель. Использование именованной функции в этом случае будет активно запутывать.

Во-вторых, и менее специфичные для JavaScript анонимные функции часто используются с функциями более высокого порядка, которые имитируют управляющие структуры. Например, eachметод jQuery . Я сомневаюсь, что вы абстрагируете каждое тело цикла или if-ответвления в функцию, если она длиннее нескольких строк. Та же самая логика применяется в этом случае.

Последняя причина заключается в том, что программирование на основе событий является распространенным явлением в JavaScript, что приводит к непреднамеренному кодированию стиля передачи продолжения . Вы делаете AJAX-вызов и регистрируете обратный вызов, который при выполнении делает еще один AJAX-вызов и регистрирует обратный вызов и т. Д. Если бы вызовы были синхронными, а не асинхронными, это была бы просто прямолинейная последовательность кода в одной лексической области , Опять же, я сомневаюсь, что вы бы абстрагировали каждые несколько строк прямого кода в функцию.

Существуют также культурные факторы, и по вышеуказанным причинам анонимные функции в JavaScript встречаются гораздо чаще, чем во многих других языках, и используются более комфортно / слабо, чем во многих других языках.

Дерек Элкинс
источник
Мои собственные, возможно, наивные структуры в кодировании C ++ иногда использовали принципы кодирования на основе событий и обратных вызовов из JavaScript через std :: function и lambdas. В моем случае это частично потому, что я делаю код пользовательского интерфейса на C ++ и не хочу выполнять операции блокировки. Мне любопытно, полезны ли практики JavaScript кому-либо, если язык хорошо их поддерживает.
Katana314