JavaScript — ужасный язык программирования. По сравнению с другими распространёнными языками он выглядит генетическим уродом. Дело даже не в отсутствии многопоточности, или статической типизации, или того, что node_modules для простого проекта занимают сотни мегабайт, а в том, что в JavaScript столько стилей и подходов, что семь человек одну и ту же несложную задачу могут написать на нём семью различными способами. Каждый из них с трудом будет понимать, что написал другой, и тихо материться. Причем, так напишут и новички, и опытные программисты, которые просто привыкли писать по‑своему или захотели выпендриться.
Синтаксис и семантика JavaScript неадекватно усложнены и запутаны, что явилось следствием того факта, что его основа была придумана на коленке за десять дней, и в последующем изменена множеством акторов, каждый из которых преследовал свою цель и видение вместо следования единой стратегии.
Важная цель при разработке языка программирования — сделать так, чтобы он был понятен, логичен и хорошо сформулирован, не приводил к возникновению странных тупиковых ситуаций. Но JavaScript даже близко не подвели к достижению этой цели. С каждым выпуском языка его странности растут как снежный ком, неизменно усугубляя ситуацию. В нем появляется множество тупиковых и критических проблем
Дуглас Крокфорд, программист, автор формата JSON, исследователь JavaScript
Принято считать, что Java — серьезный язык для серьезных проектов, а JavaScript — лёгкий скриптовый язык для веб‑страничек. В принципе, да, вот только код на Java получается намного проще, чище и читабельней кода на JavaScript. В нём на порядок меньше всевозможных абсолютно ненужных рудиментарных заморочек. И, в то же время, с возможностями Java как языка можно реализовать практически всё.
Я пишу преимущественно на JavaScript (Vue.js). За неимением альтернатив, JavaScript удобен для фронта, для несложных скриптовых блоков кода в SFC и ES модулей. Когда обучаю детей программированию, то предпочитаю начинать с простой веб‑разработки — сделать HTML страничку, скриптом добавить небольшую анимацию, потом загрузить через fetch
прогноз погоды с открытого API и красиво отрисовать его. Это их заинтересовывает, знакомит с различными веб технологиями в понятной форме и даёт энергию для дальнейшего изучения программирования. Так получилось, что этот язык вкупе с веб разработкой удобен для знакомства с IT.
На JavaScript можно написать несложный бэкенд API на Express.js или serverless функцию, но это его потолок. Использовать его для чего‑то серьезного на серверной стороне — ошибка. Небольшие скрипты на JavaScript удобно писать, но когда кода много, логика сложна, и пишут это разные люди, то кодовая база превращается в месиво из‑за отсутствия и следования не столько даже `code style guide`, сколько `language style guide`. Это как люди с одним, вроде бы, формальным разговорным языком, но разными диалектами, плохо понимающие друг друга.
Выпуски новых редакций стандарта ECMAScript не приводят к устранению серьезных проблем JavaScript, а иногда и создают новые проблемы. Комитет по стандартам имеет ограниченные полномочия по коррекции языка. Его представители обладают практически безграничной властью над развитием языка, делая его все более сложным и странным. У них есть достаточные полномочия, чтобы не усугублять ситуацию, но заинтересованы ли они в этом?
Дуглас Крокфорд, программист, автор формата JSON, исследователь JavaScript
Но отсутствие стандартов и узаконенных лучших практик в написании кода это далеко не всё.
Все уже привыкли к зоопарку фронтенд фреймворков, когда специально учишься писать под конкретный, если хочешь на нем работать. И это понятно — если используешь библиотеку, нужно жить в рамках её интерфейса. Но это только часть айсберга. Многие npm
пакеты тоже должны быть адаптированы или сделаны под этот фреймворк, образуя свою «экосистему». И меняя фреймворк надо менять и экосистему.
Есть еще сборщики. В том числе и для бэкенда их используют. И их не один, и не два, и не три. И чтобы в твоем прикладном коде просто отобразить на странице картинку, ты должен подчиняться правилам конкретного сборщика и выполнять нетривиальные миграции при переходе с одного на другой.
А у сборщиков есть плагины, и чтобы отобразить на странице svg иконку, ты должен подчиняться правилам выбранных плагинов. И еще есть js runtimes. И их тоже уже не только Node.js — Deno, Bun, Cloudflare Workers, Netlify, Vercel Edge, AWS LLRT, — один другого краше. А под ними — js движки. V8, SpiderMonkey, Boa, QuickJS и еще несколько десятков.
Вроде бы уже дно? Нет, у движков и сборщиков есть еще версии, и то, что работает на Node 16, не работает на Node 20, и наоборот.
Всё? Почти. Окружение, включая операционные системы. Нравится удобство Cloudflare workers — пиши под Cloudflare. Supabase? Только Deno до недавнего времени. Хочешь быстрый Bun? Переписывай всё под него. И он на Windows не работает пока, если что. Netlify, Vercel, AWS Lambda — у каждого свои требования и особенности.
Ощущение, что всё-таки что-то забыли
Пакетные менеджеры — npm, yarn, pnpm, — и их деривативы: Yarn workspaces, Lerna и даже новые реестры пакетов типа jsr.io
Когда изобрели Java, у нее был девиз: Write once, run everywhere. Не сильно ошибусь, если скажу, что программу, написанную на С или Java 25 лет назад можно без особых проблем скомпилировать и запустить и сейчас. А как этот слоган применим к JavaScript? Никак. Ты должен ходить везде с чемоданом набитым своим фреймворком, экосистемой библиотек под него, сборщиком, плагинами к сборщику, пакетным менеджером, js рантаймом, движком и только по своим хостингам. И всё чтобы было своих определенных версий. И ходить можно только очень небольшое количество лет (иногда от силы 2–3 года), после которых ты вместе со всем этим чемоданом безнадежно устареешь.
Может фронтенд‑разработчики честно подсчитают для себя, сколько процентов их рабочего времени за последние годы ушло на переписывание кода следуя моде или потоку времени с одной библиотеки/фреймворка/сборщика/пакетного менеджера/js runtime на другую, или из‑за апгрейда её/его версии? То есть, техническая работа без, по сути, изменения функционала программы. Для JavaScript это воспринимается как естественная данность, следование фарватеру эволюции, хотя для других языков это дикость.
И, самое веселое, что со временем всё не упрощается и унифицируется, а совсем наоборот.
Теперь представим архитектора или техлида в здравом уме, который должен решить, на чем писать нетривиальное серверное приложение с расчетом на работу дольше одного года. В каких случаях он выберет JavaScript? Видны три варианта:
Он/его команда больше ничего не умеют
Его вынуждают это сделать силой
Он не совсем в здравом уме.
TypeScript может давать локальное симптоматическое лечение, но в целом ситуацию только ухудшает.
На бэкенде еще есть возможность выбрать для работы другой язык, но на фронте глобально поможет только создание и внедрение нового с нуля, как это было с Java или C#, с продуманными спецификациями языка программирования и виртуальной машины и всех нужных API.
Было множество попыток как создать новый язык, так и написать компилятор в JavaScript какого‑то существующего (краткий список). Например, Google AdWords был написан на Java с последующей компиляцией в JavaScript (хотя это больше попытка работы с UI). Однако ничего не получило достаточного распространения.
Так что пока JavaScript ужасный язык программирования, но другой альтернативы нет.
Поэтому, для минимизации рисков, в своей работе приходится следовать нижеописанному принципу и использовать только самые необходимые, ясные и разумные элементы JavaScript, инвариантные и для большинства других языков.
Вот мой самый эффективный инструмент для наилучшего использования языка программирования:
Если что‑то в одних случаях полезно, а в других — опасно, и есть более подходящий вариант, нужно именно им и воспользоваться.
Взяв этот принцип на вооружение, я всегда стараюсь свести язык к его меньшей и лучшей части, чтобы по возможности избежать того, что с большой долей вероятности может привести к возникновению ошибок
Держитесь подальше от всего, что приводит к тупиковым и крайним ситуациям. Не углубляйтесь в этот мрак. Оставайтесь в той части языка, где все просто и понятно. Там есть все, что вам нужно для написания хороших программ. Истинное мастерство проявляется в создании хороших программ, код которых легко читается, сопровождается и не содержит ошибок. Оптимизация с целью использования характерных особенностей приводит к обратным результатам.
Дуглас Крокфорд, программист, автор формата JSON, исследователь JavaScript
Все цитаты и иллюстрация взяты из его книги «How JavaScript works»