Найти тему
ZDG

Языки программирования 9: JavaScript

Оглавление

JS появился в 1995 году и в некотором смысле был сиамским братом языка PHP, разделив его нехорошую репутацию.

Предыдущая часть:

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

Но именно симбиоз PHP+JS позволял строить технологичные сайты.

Уже не имеет смысла говорить о самых первых версиях JS, как и о первых браузерах. Основная проблема была в том, что конкурирующие компании назло маме друг другу продвигали свои стандарты. Что-то работало в Netscape Navigator (помните такой?) и не работало в Internet Explorer, или наоборот. Этот кошмар длился годами, и продолжается сейчас, но большая часть возможностей языка всё-таки выравнялась.

Это Java?

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

Первоначально JS назывался LiveScript, а в браузерах также работала альтернативная технология – Java-апплеты от компании Sun. Компания Netscape, разработчик JS, была партнёром Sun и назвала свой язык как бы в смысле компаньона Java-апплетов. Которые потом тихо умерли, и их заменил Flash, который потом тоже умер, и остался лишь JS.

Браузерное окружение

Работая в браузере, JS имеет доступ к HTML-документу в виде уже готовых объектов. Например, объект window это окно браузера, document это документ, загруженный в окно, document.forms это веб-формы, содержащиеся в документе, и т.д. JS может обратиться к любому узлу документа, изменить его, удалить или добавить новый:

document.write("Hello World");

То есть модифицировать страницу, не загружая её повторно с сервера.

Впервые с этими возможностями я познакомился, когда зашёл на сайт id Software, который выглядел примерно так:

таких больше не делают...
таких больше не делают...

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

Событийная модель

На JS можно написать полноценную программу, но она не может работать в браузере постоянно, потому что пока работает JS, браузер просто висит. Подход там другой. В браузере есть диспетчер событий, который генерирует события: подвинулась мышь, нажата клавиша, загрузилась картинка, истёк таймер, окно потеряло фокус и т.д. На каждый тип события можно повесить обработчик в виде кусочка JS, который сделает что надо (в примере выше – заменит картинку на другую), и закончится. После чего всё будет тихо до следующего события.

Такая архитектура называется event-driven и часто используется в пользовательских интерфейсах, но также и в очередях, сетевых запросах и т.п.

Но из-за "кусочной" организации программирование на JS стало (в некотором временном периоде) ассоциироваться с грязным кодингом, как и на PHP. Вставки в HTML, написанные на PHP и JS, благородно оттеняли друг друга.

Node.js

Это "серверная" версия JS, которая вырвалась из браузерной тюрьмы и стала языком и для бэкенда тоже – ну то есть таким же, как Java или PHP или Python. Облегчение для веб-разработчиков, которые могут писать и клиент, и сервер на одном языке, а не на двух.

Всё является объектом

JS выделяется своим ошеломительно наглым подходом к работе с объектами. Любой объект можно создать прямо на лету, используя JSON-нотацию:

-2

Собственно, она называется JSON, потому что JavaScript Object Notation, и популярна среди других языков, и вообще уже стандарт для обмена данными. Это по сути словарь, где ключи это строки или числа, а значения – от скаляров до массивов и снова объектов, то есть объекты можно вкладывать в объекты.

-3

Естественно, с такими объектами можно и дальше творить что угодно.

Но самое дикое для программистов, учившихся на Паскале или C – то, что функция это тоже объект! Её можно тоже создать на лету и присвоить чему-нибудь, например:

-4

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

-5

С виду обычная функция, но... мы создали в ней свойство x = 100! И вызов этой функции напечатает: Hello world 100. Это вообще как?

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

ООП

В JS есть объекты, свойства объектов, методы (функции), есть даже схема наследования, которая сильно отличается от привычной. Подробно она описана здесь:

Но нет классов. Тем не менее, всё это примерно отображается на классическое ООП: вместо классов именованные функции с конструкторами, вместо методов анонимные функции и вместо наследования прототипы (см. ссылку).

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

Вавилонская башня

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

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

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

Но ящик Пандоры уже открылся. Сначала jQuery стал де-факто обязательным компонентом, потом поддержка Bootstrap, потом внедряем новую модную библиотеку или фреймворк React или Angular или Vuе, которые тащат ещё тонны зависимостей – и вот сайт, который в общем-то ничего особенного не делает, становится супер-тяжеловесом.

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

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

-6

Известен случай, когда одна маленькая зависимость сломала интернет, после того как автор удалил её из репозитория. И этой зависимостью была... функция выравнивания строки пробелами, значащий код которой занимает 6 строк. Вдумайтесь. 6 строк, которые всем было лень писать, и было "эффективнее" полагаться на внешнюю зависимость.

-7

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

Параллельно появился язык TypeScript, который был типизированным JavaScript – естественно, для улучшения качества кода. Но он не работал сам, его надо было потом компилировать в обычный JS с помощью отдельного транслятора. Значит, дополнительно нужен транслятор, который, по отзывам, настраивать дольше и проблематичнее, чем просто написать код вручную. Появилось также подмножество asm.js с особыми правилами, нацеленными на улучшение производительности.

Как перестать беспокоиться и начать программировать

В сети можно найти уже довольно много высказываний людей, которым осточертели громоздкость и утерянный смысл экосиcтемы JS. Могу даже процитировать одно из них в моём переводе:

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

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

Заключение

Из планируемого краткого обзора получился какой-то манифест, видимо потому что я где-то в глубине души люблю чистый JS.

  • Доступность в любом браузере (ну кроме lynx :)
  • Доступность не только в браузере (node.js)
  • Свободная работа с объектами, функции тоже объекты, всё объекты
  • Очень своеобразное ООП, но также очень интересно устроенное
  • События управляют программой
  • "Улучшенные" варианты языка требуют дополнительных трансляторов
  • Не перебарщивать с зависимостями

Читайте дальше: