Декларация-вызов в JS

Сегодня на первой части семинара Ильи Кантора по JS присутствовал (к сожалению, на второй части не получится, буду в Москве это время). Немного поговорили о частом паттерне «объявили функцию и тут же вызвали». Используется этот приём (если кто не знаком с ДжаваСкриптом) для изоляции — в этом языке функции единственное, что может создавать зоны видимости.

Я вскользь затронул свой любимый способ — описание функции и вызов через восклицательный знак или тильду, вместо оборачивания скобками. Вообще, в JS непосредственный вызов функции сразу по месту определения возможен, только если декларация находится в контексте выражения. Для этого и нужны традиционные скобки:
(function () {
    // скобки вокруг функции говорят интерпретатору, что это выражение
})();
Вообще говоря, можно использовать любые средства, чтобы декларация стала частью выражения. Например, можно что-то прибавить к декларации. Или использовать любую унарную операцию.

Использование тильды или восклицательного знака гораздо лучше скобок по трём причинам:
!function () {
    // 
}();
Во-первых, на один байт меньше. Если таких функций много, экономия существенная. Во-вторых, скобки надо балансировать, а унарный оператор — нет.

И, в-третьих, самая главная причина. Вот такой код вызовет ошибку:
var a = 5
(function() {})()
Причём ошибку, которую найти иногда довольно трудно, да и сообщение о ней не самое дружественное: «TypeError: 5 is not a function». На самом деле, тут пропущена точка с запятой. Интерпретатор считает, что ему встретились две части выражения, между которыми пропущен какой-то знак. Эта ситуация часто встречается при автоматическом объединении двух скриптов в один.

Обычно для этого добавляют точку с запятой сразу перед такими блоками.

Но если использовать унарный оператор, то этой проблемы просто нет (поэтому, на самом деле, мы экономим два байта, ещё и точка с запятой не обязательна):
var a = 5
!function () {}()
Тут интерпретатор, встретив унарный оператор, понимает, что предыдущее выражение закончилось и началась новая конструкция.
23 апреля 2012 22:16

yahoob (инкогнито)
24 апреля 2012, 22:18

Да, недавно наткнулся на такую ошибку, искал довольно долго.
Но мне кажется использование таких приемов и не расставления точек с запятых противоречит общепринятым код стандартам. Разве нет?

Fulcrum (fulc.ru)
24 апреля 2012, 22:41

А какой смысл не использовать точки с запятой, кроме какого-нибудь спортивного программирования, где нужно уложиться в килобайт кода? И можно ли заметить разницу в размере кода в реальных ситуациях при экономии байтов? Польза от какого-нибудь сжимателя js будет гораздо больше.

Вот тут еще несколько граблей, на которые можно наступить, если не ставить точки с запятой: http://lucumr.pocoo.org/2011/2/6/automatic-semicolon-insertion/

Андрей (инкогнито)
24 апреля 2012, 23:25

Где именно то экономите 2 байта? ) JS-движки загружают в память все сырцы?

SiMM (инкогнито)
24 апреля 2012, 23:43

Офф: почему если я нажимаю ← старее http://bolknote.ru/write/236/ я имею в итоге всего две статьи?
PS: почему я не могу ответить лично автору? ;) В списке значатся варианты «всем» и трое отписавшихся.

Igor M Podlesny (poige.livejournal.com)
25 апреля 2012, 05:31

в этом языке функции единственное, что могут создавать зоны видимости.
Может «может», а не «могут»? :-)

Азат Разетдинов (razetdinov.ya.ru)
25 апреля 2012, 08:10

Похоже, ты пропустил недавнюю JS-драму с участием мэтров яваскрипта: http://jsdrama.com/

cssblast.ru (инкогнито)
25 апреля 2012, 11:17

By the way
Ограничивать видимость можно еще такой модной штукой как let
https://developer.mozilla.org/en/New_in_JavaScript_1.7#let_statement

bolk (bolknote.ru)
25 апреля 2012, 11:56, ответ предназначен Fulcrum (fulc.ru):

А какой смысл не использовать точки с запятой, кроме какого-нибудь спортивного программирования, где нужно уложиться в килобайт кода?
При аккуратном программировании лучше использовать точку с запятой. Жизнь сложнее. Иногда люди её пропускают.

bolk (bolknote.ru)
25 апреля 2012, 11:58, ответ предназначен Андрею

Где именно то экономите 2 байта? ) JS-движки загружают в память все сырцы?
В файле. Причём здесь JS-движки?

bolk (bolknote.ru)
25 апреля 2012, 11:59, ответ предназначен SiMM

Офф: почему если я нажимаю ← старее http://bolknote.ru/write/236/ я имею в итоге всего две статьи?
Либо так, либо две статьи будут на последней странице.
PS: почему я не могу ответить лично автору? ;) В списке значатся варианты «всем» и трое отписавшихся.
А зачем? Я и так всё читаю.

bolk (bolknote.ru)
25 апреля 2012, 12:00, ответ предназначен cssblast.ru

Её всё равно что нет. Кроме FF кто её ещё поддерживает?

bolk (bolknote.ru)
25 апреля 2012, 12:02, ответ предназначен Азат Разетдинов (razetdinov.ya.ru):

Похоже, ты пропустил недавнюю JS-драму с участием мэтров яваскрипта: http://jsdrama.com/
Да я как-то не слежу :) Почитаю, спасибо!

bolk (bolknote.ru)
25 апреля 2012, 12:04, ответ предназначен Fulcrum (fulc.ru):

Вот тут еще несколько граблей, на которые можно наступить, если не ставить точки с запятой: http://lucumr.pocoo.org/2011/2/6/automatic-semicolon-insertion/
Тысячи их. Смысл не в том, чтобы не ставить точку с запятой и этим экономить байт, а в том, чтобы предотвращать появление ошибки такой простой штукой. Это как в Си рекомендуется в сравнении ставить константу слева, чтобы найти ошибку сразу, если вдруг забудешь одно «равно» поставить.

maxim-zotov (инкогнито)
25 апреля 2012, 20:00, ответ предназначен bolk (bolknote.ru):

Это как в Си рекомендуется в сравнении ставить константу слева
Это дурацкая рекомендация, выворачивающая мозг. "Если 5 равно длине" - совершенный дурдом. Когда комфортная читаемость кода приносится в жертву надуманной проблеме - это зло. А надуманная потому, что на выражение "if (i=5)" компилятор (например, gcc) выдает предупреждение. Да даже если бы и не выдавал, так всё равно писать нельзя. Код должен быть логичным. В нем должно быть ясно видно то, что он делает, и чтобы его можно было читать гладко, а не спотыкаясь.

И в самом посте тоже извращения. Сэкономили один байт, поставив семантически бессмысленнейшую конструкцию. !function. Что и зачем здесь отрицается? Это форма без содержания. Это от мизантропии? "Да чтоб у вас крышу сорвало, если надумаете читать моё произведение!"

Особый шик ситуации в том, что это уродование кода оправдывается тем, что оно как бы решает другую проблему кода: отсутствие знаков препинания. "Я накосячил, забив на точки с запятой, но это может вызвать проблемы, поэтому нужно накосячить еще больше - ставить восклицательные знаки там, где они вообще не уперлись."

maxim-zotov (инкогнито)
25 апреля 2012, 20:07

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

zg (zg.livejournal.com)
25 апреля 2012, 20:46, ответ предназначен maxim-zotov

"Если 5 равно длине" - совершенный дурдом.
почему?

maxim-zotov (инкогнито)
25 апреля 2012, 21:08, ответ предназначен zg (zg.livejournal.com):

Я просто теряюсь, что тут требуется какое-то объяснение. Потому что 5 не может быть чему-то равно или не равно, оно 5 и есть, это уже значение, свойство, оно не может изменяться. Постановка вопроса "чему равно 5?" бессмысленна по сути. Это у объекта может быть какое-то свойство, у свойства не может быть объекта.

someone (инкогнито)
25 апреля 2012, 21:23, ответ предназначен maxim-zotov

Согласен с вами, очень разумно всё говорите.

bolk (bolknote.ru)
25 апреля 2012, 22:52, ответ предназначен maxim-zotov

Это дурацкая рекомендация, выворачивающая мозг. «Если 5 равно длине» — совершенный дурдом.
Вы уж ерунды-то не говорите. Если вы так читаете это конструкцию, то вы делаете ошибку. Она означает «если пять и длина равны между собой». Тем более, что в ПХП и многих других языках с автоматическим приведением типов она работает именно так.
И в самом посте тоже извращения. Сэкономили один байт, поставив семантически бессмысленнейшую конструкцию. !function. Что и зачем здесь отрицается? Это форма без содержания. Это от мизантропии? «Да чтоб у вас крышу сорвало, если надумаете читать моё произведение!»
А оборачивание скобками — форма с содержанием что ли? Пока не ввели «let» приходится изолировать функцией-выражением, выражение можно строить любым способом. Не нравится вам восклицательный знак, используйте тильду что ли.
Код должен быть логичным. В нем должно быть ясно видно то, что он делает, и чтобы его можно было читать гладко, а не спотыкаясь.
Код должен быть читаемым, а программист должен хорошо знать язык и основные его «хаки».

Yehat (инкогнито)
25 апреля 2012, 23:27

Сделаем жабаскрипт гибким, как зарытый в землю Перл.

Yehat (инкогнито)
25 апреля 2012, 23:39

Возможно, кто-то помнит эту шутку: мол, Перл гибок, как зарытый в землю шланг. Тут примерно та же фигня: красявость в ущерб читаемости. Я тоже люблю так писать, если не думаю о тех, кто будет разбираться в моём коде.

maxim-zotov (инкогнито)
25 апреля 2012, 23:55, ответ предназначен bolk (bolknote.ru):

А оборачивание скобками — форма с содержанием что ли?
У скобок только структурирующая функция, поэтому они смотрятся не так дико. Они не выполняют никакого модифицирующего действия. Тильда или восклицательный знак - абсолютно без разницы, какое именно бессмысленное отрицание применяется к выражению.

http://twitter.com/thenameisbusy (инкогнито)
26 апреля 2012, 01:46, ответ предназначен bolk (bolknote.ru):

Евгений, я думаю, что следует дополнить, может для кого и не очевидно, что такая функция будет возвращать только приведенное к булеву типу (и инвертированное) значение.

Т. е. в данном случае (из пустой функции), просто вернется "!undefined", т. е. true :-).

bolk (bolknote.ru)
26 апреля 2012, 07:53, ответ предназначен maxim-zotov

У скобок только структурирующая функция, поэтому они смотрятся не так дико. Они не выполняют никакого модифицирующего действия.
Выполняют, конечно. Они переключают контекст. Если вы имеете ввиду, что скобки смотрятся *более* *логично*, возможно, но только профессионалу должно быть всё равно, что переключает контекст, а новичку непонятны оба выражения.

Но я за то выражение, которое страхует от такой частой ошибки как отсутствующая точка с запятой.

bolk (bolknote.ru)
26 апреля 2012, 07:54, ответ предназначен Yehat

Сделаем жабаскрипт гибким, как зарытый в землю Перл.
Если вы хоть что-то знаете о прогрессе стандарта, то видите, наверное, что он становится похожим скорее на Пайтон, а не на Перл.

sergey.larionov (openid-provider.appspot.com/sergey.larionov)
26 апреля 2012, 09:57

Есть так называемые общепринятые практики, в качестве которых в джаваскрипте могут выступать и такие хаки. Тут же всё дело в том, что стандарт изменить непросто и нужно пользоваться тем, что есть.
Опытный разработчик на таких вещах не спотыкается, он видит за ним смысл. Просто найдите какой-нибудь js-код начала 2000-х и почитайте - сейчас пишут гораздо понятнее, как раз благодаря такой стандартизации со стороны самих программистов.

Кстати,сейчас мир js разбился на два лагеря - сторонники точек с запятыми и противники. В зависимости от того, кто из них победит и будет в дальнейшем определяться стандарт языка.
Противникам точек с запятыми приходится, кстати использовать особенности языка и различные хаки, чтобы у них всё работало и не слипалось при минимизации, а сторонникам приходится ставить много точек с запятыми :)

bolk (bolknote.ru)
26 апреля 2012, 10:22, ответ предназначен openid-provider.appspot.com/sergey.larionov:

Кстати,сейчас мир js разбился на два лагеря — сторонники точек с запятыми и противники.
Я — «за», кстати, за точки с запятой.

alax.myopenid.org (инкогнито)
26 апреля 2012, 16:00, ответ предназначен maxim-zotov

Это дурацкая рекомендация, выворачивающая мозг. "Если 5 равно длине" - совершенный дурдом.
Я, конечно, могу понять для чего это делается - чтобы случайно пропустив знак равенства нарваться на ошибку компилятора, но даже при этом я в этом вопросе разделяю твой взгляд. Всегда когда встречаю "if(константа = переменная" возникает небольшое чувство отвращения. Всегда ведь логически - по той логике по которой работает мозг - последующее исполнение зависит именно от значения переменной, поэтому с неё было бы логично и начать.

bolk (bolknote.ru)
26 апреля 2012, 16:03, ответ предназначен alax.myopenid.org

Да, я мне и самому не нравится. Но так безопаснее.

SiMM (инкогнито)
27 апреля 2012, 06:55, ответ предназначен bolk (bolknote.ru):

Опять офф:
> Офф: почему если я нажимаю ← старее http://bolknote.ru/write/236/ я имею в итоге всего две статьи?
Либо так, либо две статьи будут на последней странице.
Последнее мне кажется логичнее.
> PS: почему я не могу ответить лично автору? ;) В списке значатся варианты «всем» и трое отписавшихся.
А зачем? Я и так всё читаю.
А сейчас – могу (ибо автор есть в числе отписавшихся, полагаю). Это не для автора, это для других ;)

bolk (bolknote.ru)
27 апреля 2012, 13:42, ответ предназначен SiMM

Последнее мне кажется логичнее.
Совершенно не логичнее. Большинство читают последнюю страницу, им гораздо удобнее ничего не листать.
А сейчас – могу (ибо автор есть в числе отписавшихся, полагаю). Это не для автора, это для других ;)
Я подумаю на эту тему :)

SiMM (инкогнито)
28 апреля 2012, 18:04, ответ предназначен bolk (bolknote.ru):

Большинство читают последнюю страницу
Есть статистика? Не знаю, как большинство (нет статистики), но я чаще перелистываю назад, а уж до последней страницы времён динозавров доберусь врядли.

bolk (bolknote.ru)
28 апреля 2012, 18:57, ответ предназначен SiMM

Есть.

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)