Мастер сельского афоризму
0,4
рейтинг
14 марта 2014 в 01:01

Разработка → Javascript: фрактал отсоса

     Когда-то давно мне попалась статья про недостатки 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

Так что parseInt и parseFloat — ваши лучшие друзья. Хотя, лучше Number…

  // вы так, конечно, никогда не напишите, но зрелищно ведь, да?
  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
карма
168,0
рейтинг 0,4
Мастер сельского афоризму
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (307)

  • +36
    Мне немного непонятна ваша позиция: я прочитал всё, что вы написали(правда, в конце уже через строчку, ибо мысли повторяются), но так и не понял, чем вам так не угодил js? То вы сетуете на программистов-студентов, которые пишут быдлокод, то на на непривычные вам конструкции языка, то на разную реализацию стандартов, но язык-то в чём виноват? Он так же развивается и старается соответствовать запросам пользователей и программистов. Его API расширяется, появляются новые конструкции… Складывается ощущение, что язык работает просто «не так, как вы привыкли», и поэтому он плох. Судя по приведенным вами примерам и проблемам, на которые вы указываете, вы не часто работаете с этим языком, тогда зачем ругать то, что относится к иной для вас проф. области?

    P.S. После прочтения статьи так и не понял, что вы хотели донести, кроме сильного негатива.
    • +13
      В интернете слишком много позитива относительно Javascript и NodeJS, мне кажется что он преувеличен. А смысл статьи — во-первых донести негатив, во-вторых дать понять коллегам, что это не они виноваты в том, что язык такой. А то когда слишком много людей твердят одно и то же, начинаешь поневоле им верить, независимо от того, правду они говорят или нет.
      • +8
        Вообще, в чём-то я с вами согласен, особенно по поводу бума вокруг JS и ноды. Бум действительно преувеличен. Но, к сожалению, у нас есть то, что есть. Я возлагал надежды на Dart, но после оф. заявлений со стороны Mozilla, Apple и Microsoft об отказе поддержки этого языка на нативном уровне, надежды, вы, развеялись. Но я советую вам не расстраиваться — помните, сколько теребили тему NoSQL и в особенности NoSQL+Node.JS? Мода проходит, обкатанные решения остаются, вода сливается. Так было тогда и так произойдет и в этот раз. Node.JS слишком молод и зелен, чтобы конкурировать со сложившимися мастадонтами. Может, когда нибудь… Но явно не сейчас.
        • +1
          maxvipon.github.io/talk-dump/?full#27 13000 rps как максимум это конечно очень молодо и зелено :)
          • +4
            По вашей ссылке нагрузка 13000 RPS на кластер из 18 машин. Получается 700 RPS на машину или ~50 RPS на ядро. Это должно впечатлять?
      • +7
        Если честно, я не стал даже читать вашу статью, потому что понял, что статья в духе «PHP — отстой».

        Я полностью согласен с xamd. Если вы не любите перец — это не значит, что это яд и его нельзя применять в кулинарии.

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

        Поэтому погуляйте еще: а вдруг мнение изменится.
        • +6
          Позвольте мне наглость процитировать самого себя, раз уж вы не читали статью:

          Род человеческий издревле славится своей изобретательностью и приспособляемостью, и вовремя не выданный молоток гордый представитель человеческого рода заменит камнем. А самые изобретательные, при отсутствии камня, смогут забивать гвозди головой. Я поражаюсь тому, как эти люди искренне убеждены, что Javascript обладает какими-то незаменимыми фичами, которые, по их мнению, отсутствуют в других языках. Мои же попытки найти в Javascript что-то хорошее, чего бы не было в Python, Perl или Ruby, раз за разом терпят крах.
          • 0
            Пафосно. Беспредметно. Можно также написать что-то вроде: «Род человеческий издревле славится своей изобретательностью и приспособляемостью, и нечто новое и плохо познанное умеет ругать самым изощренным способом.»
        • +9
          Проблема тут в том, что эти ваши «специалисты по перцу», которые вчера анимировали кнопочки для сайтов и рисовали UI, и слабо знали что такое ООП, с приходом node.js вдруг придумали, что они могут писать вообще для всего. Учитывая, что JS не приучает к хорошему дизайну, имеем кучу откровенного г-на, понаписанного всякими «специалистами».
          С дизайном JS, правда, ситуация гораздо лучше чем с PHP.
          • +2
            Спасибо, мил-человек! А то все комментаторы только проблемы приведения типов видят.
            • +2
              Ну, php тоже имеет эту проблему. Почитайте тот же тостер. От вопросов а-ля «как подключить несколько иклудов в один файл»(с) немногие оставшиеся волосы стремительно сворачиваются клубком! =)
          • 0
            Говоря о PHP мне нравится идея что плохой дизайн приложений получается из-за сообщества которое советует плохие советы. Только не знаю как бороться с этим.
        • 0
          >> Если честно, я не стал даже читать вашу статью, потому что понял, что статья в духе «PHP — отстой».

          Блин, ну зачем вы тогда комментируете? Автор очень доходчего все описал: он ни отрицает ни одного пункта из вашего заявления в комментарии, и даже сделал ремарки, предвещая такие «не читал, но осуждаю» выпаде вроде вашего.
    • +5
      Видимо, автор любит следовать принципу итальянской мафии: «не понимаешь — убей».
  • НЛО прилетело и опубликовало эту надпись здесь
    • +13
      Причём вместо того, чтобы потратить его на документацию, чтобы узнать
      — что кроме parseInt() и parseFloat() существует банальный Number();
      — как работает приведение типов;
      — что можно писать просто if (!foo);
      — как работает Array.prototype.toString() и узнать почему new Array([],null,undefined,null) == ",,,";
      — как работает автоматическая расстановка точек с запятой;
      — что jQuery для кроссбраузерного выбора элементов уже не нужен, так как querySelectorAll() уже работает во всех браузерах, начиная с IE8;
      — что в HTML5 появился атрибут async у тега <script>;, а defer вообще давно работает даже в старых IE;
      — и многое другое…
      расписал свою графоманию.
      • +2
        Специально для вас был раздел «Перед тем как читать дальше».
        • +14
          Вы настаиваете на том, что не читать документацию — нормально? Представьте себе, если бы так пилоты говорили: «аэробус — кусок фрактала, там все лампочки включены, а не выключены как в боинге». Причём Javascript простой в изучении язык. Достаточно прочитать несколько глав по паре страниц, чтобы большинства вопросов, как у вас, больше не возникало.
          • –6
            Ваша аналогия содержит еще меньше смысла, чем моя статья.
          • +7
            А действительно, есть документация, в которой освящены все перечисленные вами вопросы? Мне правда интересно.
            • +4
              Есть «Подробное руководство» Дэвида Флэнагана[1], есть отличный ресурс Mozilla Developer Network (MDN)[2], есть caniuse.com, на stackoverflow.com можно найти ответ практически на любой вопрос, да и на тостере ответят — информации предостаточно.

              [1] Javascript: The Definitive Guide by David Flanagan
              [2] developer.mozilla.org/ru/docs/JavaScript — при поиске можно просто добавлять «MDN», часто ресурс находится и сам.
            • +4
              добавлю еще learn.javascript.ru/
          • +29
            На мой взгляд это классический пример accidental complexity. Ни в одном из более-менее популярных языков нет такого бедлама, как в js. Да пусть заминусуют меня насмерть, но после Java и Ruby не хочется продираться сквозь тонны документации, чтобы разобраться в этом мессиве. 21й век на дворе. Да, я понимаю, почему все так. Но я не могу принять позицию, что так должно быть всегда.
            • –3
              Вас ждут w3c, измените мир
            • +2
              Когда речь заходит об усложнии, хотите или нет, всегда будут сложности. Так, удобное сравнение '1' < 2 превращается в приведение типов, очевидные для многих программистов области видимости превращаются в уже не столь очевидные замыкания и т. п.

              Язык создан простым. Основы языка — несколько глав по паре страниц каждая из того же «Подробного руководства» Флэнагана. Отсюда и проблемы, язык кажется настолько простым, что приходят даже зелёные новички, однако, с основами языка освоится всё же стоит.
          • +7
            Для вас, наверное, будет открытием, что есть языки, в которых большинство вещей понятно без документации. Я вот люблю концентрироваться на архитектуре приложения, а не на вызубривании всяких хаков.
            • +5
              Для вас будет удивлением, но большинство вещей и в JS понятны без документации. Люди начинают делать какую-то ересь, и потом удивляются, что в результате вышла какая-то хрень. Кто в здравом уме будет сравнивать массив и булево значение, как это делает автор?
              • –1
                У меня было так (не помню уже деталей), что после рефакторинга (сделанного не мной) функция стала возвращать вместо булева значения массив. И никто ничего не заметил, все прекрасно работало до того момента, как неожиданно сломалось. Очень долго отлавливал, проклял все на свете.
                • 0
                  Тесты? Не, не слышал!
                • +5
                  Хорош рефакторинг, нечего сказать!
                  • 0
                    Да, я тоже удивился, когда обнаружил это изменение. Но я скорее не про рефакторинг, а про такое свойство js, когда все уже неправильно, но еще как-то работает.
      • +4
        Киньте ссылкой, где почитать про:

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

        Реально интересно, т.к. только вчера столкнулись с подобной проблемой: [1] == true !== [2] == true…
          • 0
            Эммм… А нет там ничего про подобное поведение. Ну или я не нашел. Более-менее подходящее, из того что нашел, вот это:



            Но это как-раз противоречит вопросу. Можете, plz, ткнуть носом, где именно почитать про разницу между [1] и [2]?
            • –5
              Очевидно же,

              11.9.3 Алгоритм сравнения абстрактного равенства
              вызовет
              9.1 ToPrimitive
              вызовет
              8.12.8 [[DefaultValue]]
              вызовет
              15.4.4.2 Array.prototype.toString
              вызовет
              15.4.4.5 Array.prototype.join

              Читаем полностью, зубрим и вопросов не возникает.
              • 0
                вот если честно только не совсем понимаю [true] == true точнее справа мы будем иметь 1, а слева мы получим вызов [[DefaultValue]] который может пойти по пути toString и valueOf выбор пути зависит от переданного значения в метод [[DefaultValue]], я вот не могу найти место где написано какой значение будет передано и соотвественно почему будет именно toString
                • –2
                  Да, я для упрощения пропустил пару моментов — ToNumber вызовет тот же ToPrimitive с подсказкой и valueOf, который будет проигнорирован, т.к. valueOf массива вернет объект.
                  • 0
                    Господа минусующие, объясните мне пожалуйста, что вас не устроило в ответе? :) Была просьба ткнуть носом в то место спецификации, где написано, почему абстрактное равенство работает с массивами именно так, как работает. В том, что цепочка действий, что происходит при этом, не маленькая — виноват не я и не моя карма.
              • 0
                Стоп-стоп… 1] => '1', [2] => '2'. Все верно? И то, и другое должно быть приведено к true, если верить документации. Соответственно, результат должен быть одинаков. Где ошибка?

                P.S.: сорри, что надоедаю, но мне реально не понятно, а с js имею мало опыта.
                • 0
                  Читайте мой ответ ниже
                  [1] == true => 1 ==1
                  [2] == true => 2 == 1

                  true в данном случае будет приведено к 1
                • +1
                  == для булевых приведет [2] к строке '2', её к числу 2, а true к числу 1. 2 не равно 1. См. 11.9.3.
                  • 0
                    Теперь понятно, спасибо.
              • 0
                Пожалуй добавлю в закладки
              • 0
                Очевидно же

                это сарказм?
                • +1
                  Без тега не ясно? :)
            • 0
              If the two operands are not of the same type, JavaScript converts the operands, then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the string operand is converted to a number if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.
              • 0
                И с чем не согласны минусующие?
                Seldon в комментарии ниже разжевал, то что я процитировал.
            • 0
              [] == true => null == 1 по спеке
              [1] == true => 1 ==1
              [2] == true => 2 == 1
              [true] == true => «true» == 1
  • +8
    > Короче говоря, язык, который используется огромным количеством людей от случая к случаю мог бы бы доставлять и поменьше проблем.
    эту же мысль продвигал и этот рубист: «20 и 1 примочка Javascript, которые я никак не могу запомнить», не высказывая её явно.
  • +2
    Наверное, все-таки, не фракталом, а эталоном.
    • +18
      Нет, я правда не понимаю, что означает фраза «фрактал отсоса».

      Фрактал — самоподобная структура. Самоподобная структура отсоса? Это как, отсасывает сама у себя что ли?
      • +8
        не просто «отсасывает сама у себя», но «отсасывает сама у себя СЕБЯ(, отсасывающую саму у себя себя)».
        www.youtube.com/user/cyriak/videos — для стимуляции воображения.

        помимо этого, вспомнилось «Уже давно не видно никакого исполина, а только нефтяная труба и висящая на ней крыса, делающая себе мистический автокефальный уроборос. » © Пелевин, «Священная книга оборотня».
        • 0
          Моя фантазия подсказала мне пару интересных образов, но я не могу их формализовать — не хватает понятийного аппарата в языке. Проклятая проблема квалиа.
      • +4
        Изначально это была пародия на название «PHP: фрактал плохого дизайна»(первая ссылка в статье), найденная мною на специализированном форуме для девочек и анимешников, и означающая нарицательное название для всякого проблемного языка программирования. Но ваша трактовка определенно нравится мне больше.
  • +9
    Обязательно сохраните этот пост на стороннем ресурсе, а то уйдет в «черновики».
  • +38
    Я, кстати, окажусь непопулярным и соглашусь с автором.

    Потому что в любом языке есть совершенно ублюдочные вещи.

    Моим первым профессиональным языком был C#. Я всегда поражался тому, что конструкция ((Foo)null).Bar() выкидывает NullReferenceException даже в том случае, если Bar невиртуален и не обращается к методам-членам, в то время как аналогичная конструкция для Extension-метода исключения не выбрасывает. Умом я это понимаю, но какая-то внутренняя часть меня каждый раз бунтует.

    Потом был C++, лишенный данного недостатка, однако обладающий массой своих bullshit-вещей, которые яростно защищают на форумах интернет-воены низкоуровневой разработки.

    Затем в моей жизни появился Objective-C со встроенным паттерном null object, который каждый раз портил мне массу крови — программа работает, но выдает совершенный мусор из-за того, что где-то вместо массива был передан nil, от которого был запрошен length, из которого получился 0 — валидное значение, чем плох массив с 0 элементом, а дальше…

    Это совершенно не значит, что надо «учить стандарт». Стандарт языка С++ содержит сколько страниц? Я за все время учебы в институте столько страниц не выучил.

    Язык должен быть интуитивно понятен. Вы берете молоток и сразу видите, куда и как бить — вам не надо читать 300-страничную инструкцию к нему. Конечно, с усложнением инструмента усложняются и правила его эксплуатации, но это совершенно не означает того, что нужно кнопку «стоп» красить в нежно-бирюзовый, а разрыв цепи замыкать под углом в 37,5°.
    • +10
      Примерно. Особенно верно, что с каждым следующим языком формируется некое ожидаемое поведение, общее для многих языков, и каждый следующий язык кажется молотком, а не аэробусом, как писали выше.
    • НЛО прилетело и опубликовало эту надпись здесь
      • +2
        Оно может нравиться миллион раз, но оно навязывает программисту определенный стиль работы, отличный от других языков.

        С учетом того, что язык выбирается исходя из задачи, а не из личных предпочтений, это довольно актуально.
    • +4
      Как раз изучаю C# после C++ сейчас, фокус с null и методами vs extensions по мне вполне логин наоборот. Что бы вызвать метод объекта, рантайм на всякий случай сверяется с RTTI, а extension — это же по сути синтаксический сахар к Extclass.Method(null);

      Это я к тому, что у разных людей разные ожидания и представления о том, что есть логично а что нет

      P.S. Про C++ кто то верно подметил, что мир окончательно рпзделился на тех, кто успел выучить C++, пока он был относительно простым и тех, кто не выучит его никогда
      • +1
        С++ невозможно выучить. Увы.

        Что происходит в кишках я знаю, я все-таки не самый плохой программист. Но интуитивно это кажется не совсем корректным.
        • +1
          Я знаю одного человека, который как минимум C++03 стандарт знает чуть ли не на изусть. Вопрос только а том, какой ценой…

          ЗЫ извиняюсь, пишу и писал с телефона, опечатки глупые порой из за свайпа
          • 0
            Следующий шаг — C++11
  • –12
    Хех, весна, весна, у автора обострение? (погуглите хорошего специалиста, запишитесь на прием)
    Но по порядку:
    1) Лично автору предлагаю удалить все браузеры, обидеться на мир и не заходить в интернет вообще, там все на js, для вашей психики — опасно

    2) Выучите матчасть! И я сейчас не о спецификации js, а о том почему в вебе все именно так! Тоже самое я могу сказать о html, css (хоть это и не языки программирования), но корень проблемы общий, код выполняется на стороне клиента и напрямую зависит от возможностей клиента, хватит ныть! Примите как данность, у всех разные устройства, браузеры, плагины, все это накладывает свой отпечаток и именно поэтому нельзя все резко поменять и сделать хорошо. Но я понимаю, лучше вылить на всех пару сотен строк ерунды, зачем вникать в проблему.

    3) Я думаю, что не один человек не учить спецификацию как стихи наизусть, но хороший программист от плохого отличается тем, что он знает принципы организации ЯП, которые берут начало еще в математики. И ему не надо учить спецификация, он просо знакомиться с принципами заложенными в язык. а далее лишь учить api стандартной библиотеки, особенности\баги\недочеты языка и примеры из «best practices»

    4) Люди на nodejs себя чувствуют хорошо ибо энвайромент на котором будет запущен проект известен заранее и проблем с совместимостью нет, вы пишите в современном стиле и используете фитчи которые точно заработают. И в общем то писать очень удобно

    5) Библиотеке в js в общем-то такие же как и в других языках, почему вы используете вон тот скрипт который забросили год назад — это к вам. В мире куча прекрасных разработок с огромным комьюнити. Откройте java и посмотрите скока там разных библиотек, а скока там проблем с ними? Когда вы берете и у вас все падает, а при поиске проблемы оказывается что в нее разработчик вшил другую библиотеку которая по версии конфликтует с вашими и тд, но никто же не умер — живут. Идеала нет, идеал создаете вы. С начало думайте, потом делайте.

    Ребята простой совет — будьте профессионалами, тогда ваше мнение будет похоже не на истерику малыша у которого отобрали конфетку, или вы не будите писать статью которую уже сотни людей писали до вас. Ну и наверное тогда вы будите воспринимать мир, таким, какой он есть и делать замечательные вещи.
    • –2
      с удовольствием мазохиста дочитал этот перл до конца. адово например. надо срочно прислушаться к мнению этого человека.
  • +2
    немножко позитива негативному посту www.destroyallsoftware.com/talks/wat
  • +5
    Ну емае.
    Все ситуации реально разбиваются о два постулата:

    -Javascript преимущественно функциональный язык с примесью объектного по большей части для реализации методов встроенных классов. Это не только Array, String и так далее, это еще и HTMLElement и его производные, которые должны обладать собственными интерфейсами. В настоящее время это основная задача ООП в js.

    -Не пользуйтесь автоматическим приведением типов.

    Что ж вы за программисты такие, вам лишь бы строгую типизацию и ООП подавай. Хотите этого — берите dart, например (который прелесть, да). Хотите скрестить жабу с гадюкой Руби с Питоном — берите кофескрипт, который отвратителен одной-единственной вещью: тем, что в js функция это переменная первого порядка, а значит, в отличии от руби того же someFunc и someFunc() дают разные результаты и запутывают разработчиков.
    • –2
      Оособенно радует, что множество ревнителей ООП имеют весьма смутное представление от тех же шаблонах проектирования. И сказать, чем отличается, например, Фабрика от Компоновщика не в состоянии. По большому счету основной недостаток объектной модели JS — это отсутствие механизма интерфейсов. В этом отношении очень хорошо смотрится Typescript.
      • 0
        тайпскрипт отвратительно смотрится, если честно. Особенно на фоне дарта.

        Документация напрочь запутанна и сложна, я с дартом разобрался за сутки с небольшим, тайпскрипт не смог осилить и за неделю. Особенно много подстав было с оверлоадом функций
        • 0
          Я серьезно еще в тайпскрипт не погружался. Пока меня привлекают 2 вещи: совместимость с JS-кодом и механизм интерфейсов как в Go. Класс автоматически считается реализующим какой-либо интерфейс, если у него есть нужные методы.
          Сегодня вот наткнулся на библиотеку DefinitelyTyped, которая в перспективе сильно упрощает работу с существующим JS-кодом.
          • 0
            dart умеет минимально взаимодействовать с JS, а возможностей у него на порядок больше. одни только нативные set / map и аналог method_missing чего стоят.
            • 0
              Минимальное взаимодействие — это немного не то. Используя тайпскрипт, для начала можно просто переименовать существующие файлы в ts, а затем потихоньку начать рефакторить код. На Dart'е придется сразу писать новый код.
              • 0
                ну, мне повезло — у меня поток новых проектов, есть возможность опробовать новые технологии, а не рефакторить старое.
    • 0
      Проблема сильно глубже. У Dart/AtScript/TypeScript строгая статическая типизация. Статическая типизация накладывает ограничения на скорость разработки, а также на качество проектируемой архитектуры. Учитывая средний уровень подготовки типичного JS программиста — такой программист с задачей тупо не справится.

      А вышеуказанные языки разрабатываются как правило под влиянием ребят, знакомых с Java/C++/C#, и разработка на этих языках для них не является проблемой.

      Идеальным решением было бы сделать строгую динамическую типизацию (как в Ruby или Python). Но вот загвоздка. Без вмешательства в интерпретатор, такую типизацию сделать крайне сложно, и реализация ее на уровне компиляции будет более затратной в плане производительности, чем даже типизация в рантайме у того же AtScript. AtScript может позволить себе вставить условие проверки соответствия переменной конкретному типу в конкретном месте кода. В случае же с динамической типизацией, информацию о типе придется таскать с собой, и проверять соответствия типов при каждой маломальской операции. Это будет занимать наверное 60-80% времени исполнения кода.

      Так что, увы — слабая типизация — это бремя языка, которое он будет нести наверное вечно, если все же разработчики интерпретаторов не озаботятся этим вопросом, и не найдут пути плавного перехода на эту схему.

      • 0
        Что-то не посмотрел на дату публикации. Некрофилией страдаю =(
  • +7
    С такими тезисами вы не найдете поддержки и приятия у людей, которые научились забивать гвозди камнями и делают это виртуозно, и делают потрясающие да и просто полезные вещи с их помощью.

    Я подумал, а это ведь вполне рационально — использовать камень вместо молотка, если камни распространены повсюду (здесь: браузеры) и по пользованию ими накоплен большой опыт (здесь: js библиотеки). Другое дело, что если вам не нравится использовать эти камни (как и мне — тут я с вами согласен и статья у меня отторжения не вызывает) — то проще и полезнее сменить специализацию. Уйти в чистый бекенд/bigdata/др. область менее связанную с веб-фронтендом (сам подумываю о этом).
  • –2
    Настоящий яваскриптер никогда не напишет:

    if (isEven(3) == false)

    он возьмёт и напишет:

    if (!isEven(3))

    а под эту проверку попадают все три выше перечисленных приёма.

    P.S. «двач образовательный» — забавно
    • +15
      foo()==false не эквивалентен !foo(), чудесно. И вы еще удивляетесь, почему пилят дарты и прочие coffee/type-скрипты.
      • –6
        Это вполне логично и правильно, вы не видите разницы между оператором == и! это два разных оператора языка, было бы странно если бы они работали одинакого.
      • +2
        Я не понял вашу мысль, поясните.
        • +4
          x==false
          и x!=true (и его сокращенная форма !x)

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

          • +2
            == это оператор сравнения без учета типа объекта
            ! это оператор отрицания

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

            И это никакой не дурдом, а вполне нормальное поведение, описанное в стандарте.
            • –1
              Я пояснил чуть ниже, специально для тех, кто любит елки вместо леса рассматривать.
              • –1
                Я Вам специально там ниже ответил, для тех, кто любит видеть в лесу только елки :)
            • 0
              Приведете валидный случай, когда сравнение без типа объекта облегчает жизнь?
              • +1
                is_there_something() && (some_var = do_something());
          • –1
            Ну и понятно, что !x это не операция сравнения, но в if выражениях по сути это используется как краткая запись условия ложности проверки на true, надеюсь, это достаточно очевидно чтобы не было придирок с формальной стороны.
            • +1
              Я могу в if использовать и арктангенс, и это тоже будет вполне валидно :)
              Но уж если вы пользуетесь сокращенными вариантами типа "!" то будьте любезны знать как оно работает.
              • +2
                Я понял, JS это как девочка. «Да», «может быть», «нет», и «точно нет». В зависимости от того, что ей принесешь — букет или тортик. Ну уж нафиг.
                • +5
                  Я там выше написал вам что JS — это «язык со слабой типизацией», не поленитесь — посмотрите что это — и Вам станет очевидно такое поведение.

                  У языка есть неявное преобразование типов, которое обязано его слабой типизации, именно по этому там есть «строгое» (с точностью до типа) и «не строгое» (с автоприведением типов) сравнение.

                  Аналогия с девочкой неуместна — если ты настоящий мужик, она всегда скажет тебе «ДА».
                  Будьте настоящим программистом :-D
                  • 0
                    Я не понимаю, зачем вообще типы языку, который так себя ведет. Ну обозвали бы все зайчиками. Строка — зайчик, число — зайчик, true — опять зайчик. Все бы все поняли и даже бы не ругались. А так, у нас есть зайчики, ежики, слонята и гиппопотамы. И все друг в друга превращаются строго по спецификации, но это не перестает делать их превращения откровенно наркоманскими.
                    • 0
                      Я жду от вас спецификацию языка где ВСЕ «зайчики». Ваше утверждение подразумевает не типизированный язык, то есть понятие типов отсутсвует, жду с нетерпением спецификацию, может это будет прорыв в программировании?
                      А js — попрежнему язык со слабой типизацией, от сюда в нем таки есть понятие типов
                      • +2
                        >Я жду от вас спецификацию языка где ВСЕ «зайчики».
                        Любое околоассемблерное с указателями и прямой работой с памятью. Заметьте, там все очень логично и понятно. Берешь всегда то, что положил. И как ты с этим работаешь — исключительно твои проблемы.
                        • +1
                          О давайте тут про ассемблер поговорим и про работу напрямую с памятью в браузере — это же так ускоряет разработку, когда все напрямую :-D
                          Я вот знаю intel, zilog, microchip и atmel нотации, а Вы? )))
                          Самое место.

                          Харош уже троллить, Все подробно и четко уже описали Вам, дальше уже не смешно.
                          • 0
                            >О давайте тут про ассемблер поговорим и про работу напрямую с памятью в браузере — это же так ускоряет разработку, когда все напрямую :-D

                            Но ведь это всего лишь крайнее выражение идей слабо типизированных языков ;)
                            • +4
                              В ассемблере нет как такового типа вообще.
                              Есть память и регистры сколькинидь там битные, ну и в крутых есть возможность мутить с плавающей запятой.

                              слаботипизированный != нетипизированный как-бе )
                        • 0
                          Ога, вот только ассемблер низкоуровневый язык и вся работа там происходит с байтами и адресами памяти, что заставляет вас самому держать в голове что за тип данных вы положили в данный адрес и также получать корректный результат если вы математически сложите число 1000 и слово «вася».
                          И не забудьте посоветоват ьвсем срочно пересесть на ассемблер для решения задачь.

                          Давайте останемся на уровне нашей проблемы и ЯП высокого уровня. Ибо в низкоуровневых языках совсем другие. свои проблемы которые никоим образом не свзаня с проблемами языков высокого уровня
                          • –3
                            Я просто хочу, чтобы люди знали, что слабая типизация это вовсе не так модно и прогрессивно, как им кажется.
                            • 0
                              Э, господин хороший, не подменяйте понятия, мы тут с Вами про JS говорим и посыл был изначально другой, никто про модность слаботипизирования тут не говорил ничего.

                              Хотите чтобы люди знали — напишите статью — там и пообсуждаем.
                            • 0
                              А вот это бредятина чисто воды, подобные разговоры должны начинаться с постановки задачи.
                              Вот я знаю случаи когда народ специально переползнает на nodejs потмоу как идет огромная работа с nosql базами а там объекты хранятся в json, а он в свою очередь является нативным объектом для js и народ переходит на js чтобы грубо говоря не получать оверхеда и писать код в 10 раз быстрее получая и обрабатывая уже готовые объекты из бд и браузера.
                              И как помне вполне логично, что крупные модульные системы в которых строгая типизация избавляет от проблем уже на этапе написания кода вполне логична ситуация использования других языков нежелеи js
                              • 0
                                >объекты хранятся в json, а он в свою очередь является нативным объектом для js
                                Тогда народу должна понравиться Clojure.
                                • 0
                                  А кому-то она и нравится, просто есть NodeJS и комьюнити а не NodeClojure
                        • +1
                          В JS, кстати, тоже если ты присвоил foo = 42, то оно там так и останется лежать в виде числа, пока этой переменной не присвоишь что-нибудь другое. Даже после foo + "bar".
                    • +1
                      Ибо string, number & boolean — это разные объекты — именно зайчики, ежики и гиппопотамы в Вашей терминологии. Вы работаете с их экземплярами.

                      Если бы это был язык со строгой типизацией, то операции типа string == boolean в принципе не возможны — сразу же будет ошибка.

                      Но если такое сделать в языке, построенном на слабой типизации — то это будет ад.

                      По этому каждый объект имеет методы приведения к определенному типу (или одному универсальному типу) и есть неявное приведение этих типов, чтобы можно было писать string == false, и в мануале описано как че когда себя ведет и во что преобразуется.

                      Вы ругаетесь на JS, потому что пытаетесь к нему относится с точки зрения строго типизированных языков, точно так-же его ругают те, кто не понимает прототипы, говоря что ООП у языка нет (ну или оно неправильное) и это пи#$ец!

                      Нельзя ругать отвертку за то, что Вы ей паять пытаетесь, хотя да — она вполне похожа на паяльник.

                      Разберитесь, что такое JS — и тогда все встанет на свои места.

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

                      Если Вам он не удобен, не привычен и не интуитивен — возьмите другой, не мучайтесь.
                      Благо альтернативы есть, пусть и с трансляцией.
                      • +1
                        >Нельзя ругать отвертку за то, что Вы ей паять пытаетесь, хотя да — она вполне похожа на паяльник.

                        У JS практически нет альтернативы для браузеров. Именно поэтому его ругали и будут ругать. Если бы с него спокойно слезали на что-нибудь другое, никому не было бы до него дела.

                        Вот те, кому не нравится PHP могут спокойно уйти на Java или C# и не ныть про типизацию. У тех, кто пишет на JS альтернативы нет (точнее есть в виде трансляторов, но любой лишний слой абстракции все равно несет оверхед, поэтому это необходимое зло, а не решение проблемы).
                        • 0
                          Трансляция Вас чем не устраивает? Dart тот-же, чем не альтернатива? По производительности практически один-в-один.

                          Ругать можно все, что угодно — толку?

                          Сделайте что-то лучше, предложите это сообществу — кто знает — быть может в будущем мы будем тогда kudrjs писать :-D

                          Лично меня JS вполне устраивает, если не писать, разбрасывая подводные грабли (а это быстро приходит с опытом), то никаких неудобств и непонимания не возникает.

                          Вполне логичный и лаконичный язык. Развивается он да, медленно — но, увы, это упирается в браузеростроение а не в сам язык.
                          • +1
                            Есть некоторые проблеммы с дебагом
                            • 0
                              Есть, но вполне решаемые, пусть и не очень красивые.
                              Зато на альтернативном языке, как того хочет мозг.
                        • +1
                          Многие трансляторы уже дают вполне хороший код без оферхеда так называемого. А отсутсвие альтернатив — не проблема js и вообще подобный взгляд является объективно не верным!
                • +7
                  блять, используйте "===" "!==" уже сказано всем 100 раз, в документации написано.
                  Почему вы используете оператор логического отрицания вместо оператора сравнения и ждете адекватных результатов? Кто вам сказал что эти оператор выполняют одну и туже роль?

                  и x!=true (и его сокращенная форма !x) НЕТ, это не его сокращенная форма, что за бред, откуда такие выводы?
                  != — оператор сравнения
                  ! — оператор логического отрицения

                  но в if выражениях по сути это используется как краткая запись условия ложности проверки на true

                  И еще раз, это ВЫ так используете оператор отрицания, именно ВЫ, никгде не написано что это сокращенная форма.
                  • 0
                    да, да. да )))
                    прекрасно Понимаю Ваше негодование )
                    еще можно автору порекомендовать юзать if(!!x == false) для полной надежности )))
                    lol
                • 0
                  Вы жалуетесь на то, если Вы скормите интерпретатору херню, он не кинет ошибку, а попытается вернуть более-менее вменяемый результат?
                  • +1
                    Замалчивание ошибок — зло. Оно точно так же приносит проблемы на продакшене, только теперь уже хорошо закопанные.
                    • 0
                      Если у вас есть QA, то он может найти ошибку на этапе тестирования, если нет, то любую ошибку легко можно пропустить. Всё-таки главная роль в отлове ошибок не у языка, а для написания хорошего кода существует такая практика как рецензирование кода (code review).
                      • –1
                        Я работал с отделом QA состоящем из 6 человек и они регулярно ловили ошибки в бою. Роль недопущения и отлова ошибок она во всем, начиная от архитектуры, заканчивая кривизной рук отдельных людей. Дизайн языка тут так же влияет, скажем, в сильно типизированных языках типа Java ошибки на продакшене больше смещены в сторону архитектуры и последовательности обработки данных, а роль опечаток и type mismatch в принципе близка к нулю.
                    • +1
                      Простой пример: если на странице в счётчике просмотров красуется «NaN», это неприятно, но не фатально. Или было бы лучше, если из-за такой ошибки вся страница становилась нефункциональной?

                      С другой стороны, скажу честно, в моей нынешней практике незамеченные баги, вызванные несоответствием типа — редкость. При условии, что в нужном месте производится проверка isFinite() (кстати, NaN может случиться и не только от приведения типов), аргументы (при необходимости) явно приводятся к конкретному типу, и сравнивание производится только через === за исключением == null.
                      • –1
                        >Или было бы лучше, если из-за такой ошибки вся страница становилась нефункциональной?

                        Вы только что затронули еще одно больное место языка/экосистемы. Один поток скрипта на все окно браузера. Топикастер, кстати, об этом написал. Если бы рухнул только счетчик, никто бы и глазом не моргнул.
                        • 0
                          Так проблема ли это языка?
                          Отнюдь.
                          Есть Worker’ы. Плюс, екзепшн в колбеке, не влияет на работу обработчиков остальных ивентов/колбеков. Если я понятно выразился.
                          • –1
                            Когда я в последний раз смотрел на воркеры, в них были недоступны все объекты window.*. И как следствие были невозможны манипуляции с DOM. Ну а исключения… их к сожалению используют только те, кто может писать стабильно работающий код без исключений. Большая часть их не использует, если вообще знает о существовании оных.
                            • +1
                              Да. Ваша правда.
                              Опишите параллельную работу с DOM деревом.
                              Я не знаю, для чего это?
                              • –1
                                Навскидку — мониторинг из воркера за каким-то значением из атрибута тэга. Сложная анимация, которой не хочется грузить основной поток выполнения. Ну и прогрессбар без обмена сообщениями с основным потоком.

                                Но я не буду отрицать, что воркеры таки решают вопрос тяжелых вычислений на клиенте для очень многих случаев.
                                • +1
                                  А зачем вам worker, когда есть MutationObserver и requestAnimationFrame? Анимация вообще должна быть нетребовательной для 60 fps. Это не вопросы тяжёлых вычислений.
                                  • +1
                                    Тут, я так понимаю, что есть тяжелая математика и надо обновлять прогресс бар по ходу этой математики. Но это смешно.

                                    И все равно. Это не проблема самого языка. Может так легче на уровне браузера это реализовать.
                                    • –1
                                      Притянуто за уши. Тяжело слушать сообщения?


                                      Мне кажется более удобным засунуть тяжелую операцию и отображение ее прогресса в одну функцию. А обмен сообщениями, согласитесь, несколько усложнит код.

                                      а кто меняет этот атрибут?


                                      Другой скрипт, который по некоторым причинам я трогать не могу или не хочу. Например потому, что скрипт был обфусцирован.
                                      • +1
                                        более удобным засунуть тяжелую операцию и отображение ее прогресса в одну функцию


                                        Это в корне неправильно — смешивать бизнес-логику и интерфейс. Как раз обмен сообщениями здесь смотрится уместнее.

                                        Для отслеживания изменения атрибута есть MutationObserver. Да, и невозможность работы с DOM из воркера — не недостаток языка (DOM — не часть JS), а ограничение API браузера.
                                        • –1
                                          По хорошему неправильно. Но мне кажется, что найдется такой класс несложных задач, когда запустить воркер с полноправным доступом к DOM было бы удобнее, чем писать мостик для обмена сообщениями.
                                    • +1
                                      Так для тяжёлой математики есть система обмена сообщениями.
                                  • –2
                                    Послушайте, я прекрасно понимаю, что можно сделать слежение за тэгом и без воркеров хоть через setInterval, хоть через MutationObserver. Но поймите и вы, что ограничений воркеров это не отменяет.

                                    Анимация никому ничего не должна.
                                    • 0
                                      > Но поймите и вы, что ограничений воркеров это не отменяет.

                                      А как вы собрались асинхронно работать с DOM? DOM же один, а то у вас один Worker обновит данные, а другой перезапишет их значком загрузки из-за условий гонки.

                                      > Анимация никому ничего не должна.

                                      Конечно, не должна, это вы должны обеспечить плавность анимации, иначе она никому такая не нужна.
                                • 0
                                  Не выдумывайте.

                                  > мониторинг из воркера за каким-то значением из атрибута тэга
                                  а кто меняет этот атрибут?

                                  > и прогрессбар без обмена сообщениями с основным потоком.
                                  Притянуто за уши. Тяжело слушать сообщения?
                            • +2
                              Тем лучше для нас, что они недоступны. Если бы worker-thread-ы могли обращаться к DOM и другим объектам доступным из главного потока, мы бы также получили необходимость синхронизировать потоки и тогда бы в JS пришлось добавлять семафоры, мютексы, спинлоки, volatile переменные и прочую жуть.
            • +2
              решение использовать "!" как краткую запись условия ложности — ваше решение, вы за него и в ответе. оператор «if» в качестве предиката примет любой объект или примитив.
              • 0
                Нет, это не мое решение, выше сказали, что так напишет любой нормальный JS разработчик. Потому что ему естественно жить в этом шизофреническом бреду приведения типов и десяти вариантов null.
                • 0
                  Любой «нормальный» разработчик напишет правильно. И если разработчик ожидает получать от функции конкретный ответ !function() будет работать,
                  isEven(3) — подразумевает возвращение в виде результата булева значения о чем говорит префикс is поэтому работая с булевыми значениями !isEven(3) эквивалент isEven(3) == false

                  если у вас есть func() которая возвращает null, undefined, 1, 0, "", «1», [], {} true, false то в случае когда вам надо проверить на false вы напишите func() === false
            • 0
              Нет, не так.

              !x — это не проверка, не условие, а оператор. Подразумевается, что в операндах у него — значение булевого типа. Если ты туда запихал что-то другое, то ССЗБвыполняется операция приведения типа операнда к булевому, это происходит по некоторым правилам, и они вполне привычные:
              — undefined, null -> false
              — 0, NaN -> false
              — пустая строка -> false
              — все остальное -> true

              Напротив, == — сравнение значений, и у него тоже есть пара особенностей:
              — null == null, undefined == undefined, null == undefined
              — при сравнении строки с числом, строка приводится к числу
              — при сравнении чего угодно с булевым значением, булево значение приводится к числу

              Это не сложно вроде, в том же PHP сложнее.
              • –3
                ! и == это в целом булевые операторы. Только кривизна языка приводит к тому, что! приводит операнд к bool прежде чем вычислить выражение, а == сначала сравнивает, а затем приводит к bool результат.
                • 0
                  Еще раз, (!x == y) === (x != y) далеко не всегда и не во всех языках верно.
          • 0
            А что говорит логика про
            if (42) { /* выполнится */ }
            if (42 == true) { /* не выполнится */ } 
            

            Много ли языков программирования, в которых второе выполняется?
            • –2
              Логика говорит, что в обоих этих случаях нужно кидать ошибку рантайма и не мучить ежика.
              • +1
                console.log(42) — тут тоже ошибку рантайма кидать?
                • –1
                  Ну давайте сюда еще логи и прочие тустринги притащим. Очевидно же, это не имеет отношения к проблеме. Неявное приведение в стринг это совсем не страшное поведение и нужно очень сильно постраться, чтобы от него были проблемы. В любом случае, это легко отлавливается.

                  А вот от сравнения несравниваемых величин проблемы есть всегда.
                  • +1
                    Что значит «не сравниваемых»? 42 и false — сравниваемые величины? А null и undefined? null и true? null и ""? null и 42?
                    • –1
                      Ответ очевиден.
                      • +1
                        На самом деле нет.
                      • +2
                        Расшифрую на всякий случай: для меня очевидно, что все указанные величины можно сравнить между собой в языках со слабой типизацией (это вообще следует из определения слабой типизации). Потому ваши претензии к JS относятся также и ко всем языкам со слабой типизацией (C/C++, кстати, в их числе).
                        • –3
                          Можно делать что угодно, только данные вещи делать не нужно.
            • +2
              Много ли языков программирования, в которых второе выполняется?

              Много. Полагаю, оно работает почти в любом языке со слабой типизацией. Помимо JS это и C/C++, PHP и т.д.
              • +2
                В JS как раз 42 == true не выполняется, т.к. true будет приведено к 1 (toNumber), и в результате получится 42 === 1, об этом и срач =)
                gleb_kudr почему-то считает, что всегда должно выполняться (!x == y) === (x != y), и удивляется, что это не всегда так.
                • 0
                  Если вместо x и y подставить true или false то это более чем логично.
                  В каком ещё языке кроме JS такое поведение? (любопытно)
                  • 0
                    Будете удивлены, но (!true == false) === (true != false) и в javascript. Это, кстати, никак не опровергает мой тезис о неравнозначности этих конструкций.
                    • 0
                      А если только в место x или y подставить?
                      • 0
                        я же говорю, что это не равнозначные конструкции, и не только в JS.
                        char* x;
                        bool y = false;
                        cout << (!x == y) << endl; // 1
                        cout << (x != y) << endl; // ошибка, в С++ нельзя сравнивать указатели и целые
                        
                  • 0
                    Проблемы от уверенности, что при сравнении вида == обе части должны приводиться к boolean, хотя это ниоткуда не следует, более того, даже не всегда логично, например, конвертация number -> boolean приводит к потере информации, т. к. диапазон значений boolean меньше, чем у number.
                    • 0
                      Мне кажется это логично. Языки так или иначе отражают нашу школьную алгебру, где для цифр сравнение определено явно. Некоторые нюансы с 1==1.5 так же интуитивно понятны. Всё остальное выпадает из области чисел и должно сравниваться через приведение к bool (результат ведь в итоге так же bool).

                      Это моё ИМХО и моя интуиция за других не говорю.
                      • 0
                        Погодите-ка, сравнение строк — тоже результат вроде bool, а ведь строки не приводятся к bool при сравнении?

                        Вообще, всегда автоматическое приведение типов работало так, чтоб исключить потерю значения. Сравните:
                        Boolean(Number(true)) // true, никаких потерь
                        Number(Boolean(42)) // 1, упс!

                        Так что именно приведение boolean к number выглядит логичнее. Ну а то, что вы операцией сравнения приводите какое либо значение к булевому типу вместо имеющихся способов приведения — так это уже ваши проблемы.
                        • 0
                          Ну я выше и написал, что это только мои личные заморочки.
    • +3
      Начнём с того, что существует две группы джаваскриптовщиков: те, которые всё ещё иногда пишут «==» — и те, которые ужé при любых обстоятельствах пишут «===» и тем навсегда освобождают свой разум (и память) от подробного знания длинной-длинной таблицы, описывающей алгоритм нестрогого сравнения в JavaScript.

      Я лично пишу «===» даже после «typeof someValue», потому что мне так психологически удобнее, уютнее, комфортнее.
      • +8
        А есть группа, которые не сравнивают яблоки и автомобили и потому им всё-равно, сколько знаков равенства писать.
        • 0
          Поддерживаю!

          Есть ещё группа, которая иногда делает так:

          var compare_params = function () {
          … do what we whant here
          };

          if (compare_params(par1, par2, settings_for_params)) {
          }

          с различным уровнем погружений в логику задачи.

          И зачастую логика приведения типов в этом случае конкретно зависит от реализации экземпляров объектов («классов», если кому-то вдруг мутит «прототипное наследование» БЕЗ Конструкторов).

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

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

          Но, Заказчик ВСЕГДА прав, особенно на рынке фриланса, пока победа в руках у него, так что, You Are Welcome to HELL!
      • 0
        Ну так может в новом стандарте сделать == как ===, а === как ==? Нужно не строгое сравнение — тогда используйте менее распространенный оператор.
        Просто после C/C++, Python, Ruby это очень смущает. Интересно в каких языках есть два типа сравнения?
        • +1
          Например в PHP
          • 0
            К стати да. Там вроде то же, что то было странное в приведении типов. Я увы давно с PHP работал и эпизодически.
        • 0
          А, ладно… Holy War такой Special Olympics.
          • 0
            По данным пунктам никаких войн нету. Это просто предположение, которое возможно имеет смысл.
            • 0
              Не, я не к тому, что есть что-то плохое в исходном высказывании, просто в ответе я сначала развёл философию и потом удалил комент, т.к. большинству вообще всё равно :)

              У меня своя точка зрения на всё, что здесь написано с обеих сторон.

              Субъективизм не поможет, потому, что всё как всегда. Здесь я нахожусь там, откуда уже «не возвращаются». И я не смогу объяснить свою позицию, т.к. это вызовет Stack Overflow или у меня или у некоторых из присутствующих.

              В итоге получится то же самое.
      • +3
        Ага, и пишут

        if (typeof foo !== "undefined" && foo !== null && foo !== "" &&
        (typeof foo !== "number" || foo !== 0 && !isNaN(foo) && isFinite(foo))) …

        вместо простого

        if (!foo) …

        Глупо не использовать возможности языка.
        • –3
          Плохой дизайн одной части вполне компенсируется плохим дизайном другой. Priceless!
          • 0
            Priceless! Fucn Awesome!

            Я сам из тех, кто спрятался за двери…

            Но всё таки пою.
      • 0
        Эм, вроде же вся «длинная-длинная таблица» отличий от строгого сравнения — четыре строки:
        — null == null, undefined == undefined, null == undefined
        — при сравнении строки с числом, строка приводится к числу
        — при сравнении чего угодно с булевым значением, булево значение приводится к числу
        — при сравнении строк и чисел с объектами, объект приводится к примитивному типу
        • 0
          >при сравнении чего угодно с булевым значением, булево значение приводится к числу

          Думаю, вот в этом и заключается главная причина непонимания, т.к. люди привыкли, что в таких случаях обычно число приводится к булеву значению, а не наоборот.
          • 0
            Ну да, но я не могу сказать, что это сильно менее очевидно, чем то, что пустой массив приводится к false в перле и пхп (хотя ссылка на него не является null). В общем, у всех свои недостатки.
      • –2
        И при этом JS «хороший и логичный». Ну а что, всего-то оператор, которым никогда не надо пользоваться.
        • 0
          Ну, почему же прям таки «никогда».

          А null?
  • –8
    Реально достало это нытьё. IE6 не стало, теперь js не нравится?
  • +9
    Предчувствие недели холиварных постов про javascript одолевает меня.
    • +2
      Ага, «зато мы делаем ракеты».
  • +7
    А мне кажется, что это все следствия одной совершенно банальной вещи — тотальной безальтернативности JS на клиенте (не нужно, пожалуйста, сюда приписывать «компилируемые в JS» языки). Популярность JS на сервере (а ноде-то уже 5 лет как будет, не считая того, что было огромное кол-во людей, так или иначе, но уже знающих язык) низкая, чтоб ни говорили, а еще можно сравнивать то, что сделали RoR за 5 лет существования (хотя тоже много хайпа, но все же). И следующая проблема, выходящая из первой — невероятно низкая скорость обновления самого райнтайма.

    PS. Спорить с тем, что масса программистов ненавидят JS, по-моему, бесполезно, потому как это факт.
    • +1
      Золотые слова!
      • –1
        Просто добавлю, что JS есть не только в браузере.
        Вот неполный списочек того, где он ещё есть:

        — Active Directory посредством Windows Scripting Host
        — Сам Windows Scripting Host
        — HTML Applications, известные со времён Windows 98
        — Rhino JS, встраиваемый куда угодно, по дефолту идёт вместе с Alfresco и Asterisk
        — 1C поддерживает JS
        — common.js library в Linux, и всякое GUI на основе него напиленное
        — Firefox OS
        — PnoneGAP и последователи
        — Куча корпоративных приложений под разные платформы, т.к. куча интерпретаторов являются либами с настраиваемыми wrapper'ами для объектов бизнес логики
        — Game Dev, тот же Unity

        До сих пор безальтернативно?

        Мух от котлет нужно отделять. Есть масса людей, которым просто нравится JS.
        Попробуйте написать полиморфы на языках со строгой типизацией, я верю, у Вас всё получится :)
        • –2
          До сих пор безальтернативно?


          На клиенте — да. Причем тут ваш список — вообще не ясно.
  • +2
    Разожгу :)

    function isEven(arg) {
        return 1 - (arg % 2);
      }
    
    

    Ну и варианты всякие типа !(arg % 2)
    • +2
      Ну и да, можно привести к булеву значению — силами языка — !!!(arg % 2) — в постановке isEven.


      • +6
        В джаваскрипте вместо «!!!» всегда можно записывать просто «!», я полагаю. Так не бывает, чтобы приведение типов работало только со второго или третьего раза.
        • +1
          точно, погорячился :) зато — железобетонно :)
          Хотя, продолжая идею автора статьи (можно наоборот, я знаю):

          function isOdd(arg) {
              return ( !! (arg % 2) );
          }
          function isEven(arg) {
              return !isOdd(arg); // !!! =)
          }
          
          • +2
            Я вижу проблему в другом. Почему автор для функции, у которой возвращаемое значение должно быть Boolean, придумал какие-то примеры с 1 в качестве true, и 0/null/undefined в качестве false? Сочувствую, если ему приходится работать с людьми, которые выдают такое, а также проводить у них code review. А вообще, после прочтения и изучения остальных примеров в статье, у меня закралось подозрение, что автор и сам не сильно квалифицирован в областях о которых пишет.
    • +4
      Я совсем не сишник, но «& 1» же.
      Менее интуитивно, но зато быстрее в большинстве ЯП. Настоящие сишники заботятся о быстродействии, а тут каких-то поддельных завезли. :)
      function isEven(arg) {
      	return !(arg & 1);
      }
      


      Добавлено:
      И даже какой-то пруф: jsperf.com/odd-and-even/2
      • 0
        И ведь никто не заметил, что в тесте по ссылке не учитывается, что у == выше приоритет, чем у &.
        Вот так должно правильнее сравнивать: jsperf.com/odd-and-even/6
        Но общая тенденция все равно в пользу &, а не %.
    • +2
      а чем такой вариант не угодил?
      return arg % 2 == 0;
      • 0
        Он посчитает null и [] чётными числами, а +Infinity и -Infinity или любую строку — нечётными.
        • +1
          Строка, которая может быть преобразована в число, будет обработана корректно. null, [], Infinity, -Infinity — для все этого проверка четности смысла не имеет. Обеспечивать какое-то спец. поведение смысла тоже нет. Правильнее обеспечить подачу корректных данных на вход функции.
          Кстати, вариант с побитовым И выдает такие же результаты.
          • –1
            Обеспечивать какое-то спец. поведение смысла тоже нет. Правильнее обеспечить подачу корректных данных на вход функции.


            Кто знает, что там в эту функцию подадут? Никто об этом не позаботится, если сама функция не позаботится:

            if(isNaN(parseFloat(arg)) || !isFinite(arg)) throw Error();
            • +2
              Это тупиковый путь. В случае такой простой функции как isEven ваш подход может показаться логичным. Но уже код isEven вырос в 2 раза. Более сложный код вырастет еще больше. Усложняется поддержка кода.
              В конце концов есть архитектура приложения, есть юнит-тесты. Гарантировать, что в функцию попадают корректные аргументы — можно и нужно.
              Конечно, есть код, где проверки нужны обязательно, но везде их лепить — это неправильно на мой взгляд
              • 0
                Как раз чем больше функция, тем меньшую долю займёт контроль параметров.
                • +1
                  Чем больше размер функции, тем больше вероятность того, что в ней есть вызовы других функций. Руководствуясь логикой недоверия ко внешнему коду, вызовы внешних функций нужно оборачивать в try/catch, а также тщательно проверить возвращаемый результат. Т.е. объем проверочного кода все-таки будет расти с увеличением размера кода функции.
  • +16
    А ведь прикольная статья то. Автор, разбомбите ещё что-нибудь популярное. Хинт (CSS).
    • –4
      CSS 2 был девственно чист и прекрасен пока в него своими грязными ручонками не залезли программисты, которые куда не влезут везде хотят впендюрить свой ООП. В итоге появляются выкидыши типа SASS и LESS, а затем скверна распространяется и в стандарте появляются переменные, функции (calc) и прочая ересь, которой там совсем не место.

      В итоге какой-нибудь CSS 4 превратится в очередной ЯП и от этого на душе гадко.
      • +1
        девственно чистый CSS 2 не могу решить всей широны задачь, которые стояли перед ним, так что не надо?
        Вот если для ховера в дизайне определен цвет #453665 хорошо бы его класть в переменную hover = #453665 ибо в противном случае в стилях начинают рождаться #453666, #453555, #455665, #466666 и тд А потом вам скажет, ховер плохой, меняйте на #777555 и вы пошли лопатить тысячи строк десятки файлов, зарабатывая геморой.
        Выкидыши типа less sass решают за вас кучу проблем начиная от автоподстановки префиксов — а это поверьте огромное благо. каждый раз писать десятки префиксов — удовольствие сомнительное, а тем более помнить есть ли такой или нет.

        Так вместо слов ересь. аргументируйте почему, а не несите бред.
        • –3
          CSS 2 решал любые задачи, которые вставали перед верстальщиками, много лет и никто не жаловался.

          Вместо переменной hover, можно завести класс hover, который добавлять всем элементам, где он нужен. И не надо будет перелопачивать 100500 строк для того, чтобы поменять #453655 на #777555, зарабатывая геморрой.
          • +1
            Надо будет пролопачивать 100500 строк html кода, а также 100500 классов на каждом элементе. То есть нам говорят вот тут ховер не нужен вообще, вместо редактирования 1 строки в css мы идем и лопатим html (шаблон) выпиливая класс. Это так в стиле современного веба где стараются таки отделить стили от html.

            СSS2 и щас решает любые задачи если вы делаете сайт визитку в одно рыло, кто спорит.
            Зачем нам удобные бордер радиусы, градиенты, трансвформации и анимация мы и по старинке тонной js все решим.
            $.on('hover', function, function) — любимый код для всплывающей подсказки или меньшки? Зачем нам 1 трока в css?
            Зачем нам организовывать работу 3-5 верстальщиков, сами разберуться, эффективность труда — не не слышал. Зачем переменные в css эти 5 замечательных специалистов сами договорятся, что делать и какой цвет юзать.
            • –4
              Ок, я понял, что доказать вам ничего не смогу. Так что разрешите откланяться.
          • 0
            Любые? Сделайте раскладку картинок как на Pinterest.com, чтобы первые элементы были верхними и дальше они равномерно заполнялись вниз (так надо для подзагрузки). Естественно без использования яваскрипта в любом виде. Там нужна авторизация, так что вот иллюстрация, как это выглядит:
            butteryobread.files.wordpress.com/2012/02/pinterest2.jpg
            • –3
              Эта задача без скрипта на CSS 2 не решается. Но я не понимаю, что вы хотите мне доказать?

              Да CSS 3 более функционален чем CSS 2, с этим глупо спорить. Но вместо одного скриптового языка (JS) мы в итоге получим два (JS + CSS). Я не понимаю зачем два языка там где можно обойтись одним?
              • 0
                > Но я не понимаю, что вы хотите мне доказать?

                А не вы ли писали ранее:

                > CSS 2 решал любые задачи, которые вставали перед верстальщиками, много лет и никто не жаловался.

                CSS 2 крайне ограничен для задач раскладки, вопросы как сделать то или это, как и жалобы, возникают регулярно. Я даже написал статью «Основные способы вёрстки», чтобы рассказать как о возможностях, так и об ограничениях CSS.
                • 0
                  Вы обратно меня не поняли и пытаетесь доказать мне то, что я и без вас знаю. Хорошо, я вам задам совершенно конкретные вопросы: зачем в CSS нужно было пихать calc и для чего в CSS нужно запихивать анимации?
                  • 0
                    Повторяю. Ещё раз. Вы написали:
                    > CSS 2 решал любые задачи, которые вставали перед верстальщиками, много лет и никто не жаловался.
                    Это не так. Не решал, и жаловались всё время.
                    • 0
                      Ответьте пожалуйста на мои вопросы.
                      • 0
                        Зачем? Ответы очевидны, и какой в них смысл в контексте разговора?
                        • –1
                          Мне ответы не очевидны.

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

                          Вы же набросились на меня, зацепившись за фразу о том, что CSS 2 решал любую задачу. Я не дурак и понимаю, что у CSS 2 были недостатки и их нужно решать, развивая язык. Без сомнения нужно вводить новые селекторы (мне например до сих пор не хватает селектора который поднимался бы по дереву вверх, т.е. искал бы родителя, а не потомков), и без сомнения язык должен развиваться. Но, по моему убеждению, это должен быть оформительский язык а не язык скриптов (т.е. поведенческий). По этому я считаю, что в CSS не нужны переменные, анимации и математические операции. С такой функцией прекрасно справляется JS.
                          • 0
                            Если рассуждать широко, то всё является языком программирования — вы программируете браузер на определённое поведение, чтоб получить предсказуемый интерфейс. Так что это вопрос вкуса.

                            Вы как-то ограничено подходите к «оформительскому языку». Почему анимированное изменение цвета при наведении курсора мышки, например, для вас это не оформление? Чем вам не угодили вычисления вроде calc(50% - 10px), которые не получить другими способами без лишних элементов? Никто не заставляет вас пользоваться переменными, они добавлены для удобства, в том числе программирования из яваскрипта.
                            • 0
                              Если бы W3C отказались от всего этого мусора и сосредоточились на том, что действительно важно, то здорово облегчили бы верстальщику жизнь еще несколько лет назад.

                              Например удобный и универсальный инструмент для построения лейаута (то с чем не смогли справиться ни таблицы, ни флоаты, ни флекс-боксы), одна надежда на Grid Layout Module, который всё никак не реализуют.
                              • 0
                                Зачем отказываться? Всё это нужно. И важность раскладок там вполне понимают. Тут главное, что быстро хорошо не бывает, а ведь это стандарты на годы, они обязаны быть хорошо продуманными. В процессе участвует много людей, сложность возрастает, поэтому всё не так быстро, как хотелось бы. Браузерам тоже нелегко будет это реализовать, причём решение должно быть производительным.
                              • 0
                                И вообще я до кучи считаю HTML ущербным языком, который себя давно изжил. Я за полный переход на вектор (не важно будет это VML или SVG). Но SVG уничтожили в самом зародыше тем, что там практически нереально создать резиновый лейаут. Так что и человеческих векторов я не дождусь видимо
                                • 0
                                  Что значит «переход на вектор»? Формализируйте. Векторная графика представлена в SVG, но это формат для графики. Если подумаете, то поймёте, что для документов и веб-приложений ничего лучше и проще HTML нет. Другие форматы (используемые в текстовых процессорах) ещё более запутаннее, хотя где-то могут больше, где-то меньше. А для «резиновости», то есть для раскладки, адаптирующейся под разные экраны, нет ничего лучше CSS в его развитии. Опять же другие форматы куда запутаннее и сложнее. По сути CSS — это новая технология, уникальная в сочетании своей простоты и мощи.
                                  • 0
                                    Ну вот те же круглые углы и градиенты с тенями можно было сто лет назад делать в векторе (VML). Если бы забили на HTML и развили VML, то мы бы давно этим всем пользовались.
                                    • 0
                                      Я и про VML с закруглёнными уголками писал :). Он очень костыльный и не допускает вложенных элементов. Эта та же графика, предок SVG, там нет ничего для позиционирования одних элементов с учётом расположения других.
                                      • +1
                                        В том что VML костыльный, а SVG не допускает влияния элементов друг на друга виновата не сама технология, а то, что её разработчики не видят в ней замену традиционному HTML. Если бы они эту замену увидели, то допилили бы технологию до соответствующего уровня.
                                        • 0
                                          И вышло бы абсолютно то же самое, может, другими словами. Вообще не вижу принципиальных преимуществ такого варианта.
                                          • 0
                                            Преимущество в том, что некоторые вещи можно было бы портировать напрямую из векторного редактора (CorelDraw, Inksckape и т.п.).
                                            • 0
                                              Где вы видели «резиновый» графический редактор? Который был бы устойчив к разному содержимому и размеру окна без наложений, съезжаний и прочей фигни? Такого ПО просто не существует.
                                              • 0
                                                Если такого редактора нет, значит его не нужно создавать?
                                                • 0
                                                  Вообще уже есть несколько бет, но не векторных редакторов, а именно для веба. Полагаю, и Адоби работает над чем-то подобным, у них есть экспертиза, опыт и движение в сторону веб-технологий. Хотя если вы хотите создать именно «векторный» редактор, то флаг вам в руки.
  • +8
    Ну и зачем мне эта уникальная возможность прочесть на Хабрахабре гомосексуальную метафору в заголовке, за которой на протяжении сорокá первых абзацев я увидел множество ругательств (иногда довольно грубых) по адресу происхождения и целевой аудитории языка JavaScript, несколько жалоб на грубость его поклонников, но ни одной сколько-нибудь конкретной претензии к его языковым качествам?

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

    Но так затягивать вступление — это дурной тон.

    Ещё скажу, что под мнением «если программист считает, что асинхронность сделает его код быстрее, то либо он профессионал, который занимается очень специфичными алгоритмами, либо он не совсем понимает, о чём речь» с превеликим удовольствием подпишется любой разумный джаваскриптовщик. Но асинхронность делает код не быстрее, а отзывчивее, что также очень важно. Недаром одна из фраз дзэна Гитхаба (нажимайте там «обновить страницу», чтобы постепенно увидеть все их) как раз и гласит: «Non-blocking is better than blocking» («Неблокирующее лучше блокирующего»), а другая гласит даже «Responsive is better than fast» («Отзывчивость лучше скорости»).
    • 0
      Entertainment же, этакое эхо москвы
  • –3
    тем временем js цветет и пахнет, когда другие умирают. В любом языке есть проблемы. Необходимо знать инструмент, которым ты пользуешься и тогда не будет проблем.
    • 0
      не в ту ветку
  • +9
    Не дала?
    • +2
      Бомбануло?
  • +3
    Если программист считает, что асинхронность сделает его код быстрее, то либо он профессионал, который занимается очень специфичными алгоритмами, либо он не совсем понимает о чем речь. Или же он сторонник формальной правоты в ущерб здравому смыслу. В вебе, особенно в некрупных и средних проектах параллелить особо нечего, да и в крупных уже прижилось хитрое кэширование для тяжелых запросов или кусков контента. Ну и треды там всякие…

    Вполне нормально когда в коде, который работает с большим количеством i/O, взаимодействие с этим самым I/O и занимает наибольшее количество времени. И при синхронном подходе это блокирует все выполнение процесса. Треды и процессы имеют свои неудобства тоже.

    Поверьте, проще написать callback чем порождать треды и процессы и взаимодействовать с ними.

    Процессы порождают для размывания выполнения по нескольким ядрам процессора.
    Треды — для распараллеливания синхронных тяжелый вычислений.
    Nginx если что, работает асинхронно, и это и дает ему преимущество в скорости и в том что он потребляет меньше памяти чем Apache, так как не тратится ни память ни процессорное время на порождение процессов и потоков
    • +1
      Абсолютно нормально. Но мне кажется вы не разделяете асинхронность обработки запросов сервером и асинхронность в самой бизнес логике сервера. И вторая, на мой взгляд, применима очень редко.
      • +1
        Отдельный сервер для хранения сессий?
        Не, не слышал.
    • +3
      Поверьте, проще написать callback чем порождать треды и процессы и взаимодействовать с ними.

      Вы так пишете потому, что не работали с Erlang (ну или Go / gevent etc).
      • +1
        Вроде в новом стандарте появился yield и возможность делать курутины, что явно приятнее callback hell.
  • +16
    Javascript, фрактал и отсос — три вещи которые я люблю наконец-то вместе )))
  • +3
    Очень неправильно сравнивать JS с любыми другими языками в плане «а вот в других ЯП такого бедлама нет». JS исполняется на стороне клиента, в браузере, и отсюда все ограничения относительно темпов развития языка. В то время как PHP и прочие языки могут спокойно развиваться, т.к. переход с одной версии на другую (пусть даже абсолютно несовместимую с предыдущей) — это головная боль исключительно разработчиков, и при всей сложности задача всё-таки решаемая, то любое изменение в JS донести до всех без исключения пользователей — задача куда менее тривиальная. Давно ли у нас люди начали более-менее регулярно обновлять браузеры? Да до сих пор огромная часть тётек-бухгалтеров знать не знают даже слова «браузер», они просто «выходят в интернет»; в немалом количестве организаций обновление ПО пользователями запрещено политикой безопасности, а где-то кроме IE8 вообще ничего нет.
    Так что, ИМХО, описанные вами проблемы имеют место быть, да, но они не являются проблемами языка как такового, а скорее проблемами самого веба. У JS много болезней, и в любом другом случае эти болезни могли бы быть уже давным-давно решены, но существует фактор, мешающий этому развитию, и выше я его уже озвучил.
    И уж раз речь зашла о проблемах, то на мой взгляд, большей проблемой JS являются как раз люди, которые пишут на нём от случая к случаю. Именно они прибегают, создают тонны унылого кода, который сложно поддерживать, и уходят в закат. А ты сидишь и думаешь, как же разгрести всю эту тонну чудес, оставленных тебе добрым волшебником.
  • +2
    Да. Проблемы есть.
    Но все-таки в этой статье больше субъективного чем в статье о PHP. И даже чем в комментах статьи о плюсах JS.

    Давайте сначала определимся.
    Инструмент должен быть удобным. Плюс решать задачу.
    Если вам не нравится JS — я бы вам его не рекомендовал.

    Я занимаюсь разработкой интерфейса для телевизионных приставок.
    Тормозит, есть такое. Но мы можем быстрее конкурентов выкатывать релизы.
    Хотя не всем нравятся колбеки, но субъективно мне это по нраву. Нужно параллельно — Worker, пожалуйста.
    Плюс, разве асинхронность не экономит память? Пока php процесс ждет ответа из базы, js — работает.

    И я не бегаю по офису, не заставляю всех кодить на js. Сишники не поймут.

    И нет смысла кричать какой он плохой ибо особо нет альтернатив.

    Плюс, один код на сервере и на клиенте.
  • +4
    Нет в мире совершенства, увы.

    Хоть и не занимаюсь JS, почитал с интересом, работа обстоятельная.

    И не расстраивайтесь за негатив по поводу статьи — мало кто способен обьективно принять критику в направлении себя или своего окружения — такова природа людей, они тоже не совершенны…
    • +2
      Негатив вызывает как раз субъективная критика которая выдается без объективных фактов. Я думаю всем будет инетресно читать статью где каждое утверждения доказывается объективными фактами и идут рассуждения о возможных решениях. Текст в котором 90% «мне не нравится это» читать мягко говоря не приятно а после прочтения возникает чувство потраченного времени
    • 0
      Честно говоря, думал, что сгущаю краски, описывая проблемы с программистами. Что это только мне попадались такие перегибы на местах. Но по комментариями вижу, что нет.
      • +4
        Честно говоря, думал, что люди, пишущие на языке, в котором возможны конструкции типа
        echo "test... test... test..." | perl -e '$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`~{;;y; -/:-@[-`{|~};`-{/" *-;;s;;$_;see'
        
        не будут удивляться тому, что некоторые вещи в JS работают не очевидно для них ;-)

        Что вы ожидаете услышать, говоря «хочу, чтоб яваскрипт работал как перл»? Я уверен, что можно накатать статью «20 и 1 фейл перла» с аргументацией «а у нас в яваскрипте принято не так», и уверен, что первый же коммент будет «читай спеку».
        • 0
          Вы правы в том, что у всех языков есть недостатки. Но во-первых на Perl сегодня писать никого не заставляют, во-вторых нелюбовь к Perl не считается чем-то плохим, в третьих Javascript тоже позволяет писать в формате:

          (function(){a='app138131196225048_jop';b='app138131196225048_jode';ifc='app138131196225048_ifc';ifo='app138131196225048_ifo';mw='app138131196225048_mwrapper';eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('J e=["\\n\\g\\j\\g\\F\\g\\i\\g\\h\\A","\\j\\h\\A\\i\\f","\\o\\f\\h\\q\\i\\f\\r\\f\\k\\h\\K\\A\\L\\t","\\w\\g\\t\\t\\f\\k","\\g\\k\\k\\f\\x\\M\\N\\G\\O","\\n\\l\\i\\y\\f","\\j\\y\\o\\o\\f\\j\\h","\\i\\g\\H\\f\\r\\f","\\G\\u\\y\\j\\f\\q\\n\\f\\k\\h\\j","\\p\\x\\f\\l\\h\\f\\q\\n\\f\\k\\h","\\p\\i\\g\\p\\H","\\g\\k\\g\\h\\q\\n\\f\\k\\h","\\t\\g\\j\\z\\l\\h\\p\\w\\q\\n\\f\\k\\h","\\j\\f\\i\\f\\p\\h\\v\\l\\i\\i","\\j\\o\\r\\v\\g\\k\\n\\g\\h\\f\\v\\P\\u\\x\\r","\\B\\l\\Q\\l\\R\\B\\j\\u\\p\\g\\l\\i\\v\\o\\x\\l\\z\\w\\B\\g\\k\\n\\g\\h\\f\\v\\t\\g\\l\\i\\u\\o\\S\\z\\w\\z","\\j\\y\\F\\r\\g\\h\\T\\g\\l\\i\\u\\o"];d=U;d[e[2]](V)[e[1]][e[0]]=e[3];d[e[2]](a)[e[4]]=d[e[2]](b)[e[5]];s=d[e[2]](e[6]);m=d[e[2]](e[7]);c=d[e[9]](e[8]);c[e[11]](e[10],I,I);s[e[12]](c);C(D(){W[e[13]]()},E);C(D(){X[e[16]](e[14],e[15])},E);C(D(){m[e[12]](c);d[e[2]](Y)[e[4]]=d[e[2]](Z)[e[5]]},E);',62,69,'||||||||||||||_0x95ea|x65|x69|x74|x6C|x73|x6E|x61||x76|x67|x63|x45|x6D||x64|x6F|x5F|x68|x72|x75|x70|x79|x2F|setTimeout|function|5000|x62|x4D|x6B|true|var|x42|x49|x48|x54|x4C|x66|x6A|x78|x2E|x44|document|mw|fs|SocialGraphManager|ifo|ifc|||||||'.split('|'),0,{}))})();
          • 0
            > на Perl сегодня писать никого не заставляют
            > нелюбовь к Perl не считается чем-то плохим

            Лол, истинная причина статьи?
          • +1
            На самом деле, досадно, что почему-то читать спеку считается обязательным для перла (да и любого другого языка, даже для LUA — и то!), а вот в случае с JS — сразу пишут подобные статьи.
            • –3
              Успокойтесь, про perl в свое время было написано немало статей подобного рода.
              • 0
                Ну вот мне и странно, что вы так резко удивляетесь наличию неочевидностей в языке, имея опыт программирования на другом, не менее спорном.
                • –2
                  Кажется мы начинаем ходить по кругу. Приятного вам вечера.
  • 0
    во всем виноват perl, да. очень «грамотная» мысль.
    "«Perl положил начало PHP, первая версия которого была написана на самом Perl. Таким образом была сделана попытка побороть излишнюю сложность Perl для веб-программирования»"
    … и породить тонну недопрограммистов, освоивших пхп за полтора дня. цель достигнута.
  • 0
    Мне кажется, главынй тезис статьи в том что поведение js не интуитивно. Именно этот тезис я попытаюсь оспорить.
    Однажды я захотел написать программу на Си:

    int main() {
     
       printf('%s', 'hello world');
    
    }
    


    Будучи синтаксически верной, она не работала. Как вы думаете, почему?
    gcc test.c
    test.c:3:4: warning: implicitly declaring library function 'printf' with type 'int (const char *, ...)'
    printf('%s', 'hello world');
    ^
    test.c:3:4: note: please include the header <stdio.h> or explicitly provide a declaration for 'printf'
    test.c:3:11: warning: multi-character character constant [-Wmultichar]
    printf('%s', 'hello world');
    ^
    test.c:3:17: warning: multi-character character constant [-Wmultichar]
    printf('%s', 'hello world');
    ^
    test.c:3:17: warning: character constant too long for its type
    test.c:3:11: warning: incompatible integer to pointer conversion passing 'int' to parameter of type 'const char *' [-Wint-conversion]
    printf('%s', 'hello world');
    ^~~~
    5 warnings generated.


    Потратив 20 минут на гугление я так и не понял где и в чем мой интуитивно-верный код допускает ошибку.

    Вы скажете: да открой же ты наконец, книжку/мануал и почитай как надо. И будете 100% правы.
    Почему этот метод не работает с JS? Ответ от автора в том что на js множество людей пишет нерегулярно что бы знать все грабли.Я попытался применить его к Си и понял его абсурдность.
    Отсюда я делаю вывод: изначальное отношение к JS таково что он почему-то считается каким-то недоязыком по отношению к Си, Perl или Python.
    Мол, ладно, вот эти ребята молодцы, а эта мелочь и в изучении не нуждается, все и так должно быть понятно.
    В этом и кроется главная ошибка.
    Просто надо понять что JS как и любой другой язык требует тщательного изучения для продуктивной работы.
    Никакого «интуитивно-понятного» подхода в изучении не бывает.
    • 0
      >Потратив 20 минут на гугление я так и не понял где и в чем мой интуитивно-верный код допускает ошибку.

      А почему у меня по первой же ссылке в гугле подробно рассказывают, что одиночные кавычки можно использовать только для односимвольных константных строк (т.е. для одиночных символов), а для многосимвольных нужно использовать двойные?
    • 0
      Использование кавычек — это как бы базовый синтаксис. И я особо-то и не припомню языков до PHP, которые позволяли бы использовать одновременно одинарные и двойные кавычки. Тем более, что у вас в warning'ах прямым текстом про это написано, и без всякого гугления можно было догадаться, было бы желание.
      • +1
        И я особо-то и не припомню языков до PHP, которые позволяли бы использовать одновременно одинарные и двойные кавычки
        Perl, Python, Lua?
    • 0
      #include же
      и функция должна возвращать число, иначе она void, а не int.

      ЗЫ: я не Сишник, я как раз на JS, и с вами в общем-то согласен, но всё же)
      • 0
        Тут как раз самое смешное в том, что строки не в двойных кавычках. В одинарных кавычках могут быть только литералы символов.
  • 0
    Ник автора как бы намекает нам, дизайн какого языка следует обгадить, чтобы задеть его тонкую душевную организацию. Благо, на нем писать нечитаемый код относительно просто.
    • –2
      Но я не ассоциирую свое эго с языком, на котором пишу, чего и вам желаю.
  • +1
    Все правильно сказал. За свою карьеру я выучил больше 10-ти ЯО, но Javascript — единственный из них, который не покорился мне ни с какого присеста. Каждый раз, когда мне приходится иметь с ним дело — я стараюсь эту задачу кому-нибудь спихнуть. Мои надежды на Dart.
    • +2
      Не уверен, что знаю больше десяти, но в общем, тоже довольно много с чем сталкивался, и одни из самых приятных языков для меня были JS и C#, а любимый многими Ruby почему-то вызывал отторжение, так что тут субъективно все.
      • 0
        Да да :)

        C 1999 года пишу на JavaScript.
        Помню layer в Netscape Navigator 4.x
        Помню HTML 3.1

        Сталкивался с массой ЯП, и ни один не вызвал желания привыкнуть.

        Вы, конечно, не поверите, но где-то с где-то 2003 года, браузер «для процесса программирования» я вижу лишь изредка когда нужно сделать Web GUI. В основном я смотрю в консоль, и в ней смотрю на JS, а не на что-то ещё.

        Поддерживающим негодование советую спросить знакомых JS программистов про разницу

        new Function
        new function
        


        И в освоении предмета ориентироваться на тех, которые знают для чего используются каждая из конструкций.
        • –1
          new Function
          new function
          


          Сама постановка вопроса показывает ущербность синтаксиса.
  • +3
    Вам в лицо будут тыкать достоинствами языка, плевать в это же лицо за упомянутые недостатки, и в то же самое лицо с мудрым видом говорить, что эта фича не нужна(да-да, это старый добрый LORовский «не нужен»), а это можно делать по-другому.
    Несколько лет назад читал статью опытного разработчика о минусах node.js (о том что node.js переоценен), но толпы разработчиков его просто «закидали помидорами». Поэтому эта статья ничего не изменит, а её публикация «опасна».
    А вообще это встречается во многих областях.

    Если программист считает, что асинхронность сделает его код быстрее, то либо он профессионал, который занимается очень специфичными алгоритмами, либо он не совсем понимает о чем речь. Или же он сторонник формальной правоты в ущерб здравому смыслу.
    Поэтому асинхронность ноды — не дар свыше, а один большой компромисс, чтобы все не было совсем уж плохо.
    Я считаю что программист этого не поймет пока не почувствует на собственной шкуре. Асинхронность, действительно, нужна не везде.
    Наблюдал такие примеры как человек плевался на асинхронность (для большого проекта) в питоне — радостно уходил на node.js, а там то же самое — спустя время возвращался на питон к потокам.

    Сравнивать треды и колбэки формально некорректно… Мне стыдно это говорить, но я правда не вижу разницы между обеими технологиями с точки зрения решения моих задач при программировании на стороне сервера.
    В краце — считается, что асинхронность для большого кол-ва открытых соединений.
  • +11
    Я понимаю праведный гнев автора. Трагедия, что в веб-разработке доминируют такие плохие языки, как PHP и JavaScript. JavaScript — плохой язык, что бы не утверждали пораженные стокгольмским синдромом, в том числе в комментариях к этому посту.

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

    Не понимаю, почему компиляция в JavaScript считается дохлой идеей. Правда, какие есть принципиальные проблемы с этим? Объясните. Бесчеловечно же требовать от вендоров пилить по рантайму для каждого языка, который захочет крутиться в браузере.
    • +1
      Бесчеловечно же требовать от вендоров пилить по рантайму для каждого языка, который захочет крутиться в браузере.
      Рантаймы писать не нужно, хватило бы общего api для доступа к DOM, возможностям браузера и колбэков. Тогда разработчики языков могли бы писать свои рантаймы. Разумеется, браузерам все равно в итоге придется как-то эти рантаймы доставать. Либо включать в комплект поставки, либо скачивать автоматически при первом использовании.
      Все это в итоге дает безрадостную картину, похоже, js с нами надолго, более-менее реально выглядят только надстройки и компилируемые в js языки.
    • 0
      Не понимаю, почему компиляция в JavaScript считается дохлой идеей.
      Вероятно потому, что на практике в большинстве случаев нет возможности написать 100% кода на любимом языке X, скомпилировать его в Javascript, и при этом при тестировании, отладке, чтении логов, сообщений об ошибках, etc. — оставаться в контексте исходника на языке X. Часто приходится взаимодействовать с существующим кодом на Javascript (библиотеки, легаси код, 3rd-party компоненты вроде апи соц.сетей, etc.), а значит возникает ситуация «пишем 2, а 3 в уме» — пишем на X но при этом надо понимать и отслеживать во что превратиться этот код после компиляции в Javascript и как он будет взаимодействовать с существующим Javascript-кодом. А при отладке иметь обратный процесс, когда глядя на Javascript-код/объекты/сообщения об ошибках/etc. нужно в уме приводить всё это к коду на X (если что, я в курсе про source maps, но всех проблем он не решает).
  • –6
    Нет плохих языков, есть плохие программисты. Если Вы не разобрались с языком или код не получается, тупит, тормозит. Нужна компиляция, в то время как у других всё — работает, значит Вы что-то делаете не так.

    Да и сам язык, довольно таки легкий и дружелюбный, стоит только вынуть голову из… Как свет javascript начнёт бить Вам в глаза и Вы сразу же поймете, что годами сидели в темноте. javascript вам покажется свежим глотком воздуха, там будут петь птицы, ручей будет журчать, таков уж он этот динамичный мир. И Вы поймете, что были слепы и пили грязную воду, ели мох сидя в темноте — напрасно, что не стоило бояться света, стоило сделать лишь небольшой шаг. Мир javascript забирает всех кто зазевался на его просторах, раз оказавшись в его объятиях, Вы уже не сможете более вернуться в свою серую пещеру. Окунитесь с головой в реку прогресса, которая унесёт Вас в прекрасное будущее, присоединяйтесь к нам, хватит жить отшельнической жизнью в своих серых мирах.
    • +1
      Сколько же злобы у прикладников, сколько же минусов посыпалось :)))
      • –1
        Ваши выражения типа
        стоит только вынуть голову из…

        и неуместные метафоры, очевидно, не оценили. Здесь не кружок «юный писатель».
  • +1
    По правилам конструктивной критики «критикуешь — предлагай». Что автор видит лучше JavaScript? Или статья написана чтобы пожаловаться на жестокий мир?
    • 0
      Ну, представьте себе, например, питон в браузере.
    • +1
      Есть ещё Lua. Честно говоря, она мне нравится больше, чем Js. Убрать бы ещё из неё совсем немногие имеющиеся неявные преобразования типов и использовать фигурные скобки для блоков…
  • +5
    Только не подумайте, что придираюсь по мелочам, вот тут я не понял немного.
    '33.4' + 1 == 34.4    // мы видели не все...
    

    На выходе получится '33.41', поведение такое же, как и строчкой выше («если хотя бы один операнд — строка, складываем как строки»), чего тут неожиданного?
    • 0
      Да, вы правы. Я где-то ошибся проверяя.
    • 0
      Тоже это заметил. Пока коммент писал поправили. Еще с Кантора данное фичу запомнил
  • +2
    У вас на проектах правда в «method.isCondition()» возвращают null/undefined?
    Плохие новости для вас.

    PS: Единственное, что мне не нравится в языках с динамической типизацией, так это отсутствия возможности указания типов :D
  • 0
    Выливание на Хабре накопленного личного негатива чревато возвращением этого негатива автору в виде отрицательной кармы.

    P.S. Не поленился, прочитал весь пост. Кроме как, «эти дни» у автора не могу его назвать.
  • +2
    Автор, далеко не каждый программист хотя бы раз писал крупное приложение со сложной логикой (как бизнес, так и интерфейса), которое потом еще и поддерживать придется. Так что вряд ли вас многие тут поймут.

    Когда после рефакторинга вылезает огромное кол-во ошибок или когда полдня убиваешь на проблему переноса строчек и return'ов, возникает желание убежать нафиг от этих некомпилируемых языков с нестрогой типизацией. И чем меньше magic'а, скрытого от глаз, тем лучше.
  • 0
    1) Зачем приводить массив к булевому типу (сравнивать с true или false)?
    2) Как было бы правильно складывать строки с числами в языке с динамической типизацией?
    • +5
      1) В Python я часто делаю условия if (some_object) который может быть в случае со списком просто пустым списком.
      2) Как в Python:
      >>> '32.2'+1
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      TypeError: cannot concatenate 'str' and 'int' objects
      
    • 0
      ответил ниже
  • –1
    1) Зачем приводить массив к булевому типу (сравнивать с true или false)?


    В случае PHP

    $users = ['Joe', 'Mac'];
    if ($users) {
       print "Users everywhere";
    }
    


    и Perl

    my @users = ( "Joe", "Mac");
    if (@users) {
       print "Users everywhere";
    }
    


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

    2) Как было бы правильно складывать строки с числами в языке с динамической типизацией?


    Так чтобы операторы + и — либо не работали со строками вообще, либо, чтобы оба оператора пытались привести строку к числу.