Javascript: фрактал отсоса

в 21:01, , рубрики: javascript, nodejs, веб-дизайн, Веб-разработка, Программирование, метки: ,

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

     Когда я пытался решить проблемы минимализма при помощи библиотек, это порождало новые проблемы — с библиотеками. Когда я пытался решить проблемы с библиотеками, это порождало проблемы с программистами. Когда я выслушивал достаточно о своей тупости от программистов, я принимался глубже изучать язык. И новые проблемы открывались передо мной. В итоге, с ростом опыта, я пришел к необходимости использовать те инструменты, которые дает экосистема Javascript. И они тоже создавали новые проблемы, решая старые. И все это напоминает даже не фрактал, а какой-то уродливый лабиринт плохого дизайна, из которого нельзя выбраться.

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

Почему проблема все же есть?

     Javascript целиком и полностью повторяет историю Perl, который в свое время испытывал аналогичный взлет и почти такие же проблемы, я бы даже сказал, что Javascript — это злая пародия на Perl 15-20 лет спустя.

     Perl изначально не был языком созданным для веб-программирования, особенно для сложных веб-приложений. Так же и Javascript — он проектировался для создания простой интерактивности страничек, а потом на его плечи обрушилась вся тяжесть клиент-сайда. Perl обладал недостатками реализации ООП на том же уровне как и Javascript — ООП было, но весьма своеобразное, и многим оно было не по душе. И было(и есть!) много попыток реализовать ООП через сторонние библиотеки. Как и в Javascript. Были еще в Perl и хваленые замыкания, на которые тогда всем было почему-то наплевать.

     Когда в 90-е и нулевые все ломанулись писать на сайты на Perl, то квалификация у многих веб-программистов была не самой высокой. В веб переходили студенты, сишники, а то и вообще те, кто попался по руку работодателю. Сейчас в Javascript ломятся дизайнеры, верстальщики и, конечно же, студенты. Оба языка позволяют большие вольности в плане оформления кода и применения сомнительных конструкций. Перловики тогда(да чего греха таить — и сейчас) гордились сложностью и свободой своего языка, выписывая мозголомные конструкции, а также клеймя всех попавшихся под руку программистов на других языках окаянными нубами и недопрограммистами. Javascript-програмисты сейчас горд… а, впрочем, мне лень переписывать предыдущее предложение в настоящем времени.

     У обоих языков изначально была четко обозначенная область применения, из которой они со временем вылезали, получали линейкой по рукам и заползали обратно. Оба обзавелись своими пакетными менеджерами, и если Perl уже прошел стадию, когда доверять качеству модулей CPAN было опасно, то npm еще только в нее входит.

     Perl положил начало PHP, первая версия которого была написана на самом Perl. Таким образом была сделана попытка побороть излишнюю сложность Perl для веб-программирования. И, аналогичным образом, мы можем наблюдать, как сегодня появляется все больше языков на замену Javascript, претендующих на его область применения и устраняющих его недостатки. Это Dart, CoffeeScript и наверняка другие.

Начало конца

     Если вам лень читать все до конца, то главная проблема Javascript формулируется фразой «область применения языка выдвинула к нему требования, которые он не в состоянии удовлетворить». И проблема эта зародилась еще в момент создания языка:

JS был обязан «выглядеть как Java», только поменьше, быть эдаким младшим братом-тупицей для Java. Кроме того, ондолжен был быть написан за 10 дней, а иначе мы бы имели что-то похуже JS.

     Дело было в мае 1995 года, и ничто не предвещало беды. К сожалению, последний, кто знал, что станет с инфраструктурой web спустя аж 15 лет после создания Javascript, вознесся на небо около 2000 лет назад. Хотя злые языки говорят, что знай он во что превратятся веб-приложения сегодня, то и не вознесся бы.

     Между тем, нездоровая хайповость, от которой мы так страдаем сейчас, была заложена в язык уже в момент его создания. Слово Java присутствует в названии не просто так, а потому что одноименный язык в то время стремительно набирал популярность. Пропиарить новоиспеченного ублюдка таким образом удалось настолько хорошо, что до сих пор(хотя и гораздо реже, чем 10 лет назад) можно встретить начинающих программистов путающих эти 2 языка. Далекие же от программирования заказчики, не будут видеть между ними разницы никогда. Just as Planed.

     Отбросив возню с именами, замечу, что первое время Javascript был очень даже неплох, и период моих наибольших симпатий к нему приходился на то время, когда появился jQuery, но не появился nodejs, а так же не набрали популярность фреймворки типа Angular и Knockout. Период достаточно размытый, но по нему достаточно четко прослеживается то время, когда основные проблемы Javascript связанные с кроссбраузерностью были решены, а проблемы производительности и выразительности языка еще не встали в полный рост. jQeury позволяла без головной боли делать то, для чего Javascript изначально и предназначался — создавать интерактивные страницы и делать красивости.

     И вот, окрыленные успехами, разработчики решили, что на Javascript можно писать и тяжелые client-side приложения. Тогда-то и вскрылась большая часть проблем языка, выискивать которые даже человеку далекому от данной области не так сложно — обилие модулей для Javascript в репозиториях вроде bower является живым путеводителем по проблемам языка. Дело в том, что большинство языков библиотеками расширяются, а в Javascript широко представлен класс библиотек, и даже целых технологий, для решения проблем самого языка.

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

     Чтобы понять проблему еще глубже, давайте посмотрим в сторону PHP — обладая колоссальным числом недостатков, начинавшийся как интерпретатор без ООП вовсе, этот язык за последние 10 лет прошел колоссальный путь. В нем появились пространства имен, реализация ООП по уровню сравнимая с Java, автоподгрузка классов. Объема же введенного в язык синтаксического сахара хватит, чтобы подвергнуть сахарно-диабетному геноциду среднюю web-студию. В то же время Javascript топтался на месте: изменения не коснулись тех проблем, которые уже тогда вставали перед языком. Прототипное ООП вместо ООП никуда не делось, а поддержка модулей ниоткуда не появилась. Все это было дано на откуп библиотекам.

     Сейчас на горизонте маячит ECMA-6, который наконец таки добавит модули в стандарт языка. Но лишь модули как синтаксические единицы! Проблема автоподгрузки согласно именованию, а также проблема управления зависимостями так решены и не будут. Еще добавят привычную многим поддержку ООП, правда без приватных членов классов. Однако даже в случае выхода стандарта, его внедрение в повседневную практику — дело не одного дня. Вероятность того, что эти изменения уже опоздали очень велика, мне кажется сообщество скорее будет по привычке использовать require.js и его аналоги. Так же вышло и с хвалеными итераторами и генераторами, которые использует полтора эстета. Так будет просто потому, что привыкли, потому, что поддержка ecma-6 будет отсутствовать во многих пусть не самых современных, но очень распространенных браузерах. Зато в стандарте появится новый синтаксис для описания функций! Разве не это — то, о чем мы так мечтали, чего нам так не хватало все эти годы?

     Субъективно вся история развития Javascript видится мне как перетягивание на себя одеяла стандартов разными разработчиками браузеров. Несовместимость getElementBy* в IE и Firefox ранних версий наверняка памятна многим, технология E4X, которая прожила много лет в рамках продуктов Mozilla. Наверное таких примеров было гораздо больше, но мне как неспециалисту они неизвестны. Но мысль о том, что HTML5 не одинаково хорошо поддерживается всеми браузерами, витает в воздухе.

Перед тем как читать дальше

     Итак, вы — программист на Javascript. Тогда, скорее всего, во время чтения нижеследующего текста у вас будет перманентное желание воскликнуть: «Святые угодники, да выучи же ты наконец язык, на котором пишешь! И это программисты?!» Чисто формально программист должен знать тот язык на котором он пишет, это логично. Но никакая логика не заменит факты — а факты таковы, что огромный процент программистов, использует Javascript весьма эпизодически. Или часто, но не настолько часто, чтобы набить себе шишки обо все грабли языка, научившись обходить их.

     Можно бесконечно брызгать слюной и кричать о том, что хороший программист всегда должен развиваться, что выучить новый язык для хорошего программиста — плевое дело. Но позвольте! Cреди тех языков, что представлены в индустрии веб-разработки едва ли найдется какой-нибудь, программист на котором, выучив Javascript, найдет для себя что-то новое. При всей своей распространенности, Javascript выразительно беден, а его распиаренные фичи либо не новы, либо не находят широкого применения в других языках. То же ООП, построенное на прототипах, подозрительно напоминает Monkey Patching из других языков, и по каким-то причинам там не используется.

     Финансовая мотивация для изучения Javascript тоже весьма сомнительна. Мне, перловику с Mojlocious, вот этому питонщику с Django, команде рубистов с RoR, роте PHP-шников с их пачкой фреймворков, а также вооон тому взводу программистов на Java и C# — всем нам не станут платить больше от того, что мы задрочим все причуды Javascript. Если проект будет настолько сильно страдать от нашей в Javascript некомпетенции в районе клиент-сайда, то просто будет нанят фронтендщик. Или команда фронтендщиков. И это не гонор, а разделение труда. И распространенная практика, между прочим.

     Очень надеюсь, что данного пояснения будет достаточно, чтобы понять, почему столько программистов матерятся, пользуясь Javascript. И почему они не хотят его изучать досконально, при этом не являются хреновыми программистами «не способными выучить язык на котором пишут». Короче говоря, язык, который используется огромным количеством людей от случая к случаю мог бы бы доставлять и поменьше проблем.

     Далее, я клятвенно обещаю, что буду перескакивать с больной головы на здоровую и подмечать проблемы не только Javascript как языка, но и всех вещей с ним связанных. Т.е. проблемы реализации DOM в браузерах, проблемы стандартизации самих браузеров, проблемы качества библиотек, а также проблемы программистов, эти библиотеки пишущих, являются, по моему мнению, проблемами и самого языка. Потому что этот язык — де-факто стандарт для разработки на клиент сайде, и всем нам приходится плясать от того, что идет в комплекте с этим стандартом, а не только от того, что кроется за спецификацией синтаксиса.

Главная проблема Javascript — это ты

     Если в результате прочтения данного пассажа у вас возникнет чувство несогласия где-то пониже спины, то знайте, это конечно не про вас и не про вашу контору. Вы — хороший программист, вы работаете в талантливой молодой команде. Да и в конце концов мне просто могло не повезти много раз с Javascript-программистами. Такое бывает, если ошиваться по бодишопам и фрилансу. А вот тот умеренно значащий одинокий процент, который работает в серьезных компаниях, и является тем самым обликом типового Javascript-программиста, который и силен, и смел, и вообще…

     Именно яркие представители сообщества программистов на Javascript послужили последней каплей — без них эта статья наверное бы даже не появилась на свет. Но именно они к проблемам самого языка и его инфраструктуры добавляют легкий привкус шизофрении. Не у них самих, конечно, а у тех, кто сталкивается с Javascript: с одной стороны с проблемами языка, а с другой стороны со слащавыми дифирамбами очередной серебряной пуле в лице этого языка. При этом у последней стороны наблюдается некоторая слабина в логике, строящейся по формату «если что-то популярно, значит оно обладает достоинствами». Это в корне неверно, но самооценка всегда дороже, а по сему логика может быть опущена. Как и каждый кто посмеет покуситься на самооценку.

     Больше всего о прелестях Javascript, как правило, приходится слышать от фронтенд-разработчиков проходящих период профессионального становления. На обвинения в проблемах языка на фронтенде, они очень любят апеллировать к достоинствам языка на бэкенде, особенно в области написания высоконагруженных приложений. Тот интересный факт, что такие приложения эта категория программистов будет писать только в одном случае — в галлюциногенном бреду, вызванном принятием наркотических веществ, купленных на выше-чем-среднюю-по-региону зарплату, опускается. И, возможно, дело тут даже не в молодых программистах, а в зарплате(нередко превышающей суммарную зарплату родителей программиста), которая больно бьет по самооценке, из-за чего та распухает до невообразимых размеров.

     Вопреки мнению о том, что программисты — не люди, множеству людей из среды программистов также свойственно объединяться вокруг доминирующих в обществе идей. Ибо, во-первых, могут не понять и растоптать, а во-вторых, можно не понимать и топтать других. За третьим и четвертым номером следует причастность к великому и чувство локтя. Но во время дискуссий, как правило, всплывает только второй пункт. И все эти толпы программистов, пишущих на Javascript(кроме вас, конечно, дорогой читатель), будут готовы возвести вас в сан елейного дегенерата за то, что вы не разделяете их восторга перед переименованными технологиями 30-летней давности. Вам в лицо будут тыкать достоинствами языка, плевать в это же лицо за упомянутые недостатки, и в то же самое лицо с мудрым видом говорить, что эта фича не нужна(да-да, это старый добрый LORовский «не нужен»), а это можно делать по-другому. Конечно можно! Род человеческий издревле славится своей изобретательностью и приспособляемостью, и вовремя не выданный молоток гордый представитель человеческого рода заменит камнем. А самые изобретательные, при отсутствии камня, смогут забивать гвозди головой. Я поражаюсь тому, как эти люди искренне убеждены, что Javascript обладает какими-то незаменимыми фичами, которые, по их мнению, отсутствуют в других языках. Мои же попытки найти в Javascript что-то хорошее, чего бы не было в Python, Perl или Ruby, раз за разом терпят крах.

     Конечно, среди программистов Javascript есть люди, которые перешли на него после многолетнего опыта написания кода на других языках. И в основном именно они двигают этот язык вперед. Но их ничтожная доля процента по сравнению с той оравой вчерашних верстальщиков, которые и до того не были особо искушены, прилаживая хаки к разным браузерам(хоть я и искренне преклоняюсь перед верстальщиками — именно их результат всегда на виду, а требования к результату часто технически невыполнимы). Также Javascript полнится толпами веселых школьников, тщетно пытающихся(да и пытающихся ли?) обуздать синдром утенка, после первого скрипта на JS. А также он населен сотнями депрессивных студентов(остальные тысячи пошли проторенной дорогой Java), которые судорожно пытаются понять: а что же, черт возьми, востребовано на рынке? А куда деть фрилансеров, заботливо хранящих любимые сниппеты по 5 лет и более, и чья, накопленная в условиях профессиональной изоляции в течение 10 лет, самооценка просто не позволяет им не поделиться своими советами и наработками? А что делать с неиссякаемым ручейком приверженцев исключительно компилируемых языков программирования, втайне считающих всех пишущих на интерпретируемых языках — недолюдьми. Но, поддавшись напору новостей, они решают таки кинуть взгляд(нередко по причине продолжительной безработицы) на JS, и на нем же залипают.

     Среди самых ярких представителей плеяды джаваскриптеров можно отметить карьеристов, чей github изобилует форками популярных репозиториев на том самом языке. Коммиты в которые сводятся к исправлению опечаток и написанию документации. Способность данной категории программистов наводить тень на плетень, заумно рассуждая о разнице между замыканиями и лямбдами, можно сравнить лишь с их способностью жидко обгадиться на первом же самостоятельном проекте. К чести Javascript надо сказать, что таких перебежчиков было немало и во время взлета Python, Ruby, но спрос на веб-приложения будет расти еще долго, и другого хайпа такого же уровня пока не предвидится, так что тут они засядут надолго.

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

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

     Низкая квалификация ведет к незнанию стандартов, а высокая самооценка ведет к их игнорированию. Оба этих фактора в совокупности приводят к тому, что рождаются новые стандарты, субъективно наилучшие. Код-стандарт, действующий внутри компании — это хорошо, а если к нему не относятся чрезмерно фанатично, то это вообще замечательно. Но все это хорошо лишь до тех пока в код стандарте видится лишь средство унификации, а не способ сделать мир лучше. А увидеть такой способ в код-стандарте дело нелегкое — тут нужна прозорливость 18-летнего, ну никак не меньше 25-летнего. И они увидят. Нет почвы для раздора более благодатной, чем вопросы в которых нет единого правильного мнения, а значит все решит битва ЧСВ. Хватит ли этого ЧСВ в среде Javascript-программистов, которая сегодня в своей основной массе отличается молодостью и непримиримостью?

     Непримиримых борцов за совершенный код на очередном никому не нужном сайте уравновешивает множество программистов, которым в принципе плевать на язык и свою работу, им интересна своя жизнь, а не очередной крестовый поход во имя совершенного кода и лучших технологий. Часто это ребята без (профильного)образования, но им перепала возможность быстро выучиться и за неплохие деньги работать в офисе. Делают свою работу как могут, иногда хорошо, но не потому, что хотят писать совершенный код, а потому что хотят делать свое дело хорошо. В этих командах приятно работать — при наличии любого тимлида, задающего вектор, работа будет выполняться, вовремя и без скандалов. Спасибо вам ребята, что вы есть.

     Но все рушится, когда появляется один из тех программистов, которые искренне верят, что Javascript это язык на котором будут разговаривать наши дети, а код на нем должен идти из глубины души. А тем у кого душа неспособна рождать код, чистый как слеза ребенка, чьим первым словом было слово «var», тем в душу надобно плевать до полного очищения. Что доморощенные гуру Javascript и делают, неискренне упиваясь самопожертвованием от нахождения в среде таких бездарностей, и совершенно искренне гнобя эту среду. Конечно, наступление мира во всем мире при начале использования вами Javascript такими его адептами не декларируется, но подразумевается. Также ими подразумевается, что все недостатки, находимые в языке — лишь продолжение его достоинств, а если кто с этим не согласен, то это неосиляторство. Хотя единственное, в чем можно обвинить неосиляторов — недостаток веры. Боже храни вашу команду от таких. Ну или пусть он будет один, но будет тимлидом.

     К сожалению, эти же люди искренне не понимают как можно не любить Javascript, хотя из доступных им аргументов можно перечислить всего два — их субъективную любовь к языку, а также его высокую популярность, которую они ошибочно обуславливают плюсами языка, которые в свою очередь неоспоримы(см. первый аргумент). Работать с ними тяжело, потому что грань между стремлением к совершенству и ЧСВ очень тонка, а конфликты на работе неизбежны. Их же советы использовать Javascript для своих задач могут создавать стойкую иллюзию разговора с коммивояжером. Дискуссия же о недостатках Javascript доставляет мало приятного.

     Обычно после того как проходит пик популярности языка, на нем остаются только те, кому он действительно подходит, для кого он правда гармонично выписывает в работу, а всеми его недостатками можно пренебречь. Ну или те, кому лень переквалифицироваться. В разговоре с этими людьми можно спокойно упоминать недостатки языка — реакция или будет адекватная, либо будет отсутствовать вовсе. В случае JS-фанбоев даже пожаловаться на какую-то неприятную мелочь чревато агрессией в свою сторону.

     Даже если отбросить проблемы коммуникации, то перфекционизм и желание делать что-то по-настоящему хорошо на языке, в котором куча недостатков имеется by design, не приведет ни к чему хорошему. А потеря времени на борьбу с языком и основной массой программистов на нем — непродуктивна.

     Из-за всего этого даже те хорошие идеи, которые несет в себе Javascript, разбиваются о восприятие нами их носителей, которое подобны восприятию пролетариатом добра, творимого руками сексуальных меньшинств. Хочется взять и… не принять, не принять эти идеи, доносимые столь вульгарным образом. И мне очень хотелось бы поставить в пример Javascript-программистам их коллег, пишущих на PHP. Которые просто делают свою работу, которые в отличие от первых, знают о недостатках своего языка так же хорошо, как пишущие на Javascript о достоинствах своего. Когда-нибудь шумиха вокруг Javascript утихнет, сегодняшние воинствующие программисты повзрослеют или свалят на следующий модно-ново-лучший язык, а до тех пор мы имеем, что имеем.

Чисто формальные недостатки

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

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

Null, операторы сравнения и все, все, все

     При всей той напускной строгости и минимализме, которыми блещет Javascript, он не дотягивает до уровня строгости и логичности Python, при примерно таком же уровне минимализма. Зачем, например, такое количество разных значений-аналогов хрестоматийного false? Интерпретация false в вычисляемых выражениях это сплошная головная боль — проблемы приведения «пустых» значений есть в самом языке, это раз. Во-вторых львиная доля времени проводится во взаимодействием со встроенными в язык или браузер объектами, и что возвращает каждый из них можно только запомнить. В-третьих, есть еще написанные неведомо кем библиотеки.

     Что такое «пустые значения»? Это собирательное название для всех тех вариантов возвращаемого значения, когда функция не нашла ничего, вычисление невозможно, произошла ошибка и т.п. Несмотря на то, что такого термина нет, данная идиома повсеместно используется всеми программистами на всех языках. И в этом коварство Javascript, потому что он предоставляет несколько вариантов для таких значений. Можно искренне порадоваться за вас, если вы всегда знаете, когда возвращать false, null, а когда undefined. Давайте теперь вместе порадуемся и за тех, кто не знает, но не унывает и пишет библиотеки, которыми нам с вами, возможно, придется пользоваться.

     Очень многое зависит от того, что намудрил автор библиотеки. Библиотек много, качество разное, есть еще стандартные объекты, которые не всегда ведут себя логично. Какое отношение сторонние библиотеки имеют к самому Javascript? Никакого, если забыть, что до сих пор порой проще применять костыли вроде jQuery для того, чтобы ваш код работал независимо от браузера.

     Типовая сторонняя функция, в зависимости от своей логики, может возвращать одно из следующих «пустых» значений:

  false      // старый-добрый булевский false
  undefined  // значение переменной, которая не была инициализирована
  null       // а это специальное значение для переменной инициализированной null
  NaN        // выдается при ошибках арифметических операций типа 1 / 0
  {}         // совсем не NULL, а пустой объект, но часто используется авторами как "пустое значение" по недосмотру
  []         // пустой массив, типичное дело для функций возвращающих список
  Object     // объект да и объект, оставьте его в покое

     Выше было сказано, о проблемах библиотек, но далеко ходить не надо. Что из этого по вашему будет выдавать стандартный объект Date, если на вход ему передать неправильную дату? Ошибку? null? Нет — Object.

    var d = new Date("2012--12-01"); // объект будет создан без предупреждений

    d.toJSON();       // null
    d.getTime();      // NaN
    d.toString();     //'Invalid Date'
    d.toISOString()   // наконец-то бросит ошибку!

     Поскольку выше было сказано, что на Javascript пишет много кто, то нередка ситуация, когда одну и ту же функцию С-шник напишет так:

  function isEven(arg) {
    if (arg % 2 == 0)
      return 1;
    else
      return 0;
  }

     Любитель Perl выдаст

  function isEven(arg) {
    if (arg % 2 == 0)
      return 1;
    else
      return undefined;
  }

     Программист на PHP может выдать и:

  function isEven(arg) {
    if (arg % 2 == 0)
      return 1;
    else
      return null;
  }

     Тем не менее в случае такого вызова, корректно будет работать только первый вариант.

if (isEven(3) == false) {
    alert("ба, нечетное число!");
}

     И проблема не сводится к банальному заучиванию таблиц истинности Javascript. В настоящий момент любой сколько-то серьезный сайт содержит в себе гребаную кучу разномастных библиотек, начиная от гигантов типа ExtJS и заканчивая воооон тем маленьким скриптиком, который вы нашли на гитхабе человека, который, судя по остальным его тамошним проектам и дате последнего обновления скрипта, на Javascript пишет редко, давно, и, скорее всего, первый и последний раз.

     Но вернемся к обработке пустых значений. Допустим мы, отдавая дань моде, пишем некий сайт на nodejs. И решили мы сделать на нем регистрацию. Поскольку мы заботимся о безопасности, то хотим сделать длину пароля не менее 8 символов, и разрешим использовать в нем буквы в разном регистре и цифры. C Javascript это просто, ведь в язык встроены регулярные выражения:

  /^[a-zA-Z0-9]{8,}$/.test('passworD1'); // пароль подходит

     Теперь давайте представим, что пароль приходит к нам откуда-то из запроса, или из какого-то input, если речь идет о клиент-сайде. И вот так получилось, что в результате опечатки или что-то напутав вы засунули в переменную с паролем что-то не то:

  var request = {
    "user"     : "alex",
    "password" : "sdjk23h78dg2"
  };

  // опа, опечатка
  if ( /^[a-zA-Z0-9]{8,}$/.test(request["pasword"]) ) {
    save_user_to_database(request);
  } 

     И что характерно, пользователь сохранится. С пустым паролем, или только с солью, если таковая предусмотрена. Все это благодаря особенности Javascript:

  /^[a-z]{1,10}$/.test(null);      // true 
  /^[a-z]{1,10}$/.test(undefined); // true 

Строки и числа

     На эту тему сломано много копий, кому-то милее, чтобы за попытку сложения строк и чисел интерпретатор больно бил по рукам(и, наверное, это самое правильное поведение), а кто-то хочет, чтобы интерпретатор интерпретировал строки как числа когда это возможно. Что тоже, согласитесь, часто удобно, когда мы знаем, что на более высоком уровне переменная уже прошла через валидаторы, и в ней все-таки число, пусть и в строковом представлении.

     Давайте посмотрим как происходит интерпретация таких чисел в строках в разных языках:

PHP 34 32
Python ошибка ошибка
Perl 34 32
Ruby ошибка ошибка
Javascript '331' 32

     Казалось бы, простительная мелочь, но на этом прелести Javascript не заканчиваются:

1 + '33.4' == '133.4' // да мы уже увидели, что в Javascript числа приводятся к строкам при суммировании..

'33.4' + 1 == 34.4    // мы видели не все...

     В других вышеупомянутых в таблице языках закономерность интерпретации не меняется при переходе от целых к числам с плавающей точкой. Так что parseInt и parseFloat — ваши лучшие друзья. Хотя…

  // вы так, конечно, никогда не напишите, но зрелищно ведь, да?
  parseInt(null, 24) === 23 // true

Множественные аргументы

     Забудьте свои перловые и питонячьи замашки с прохождением списка списка аргументов через pop, shift, или что вы там используете.

  function lastNegative() {
    var negative = null;

    while ( arguments.length ) {
      negative = arguments.pop(); // ошибка
      if (negative < 0)
        break;
    }

    return negative;
  } 

     Несмотря на то, что локальная переменная arguments — массив неименованных аргументов функции, она не является полноценным массивом Javascript. И чтобы работать с ним привычным образом следует каким-то образом преобразовать ее в массив нормальный, класса Array. Самый частый сниппет используемый для этого имеет такой вид.

  var args = Array.prototype.slice.call(arguments);

Массивы

     Всегда тщательнейшим образом следует проверять тип и структуру возвращаемого массива, иначе после нескольких часов дебага вы можете с удивлением обнаружить, что:

[]     == true // false - пустой массив, вроде бы интуитивно понятно
[1]    == true // true  - единица, все логично - и массив непустой, и единица приводится к true
[2]    == true // false - массив непустой, значит дело в единице, которая приводится к true... 
[true] == true // false - либо мы имеем хитрое правило приведения, либо true != true

// может все дело в магической единице ?
[1 , 1]  == true // false нет...

// а если вложенный массив?
[ [1], [1] ]    == true // false
[ [ [ [1] ] ] ] == true // true

// но !
new Array()    == true // false 
new Array(1)   == true // false 
new Array(1,2) == true // false 

     Наверняка у профессионалов Javascript есть объяснение для всего этого, но проблема от этого не исчезнет. Утешает только то, что далеко не каждый гуру языка без гугла сможет объяснить почему:

  new Array([],null,undefined,null) == ",,,"; // true

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

Форматирование

     Благодаря тому, что Javascript позволяет не ставить; в конце каждой строки, вы можете написать функцию, которая, в зависимости от форматирования, будет возвращать разные значения:

  function foo() {
    return "Феанор велел остановиться, раны его были смертельны и он знал, что час его близок";
  }
 
function bar() {
  return 
    "Феанор велел остановиться, раны его были смертельны и он знал, что час его близок";
}

foo(); // возвращает текст
bar(); // возвращает undefined 

Оператор foreach

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

for (index in ARRR) {
    var value = obj[index];
    console.log(value); 
}

     А Кто-то любит использовать дедовский метод:

for (var index = 0; index < a.length; ++index) {     
    console.log(a[index]); 
}

     Для тех кто хочет умилостивить колбэчное божество есть свой вариант:

a.forEach(function(entry) {
    console.log(entry);
});

     У меня есть свой сниппет для такого цикла, а у вас? Не находите, что когда в языке есть целых 3 способа(не считая собственные foreach для каждой уважающей себя библиотеки), делать одну и ту же вещь базовую вещь, и каждому способу чего-то не хватает, то здесь что-то не так? Не находите? А это все потому, что вы пишите на Javascript. Но все же задумайтесь почему в CoffeeScript и Dart таки поддерживается итерация по значению списка:

# dart
for (var x in collection) {   
    print(x); 
}

# coffeescript
for x in collection
    print(x)

И это не все

     Если вы хотите увидеть больше возможностей Javascript, то добро пожаловать на wtfjs.com. Только возвращайтесь.

Javascript как часть целого

Хайп

     И хайп этот будет длинным, потому что веб-приложения нужны всем, и потому, что реальной альтернативы нет. Потому, что альтернативы вроде Dart и CoffeeScript при своих плюсах не имеют того пула программистов, который бы удовлетворил потребности отрасли в сфере программирования на клиент-сайде. В довершение ко всему есть куча легаси кода, которая никуда не денется.

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

Инструментарий

     Низкий уровень программистов ведет к тому, что рабочие инструменты для большинства — это браузер и firebug. И в этом тоже проблема Javascript — все инструменты для него требуют nodeJS, что в принципе логично. А вот установка же nodeJS подчас является головной болью даже на unix-системах(в немалой роли благодаря хостерам, которые предпочитают не обновлять шаблоны VPS без крайней необходимости). На Windows ситуация в последние пару лет кардинально улучшилась, и node и npm можно поставить даже без установки Cygwin. Но установка остальных расширений под Windows — это минное поле, на котором можно подорваться даже при правильно настроенном Cygwin. Поэтому большой процент фронтендщиков игнорирует современные достижения в области Javascript, спасая себя от лишней головной боли.

     В общем, не так много джаваскриптеров могут настроить ноду, и установить все необходимые модули к своему проекту, как может показаться по тону заявлений в интернете. Выдача образов виртуальных машин с рабочим окружением, чтобы каждый сотрудник не настраивал все по новой и не тратил время на ненужную рутину, является нормальной практикой во многих компаниях. Но проблема в том, что среди тех же питонщиков и перловиков, не говоря уже о программистах на PHP, относительный процент тех, кто может развернуть тяжелое рабочее окружение, несравнимо выше того же процента среди Javascript-программистов. И даже среди того процента, который может есть мнение, что инструменты могли бы быть и получше.

     Радикального улучшения качества инструментов врядли стоит ожидать в ближайшее время — Google не заинтересован делать такое вливание ресурсов в инфраструктуру Javascript, какое было сделано для развития движка V8. Сообщество предпочитает пилить свои велосипеды, а не приделывать колеса к уже существующим, так что если оно и сможет довести связку nodejs + npm до уровня CPAN, то это будет не скоро.

Асинхронность

     Если программист считает, что асинхронность сделает его код быстрее, то либо он профессионал, который занимается очень специфичными алгоритмами, либо он не совсем понимает о чем речь. Или же он сторонник формальной правоты в ущерб здравому смыслу. В вебе, особенно в некрупных и средних проектах параллелить особо нечего, да и в крупных уже прижилось хитрое кэширование для тяжелых запросов или кусков контента. Ну и треды там всякие…

     Нельзя сказать, что асинхронный подход к обработке данных бессмысленен в принципе. В случае генерации какой-то тяжелой аналитики, отчетов, которые оперируют многими не связанными друг с другом параметрами, использование колбэков может дать огромный выигрыш в производительности. Без потоков и сложностей расшаривания данных между потоками. Это правда офигенно. Так в чем же проблема? Да в том, что количество таких выигрышных ситуаций исчезающе мало.

     Программируя какую-то бизнес логику, мы пишем алгоритмы, а в определении слова «алгоритм» сказано, что это «набор инструкций, описывающих порядок действий исполнителя для достижения результата решения задачи за конечное число действий». Порядок! Данные должны обрабатываться в определенном порядке! Вы не сможете, например, получить из базы данных интернет-магазина всех покупателей определенных товаров, если входной параметр вашего алгоритма — название категории товаров, для которой вам нужно посчитать статистику. Сперва вы должны получить категорию по имени, потом товары в данной категории, потом список покупателей. Можно в нашем примере завернуть это в три колбэка подряд, получив нулевой выигрыш в производительности и значительный выигрыш в нечитаемости кода. Отдельной статьей идет обработка ошибок в таких асинхронно-сборочных алгоритмах, особенно если отображение страницы зависит от того, какой именно колбэк упал.

     Пример с интернет-магазином простой, но 95% веба состоит именно из этой простоты. Да и вообще как вы себе представляете раскручивание колбэчных цепочек в сложной бизнес логике? Там и без того обычно у многих проблемы с пониманием того вороха абстракций, который накидали в систему за годы выполнения противоречивых требований. Я даже не уверен, что IDE будет по силам строить графы вызовов в такой логике — порядок выполнения будет виден только в рантайме. Конечно, есть места, когда параллелить обработку данных путем раскидывания по асинхронно запускаемым обработчикам можно и нужно. И этих мест исчезающе мало. Гораздо меньше, чем может показаться любителям ноды. А вот накладных расходов связанных с поддержкой такого асинхронного кода — много.

     Кстати, данный подход подозрительно напоминает старые-добрые треды, которые если не в PHP, то уже в Perl и Python были доступны еще во времена web 1.0. И нельзя сказать, чтобы они активно использовались, что тогда, что сейчас. Да, треды в питоне славны медлительностью из-за GIL, но позвольте, разве сама nodejs не ограничена одним ядром процессора в рамках текущего процесса? Да синтаксис создания тредов порой не так лаконичен, как колбэки, но последние тоже не улучшают читаемость, особенно начиная со второго уровня вложенности. А у вас будет второй уровень вложенности, потому что весь ввод-вывод асинхронный.

     Почему-то параллелизм в рамках одного процесса не прижился широко в веб-разработке. Накладные расходы на создание тредов? Но ведь число создаваемых тредов для нужд генерации веб-страницы(по аналогии с коллбэками) невелико. И даже если предположить, что колбэки являются на порядок быстрее тредов, то переписывание алгоритмов с учетом первых часто является экономией на спичках, и при этом неудобно «размазывает» получившийся алгоритм по коду. И что характерно, многих это не устраивает, а потому они пишут свои костыли для борьбы с особенностями асинхронного программирования. Та асинхронность, которую способна выдать нода — очень, очень, очень специализированная штука. Примерно как проктолог-иллюзионист, способный фокусами развлекать пациента во время нелицеприятной процедуры, и думающий что мастерство фокусника может восполнить его пробелы в медицинском образовании.

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

     Изначально асинхронность в Javascript была следствием области его применения — неблокирующие обработчики для пользовательского интерфейса. С не тяжелыми вычислительными алгоритмами. И смысл такой модели асинхронности был не в том, чтобы что-то ускорить, а в том, чтобы не дать скрипту возможности заблокировать браузер, пока будет происходить ожидание события или завершения подгрузки чего-то с сервера. Философия nodejs, гласящая, что нужно экономить в первую очередь на вводе-выводе появилась примерно 10 лет спустя после появления самого Javascript, но есть подозрение, что упор на колбэки был сделан в связи с тем что реализовать поточную модель параллелизма в рамках архитектуры интерпретаторов Javascript было бы невозможно. А вот колбэки в языке были. Поэтому асинхронность ноды — не дар свыше, а один большой компромисс, чтобы все не было совсем уж плохо.

     Таким образом выходит, что вся хваленная асинхронность Javascript в браузере является обычным event loop, который реализован в десятках графических тулкитов. А на сервере она является следствием проблем, вызванных портированием этого event loop на сервер. И при ближайшем рассмотрении за всеми красивыми речами о том, какое классное и полезное это асинхронное программирование, неизменно проступает гнилое колбэчье нутро.

С костылями по жизни

     Весь стэк технологий, который крутится вокруг Javascript, подозрительно напоминает пародию на идеологию UNIX: куча мелких программ, которые максимально хреново делают свою работу, порой дублируя друг друга. У нас есть несколько замечательных бразуеров, каждый из которых хорош по своему — какой-то тормозит, какой-то отказывается поддерживать редирект путем:

location.href = 'http://habrahabr.ru/';

     А какой-то имеет несколько разных и весьма широко используемых версий, о несовместимости которых с остальными ходят легенды. У всех этих браузеров, конечно же, варьируется и степень поддержки HTML5, этого сборища компонентов, призванного исправить недостатки Flash и заменить их своими недостатками. Скорость работы всего этого зоопарка, даже в случае если вы используете только поддерживаемое всеми браузерами подмножество фич, будет давать такой разброс, что пользователи Firefox или IE будут наслаждаться слайд-шоу, пока пользователь Chrome будет выжимать все соки из своего компьютера, проходя простенькую пиксельную аркаду, вроде тех, которые были столь распространены на игровых консолях в 80-х и 90-х годах. Мне кажется, что сейчас даже растет поколение Chrome-only сайтов, как в свое время были сайты, заточенные исключительно под IE. Или не заточенные, а недосмотренные до такой степени, что работают нормально только под одним браузером.

     Даже то, единственно хорошее на мой взгляд, что есть в Javascript, хваленая скорость ноды — и это результат тысяч угробленных человеко-часов на то, чтобы браузер не тормозил, когда Васин сайт бросит ему вызов всеми своими кривонаписанными скриптами. Ну или хотя бы тормозил не так сильно, когда в соседней вкладке будет работать Twitter. Это отчаянная попытка сделать веб-приложения хоть сколько-то лучше. И эта попытка была не одна — asm.js также был одной из стратегий увеличения производительности Javascript.

     Описание проблем HTML5 находится слишком далеко за пределами темы этой статьи, и наверняка достойно статьи отдельной. Надеюсь, что ее напишут те, кто пытался создать на HTML5 что-то тяжелое, или писать с использованием этой технологии игры для мобильных платформ. Просто скажу, что наличие большого числа слабосвязанных компонентов, разных техник написания игр, разных подходов к программированию на Javascript, отсутствие ориентированности технологии HTML5 на графику, а не на набор компонентов, единственный event-loop для всех HTML5 баннеров, игр, приложений, разная степень поддержки браузерами, разная скорость работы в браузерах — все это ставит под сомнение преимущества технологии HTML5 + Javascript перед Flash. И с точки зрения качества игр, и с точки зрения удобства их разработки. Даже профессиональным IDE придется сделать большой шаг навстречу разработчикам игр на HTML5.

Как будто бы все есть

     Что больше всего раздражает в Javascript, так это иллюзия того, что перед вами полноценный язык типа Java или Python. На бумаге есть все — встроенные в язык регулярные выражения, реализация ООП, пусть и альтернативная, как любят повторять адепты языка. И асинхронность есть — ею все уши прожужжали, а по факту все это выливается в бесконечное хождение по мукам да лихую пляску на костылях.

     К самому языку докопаться к слову почти негде — настолько мала его доля во всем стэке технологий. Тот же DOM отдан на откуп браузерами, весь ввод-вывод отдан библиотекам, модули и человеческая поддержка ООП реализуется ими же. И куда ни глянь, в какую область применения не кинь взгляд, тут же откуда слышится шепоток восторженного JS-боя, о том, что и для этого у них есть библиотека. Когда библиотеки используются для того, чтобы использовать какой-то нестандартный или специализированный функционал — это нормально, когда библиотеки используются для расширения языка общего назначения, это тоже нормально — Boost для С++ отличный пример(если не брать в расчет его монструозность), а вот когда библиотеки используются для узкоспециализированного языка, причем не расширяя его функционал, а просто скрывая его недостатки, то это заставляет задуматься.

     Взять тот же jQuery, его применение настолько широко, что среди остальных библиотек в Google CDN, процент его загрузок составляет 89%. Я и все мои знакомые программисты используют jQuery по той причине, что уже напоролись на особенности работы с DOM в ранних версиях браузеров. Сейчас все конечно лучше, но от греха подальше все равно используем. У Javascript есть куча библиотек, чтобы побороть асинхронность, якобы величайшую фичу ноды, но в сообществе бытует мнение, что вы все равно в конечно итоге напишите свою — которая подходит под ваши цели. Еще у нас есть несметное количество разных лоадеров. Все они, вместе с нотацией AMD, подчеркивающей то, что в Javascript нет модулей, недвусмысленно намекают на то, что модули нужны, но их нет. А потому каждый напишет свою реализацию. Казалось бы, нужная вещь, но хотя бы такого мы не дождемся никогда:

  window.addLibraryPath("/js/vendor");
  var $ = window.loadLibrary("JQuery");
  window.loadLibrary("DataTables");

     Потому что асинхронность, которая не дает привычно подгружать модули в нужном порядке(я рад за тех, кому нравится require(["/a/ab/ac",«b/ad/vr»]); ), потому что это опять изменения самого языка, которые дойдут до всех браузеров медленно и по-разному, потому что даже когда requirejs и AMD становятся де-факто стандартом для реализации модулей, огромное число библиотек не могут с ним работать, и приходится писать обертки. И это закономерная проблема, если модули учатся не в момент изучения языка, а спустя месяцы, а то и годы, когда программист дорастает до больших приложений. И то, дорастает с какой-то своей стороны, имея уже свои сформировавшиеся требования к тому как должны выглядеть модули.

     Пробежавшись по репозиториям npm, вы можете подумать что у вас есть превеликое множество библиотек для Javascript. И да, и нет — их правда много, но качество, наличие багов, проблемы со сборкой под разные платформы заставят вас подумать еще раз. В любом сколько-то развитом проекте вы неизбежно столкнетесь с этими проблемами. Репозитории любого языка в период взлета его популярности(мне кажется даже Haskell не в силах избежать этого) — это одни большие помойки. Огромное число налетающих на популярность программистов пытается втулить туда свои библиотеки, которые нужны полуторам другим программистам. Вещи, которые нужны всем, как правило пишутся медленно, неохотно, баги закрываются годами и уже больше силами сообщества. Это надо прочувствовать — как тряслись руки во время установки очередного модуля из CPAN в 2005, или из PyPI в 2008, и как сегодня это стало беспроблемной рутиной даже под Windows. Во всяком случае для большей части модулей. И Javascript пройдет тот же долгий путь, что и другие языки, прежде чем за замечание о том, что для nodejs уже реализован такой-то функционал, вам перестанет хотеться дать говорящему звонкую пощечину.

Неправильное проецирование

     Самые лучшие всегда на слуху, это касается людей и технологий, и конечно проектов, соединяющих их обоих. Интернет наполнен историями успеха про то, как nodejs позволил реализовать проект с использованием гораздо меньшего количества серверов, чем требовал бы такой же проект написанный на Java. Там также можно прочитать о том, что использование Javascript как единого языка для фронтенда и бэкенда позволило сократить количество разработчиков, а еще уменьшило дублирование кода.

     О чем вам не расскажут такие суперстары, так это о том, что их проект требовал весьма специфичных алгоритмов, которые 90% веб-сайтов нужны как собаке боковой карман с карманным справочником по Javascript. Хотя нет, они как раз таки это говорят, но на фоне остального повествования эта досадная мелочь пролетает мимо перегруженного восторгом мозга «стремящегося» программиста. Также этот «стремящийся» веб-разработчик никогда не узнает какой ценой пришлось заплатить за уменьшение количества кода, и что из себя представляет архитектура выстрелившего проекта. А чудес не бывает — чем в большем числе окружений вам нужно заставить работать ваш код, тем больше усилий вы на это потратите. Еще суперстары никогда не расскажут вам о том несметном количестве человеко-часов, которое было похерено на устранение проблем с незрелой технологией. Проблем настолько смешных, что о них стыдно писать, а то могут бросить тень на технологию, или на самого программиста.

     Хоть это и видно из статей, далеко не все читатели осознают, что речь идет о каком-то почти уникальном, штучном проекте, часто высоконагруженном, очень часто не имеющим ничего общего с тем, что в течение всей своей жизни пишет средний веб-программист. Средний в смысле характера проекта, а не способностей. Backbone, Angular, Knockout, все это уже кажется таким обыденным, доступным уже сегодня. Но какова их область применения? Так ли много сайтов вы видите вокруг с их использованием? А сколько сайтов, по-вашему, должны представлять из себя одностраничные веб-приложения? А сколько сайтов нуждаются в выносе всей логики на клиент сайд, превращая серверное приложение в API к базе данных?

     Такие приложения конечно есть, но обычно, чтобы заставить их работать так, как видится в рекламных статьях, их приходится вылизывать долго и большой командой. Код при этом обрастает такими костылями, что даже большой команды может не хватить и понадобится большая команда сеньоров. Те, кто писал что-то большое на том же Angular, и так все знают, вопрос лишь в том как они это восприняли — как мелкие недостатки, или же зареклись больше с ним не связываться.

     Да и мелкий веб никуда не делся. Ему все так же нужен Javascript на уровне «красивостей к сайту», ему нужен дешевый и широко распространенный хостинг, ему нужны тонны специалистов, которые могут быть легко найдены и не будут вымогать 3 стоимости сайта на PHP за аналогичный сайт на nodejs.

Скорость работы

     Я снимаю шляпу перед разработчиками nodejs, а вернее перед теми, кто писал, а главное — вылизывал сам движок V8, благодаря чему Javascript способен лихо уделать по скорости работы любой другой скриптовый язык. Он даже подбирается по скорости работы к Java. Вот что значит востребованность, вот что значит конкуренция между браузерами.

     Но при этом субъективная скорость работы сайтов, которые пытаются загнать как можно больше функционала на сторону клиента, повергает в уныние. На то есть 3 причины:

  • Кривая обвязка. Язык языком, но веб-приложения работают не в вакууме, а в браузере, где основные тяжелые операции это манипуляции с DOM и подгрузка данных. Проблемы скорости подгрузки, конечно, не проблема Javascript, но веб-приложения от этого быстрее не работают. А вот скорость работы браузера решает многое.
  • Архитектура любого Javascript движка такова, что поток выполнения намертво привязан к странице: подвисает скрипт — подвисает вся страница, а порой и весь браузер. Колбэки дают лишь иллюзию многозадачности — задержка в одном колбэке блокирует все.
  • Сам язык вынуждает программистов писать синхронно, теряя производительность. Часто раскидывать алгоритм по нескольким колбэкам просто лень, или получается очень некрасиво. При этом мы помним, что квалификация значительного числа программистов на Javascript оставляет желать лучшего.

     И вот, имея самый скоростной на сегодняшний день интерпретируемый язык программирования, программисты не могут в полную силу использовать ту скорость, которую он может выдать. И отчасти эта проблема не позволяет в полной мере заменить Flash на HTML5 + Javascript. При всей дырявости Adobe Flash, при всей тормознутости Flash Player на системах отличных от Windows, при всем пренебрежении в последнее время Adobe своим детищем, при всем при этом Javascript и HTML5 не обладают некоторыми важными его плюсами. Такими как унифицированность инфраструктуры для разработки и, что здесь особенно важно, единой средой исполнения — Flash Player. Который, для игр соизмеримой сложности, на сегодняшний день показывает куда более высокий субъективный результат, нежели JS+HTML5. И хреновая скорость работы игр на HTML5 на фоне бенчмарков, которые рвут Flash в пух и прах, является для меня одним из величайших парадоксов.

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

Заключение

     Те, кто любит Javascript будут и дальше продолжать писать на нем, не взирая ни на что. А тем, кто испытывает похожие чувства, будет приятно знать, что не они одни имеют проблемы с этим языком. Сам же я надеюсь, что ввиду того, что веб-приложения — это огромная отрасль, а размер приложений растет, в браузеры будет таки встроена виртуальная машина с унифицированным байткодом, для которого будет несложно написать компилятор для любого языка. И только тогда, отбросив исторический фактор, индустрией может быть критически выбран тот язык, который подходит для потребностей современного веб-программирования лучше всего.

Автор: PerlPower

Источник


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js