Язык JavaScript
Эдуард Пройдаков
JavaScript – язык многофункциональный интерпретируемый язык программирования с объектно-ориентированными возможностями. Появился он в 1995 г. как часть некогда самого популярного в то время браузера Netscape Navigator; разработчик Брендан Эйх (Brendan Eich), сотрудник компании Netscape. Главная задумка языка состояла в том, чтобы с его помощью сделать веб-страницы динамическими, что невозможно используя только HTML. JavaScript позволяет на веб-странице выполнять вычисления, взаимодействовать с пользователями, реагировать на события, получать и использовать данные из Интернета, выводить графику и многое другое. Потом JavaScript появился в других распространённых браузерах. В настоящее время JavaScript используется в качестве фронтенд-языка на 97% сайтов, поскольку ему практически нет альтернативы, а кроме этого он нужен и для мобильных приложений.
JavaScript стандартизован ассоциацией ECMA, описан в стандарте ECMA-262 (существуют различные версии стандарта, последняя пятая) и согласно ему язык официально называется ECMAScript. Но этим неудобным названием мало кто пользуется, обычно только в случае, если необходимо явно сослаться на стандарт. В дополнение к спецификациям ECMA-262 ассоциация ECMA разработала ещё стандарт ECMA-357, в котором было стандартизовано расширение JavaScript, известное под названием E4X, или ECMAScript for XML. С помощью этого расширения в язык была добавлена возможность манипулировать XML-документами. ECMAScript 2022 – это новый стандарт JavaScript, который был выпущен в июне 2022 года.
JavaScript тесно связан с языком гипертекстовой разметки HTML (Hypertext Markup Language), который используется для форматирования контента страниц, задания их структуры: абзацев, заголовков и разделов и т.д. Поэтому код JavaScript упакован в разметку HTML. Ниже приведена простая страница HTML, которая показывает пример такой упаковки:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Заголовок вашей HTML-страницы </title>
<script>
Ваш код JavaScript обычно размещается здесь
</script>
</head>
<body>
Содержимое веб-страницы размещается здесь.
</body>
</html>
Таким образом, программист включает код на JavaScript прямо в веб-страницу, которая потом загружается в браузер. Никакой компилятор или интерпретатор вызывать не надо – браузер сам сделает всё необходимое для исполнения написанного кода. Эта встроенная версия JavaScript запускает сценарии, внедренные в HTML-код веб-страниц, и называется клиентским языком JavaScript, чтобы подчеркнуть, что сценарий исполняется на клиентском компьютере, а не на веб-сервере. О серверном JavaScript, такой тоже есть, я расскажу отдельно.
Для отладки HTML-файл с кодом на JavaScript нужно просто загрузить с диска в браузер и он будет исполнен. Более того, в HTML-страницу можно включить файл (например, code.js) с JavaScript-кодом.
<script src="code.js"></script>
Тут можно ещё упомянуть, что совместно с HTML, чтобы определить стиль оформления, отделённый от структуры страницы, используется технология каскадных таблиц стилей CSS (Cascading Style Sheets), которая позволяет определить цвета, шрифты, границы, макет страницы. Вещь необходимая веб-мастеру, но с этим ему ещё нужно научиться работать. Это к тому, что JavaScript включается в HTML-страницу точно так же, как и CSS, т. е. он просто встраивается прямо в документ в тегах <script>.
Появились встроенные реализации JavaScript, существующие отдельно от браузеров. Это JavaScript Engine – движок, который может выполнять программу на JavaScript, в том числе на сервере. Один из самых популярных, движок с открытым исходным кодом V8 – был разработан корпорацией Google, он написан на С++; содержит JIT-компилятор, транслирующий исходный текст на JavaScript машинный код, который тут же оптимизируется и выполняется. Можно отметить и Rhino – также движок с открытым исходным кодом, написанный на Java. Разработан компанией Mozilla.
Движок SpiderMonkey – SpiderMonkey был написан Бренданом Айком во время его работы в Netscape Communications, а позднее сделан открытым. В настоящее время SpiderMonkey поддерживается компанией Mozilla Foundation. Наконец, JavaScriptCore – движок с открытым исходным кодом, разработанный корпорацией Apple для веб-браузера Safari.
Среди других языков, отмечу Jscript и Microsoft JScript.NET – это адаптации JavaScript, выполненные Microsoft. Многие языки транскрибируются в JavaScript. Это в первую очередь TypeScript, Dart, Elm, PureScript и CoffeeScript.
Важная особенность JavaScript – безопасность. JavaScript не может получить доступ к памяти компьютера и к процессору, на котором исполняется скрипт напрямую. Нет доступа и к файловой системе, Когда JavaScript выполняется в браузере, он имеет доступ к специальным браузерным API, и работает через них. Для доступа к оборудованию, например к микрофону, видеокамере, нужно постоянно получать подтверждение от пользователя.
С точки зрения синтаксиса язык JavaScript напоминает C, C++ и Java такими программными конструкциями, как if, цикл while, операторами && и ||, и др. Одно из наиболее распространённых заблуждений о JavaScript состоит в том, что этот язык представляет собой упрощённую версию языка Java. Однако это совсем не так и, кроме указанной выше синтаксической схожести, эти два языка между собой почти ничто не связывает – первоначальное название языка – LiveScript было изменено на JavaScript по просьбе маркетологов. Наконец, приложения, написанные на JavaScript, можно отлаживать прямо в браузере. (Имеются и более развитые отладчики – можно воспользоваться отладчиком Microsoft Script Debugger в Internet Explorer, а в Firefox – модулем расширения Venkman.)
При написании программ на JavaScript используется набор символов Unicode. JavaScript – это нетипизированный язык, т. е. в нём не требуется определять типы переменных, типизация слабая и динамическая.
Ядро языка JavaScript поддерживает работу с такими простыми типами данных, как числа, строки и булевы значения, обладает также встроенной поддержкой массивов, дат и объектов регулярных выражений. Встроенные типы данных соответствуют таковым в других ЯВУ, кроме целых чисел. Они могут быть представлены в очень большом диапазоне от –9007199254740992 ( –253) до +9007199254740992 (253) включительно. Вне этого диапазона может теряться точность в младших разрядах целых чисел. Из отличий в типах данных отмечу, в JavaScript нет типа данных, такого как char в C, C++ и Java. Одиночный символ представлен строкой единичной длины.
Объявление переменной всегда начинается с ключевого слова var. Имя переменной должно начинаться с буквы, подчеркивания или знака доллара. В JavaScript регистр символов учитывается в именах переменных, ключевых словах, именах функций. Имена переменных, начинающиеся с $, обычно резервируются для библиотек JavaScript. Если начальное значение переменной не указано, JavaScript по умолчанию присваивает ей значение undefined, сообщая, что «переменная ещё не инициализирована».
Переменные делятся на локальные и глобальные. Специфика JavaScript в том, что если используется переменная, которая не была ранее объявлена, такая переменная будет считаться глобальной. Глобальные переменные существуют, пока существует веб-страница. Жизнь глобальной переменной начинается с момента загрузки кода JavaScript для страницы. Когда страница перестает существовать, то перестают существовать и глобальные переменные. Даже если перезагрузить эту страницу, все глобальные переменные будут уничтожены и созданы заново в перезагруженной браузером странице. Ещё одна особенность – если используется переменная, которая не была ранее объявлена, такая переменная считается глобальной. А если она оказалась внутри функции, то возможен неприятный сюрприз.
Классическая первая программа на JavaScript выглядит так:
<script>
alert('Hello, World!');
</script>
JavaScript предоставляет несколько синтаксических конструкций для повторного выполнения кода: while, for, for in и forEach. Примеры:
var ps = 5;
while (ps > 0) {
document.write("Ещё одно исполнение цикла<br>");
ps = ps - 1;
}
На этом примере видно, что в текст на JavaScript могут быть включены теги языка HTML, в данном случае <br> -- перевод строки. Веб-страница рассматривается браузером как документ, поэтому функция document.write позволяет вывести произвольную разметку HTML и контент в произвольной точке страницы.
var fact = 1;
for(i = 1; i < 10; i++) {
fact = fact*i;
document.write(i + "! = " + fact + "<br>");
}
В этой конструкции всё похоже на конструкции цикла в обычных процедурных ЯВУ.
JavaScript поддерживает работу с одномерными массивами, а поскольку он является нетипизированным языком, то элементы массива не обязательно должны иметь одинаковый тип – в отличие от многих других языков, в массиве могут храниться практически любые значения JavaScript, включая строки, числа, логические значения, другие массивы и даже объекты. Так команда:
var myarray = new Array(5);
с помощью конструктора Array создает новый массив пятью пустыми позициями (то есть массив длины 5, который не содержит ни одного значения).
В JavaScript добавлена концепция «итерируемых» (iterable) объектов. Итерируемые или, иными словами, «перебираемые» объекты – это те, содержимое которых можно перебрать в цикле. Перебираемым объектом является массив. Но не только он. В браузере существует множество объектов, которые не являются массивами, но содержимое которых можно перебрать (к примеру, список DOM-узлов). Для перебора таких объектов добавлен новый синтаксис цикла: for..of.
let arr = [1, 2, 3, 4]; // массив — пример итерируемого объекта
for (let value of arr) {
alert(value); // 1, затем 2, затем 3, затем 4
}
Практически везде, где нужен перебор, он осуществляется через итераторы.
JavaScript передает аргументы функциям по значению. Это означает, что каждый аргумент копируется в переменную-параметр и любые изменения параметра в функции затрагивают только сам параметр, но не исходную переменную. При этом функция игнорирует лишние аргументы, а параметрам, не получившим аргументов, присваивается значение undefined. Функция без команды return вернёт undefined.
Обычно в ЯВУ определение функции должно предшествовать её использованию. В JavaScript, из-за того что браузер обрабатывает веб-страницу дважды – при первом проходе он читает все определения функций, а при втором выполняет код, размещать функции можно в любом месте файла даже после их использования программе.
Работа с объектами в JavaScript похожа на работу с ними в других объектно-ориентированных языках, но есть некоторые особенности, в частности, многие JavaScript-объекты и их свойства имеют те же имена, что и теги и атрибуты языка HTML, которые они обозначают, т. е. в дополнение к встроенным в браузер объектам, можно определить свои собственные объекты. Отметим, что сам JavaScript предоставляет множество готовых объектов, которые можно использовать в своём коде, в то же время программисту доступны и объекты самого браузера. Свойства объекта можно динамически добавлять к нему и удалять. Доступ к свойству можно получить с помощью точечной записи:
objectName.propertyName
или с помощью скобочной записи
objectName["propertyName"] = value
Все объекты в JavaScript наследуются как минимум от другого объекта. Объект, от которого произошло наследование, называется прототипом.
При написании приложений для браузера ключевую роль играют такие объекты браузера как
-
document – служит для записи из программного кода в веб-страницу;
-
метод log объекта console используется для вывода сообщений на консоль;
-
Window представляет свойства, относящиеся к браузеру. На самом деле это очень важный объект – через него JavaScript подтягивает себе все объекты и методы, имеющиеся в браузере. В других ЯВУ это делается через набор многочисленных библиотек.
Программа на JavaScript взаимодействует с веб-страницей, используя объектную модель документа DOM (Document Object Model). Рассмотрим, что это такое. При загрузке страницы браузер разбирает её HTML-разметку, выводит страницу на экран, и создает при этом набор объектов, представляющих разметку. Эти объекты и сохраняются в модели динамически. Код JavaScript взаимодействует с DOM для получения доступа к элементам разметки и их содержимому как для создания, чтения, так и для удаления элементов. При любом изменении DOM браузер сразу же обновляет страницу.
Корнем каждой модели DOM является объект document, а под ним располагается дерево с ветвями и листовыми узлами для всех элементов разметки HTML. Объект document может использоваться в JavaScript для получения доступа ко всей модели DOM.
Например, найти на странице идентификатор абзаца с именем EC1045:
var computer = document.getElementById("EC1045");
Метод getElementById ищет элемент EC1045 и возвращает его.
Свойство innerHTML используется для чтения и замены содержимого элемента. В innerHTML возвращается внутреннее содержимое элемента, без тегов HTML. Заменим содержимое элемента EC1045:
computer.innerHTML = "Организация-разработчик: НИИММ, Ереван.";
Содержимое элемента EC1045 заменяется новым текстом, DOM и страница обновляются, а новый текст появляется в браузере.
Встроенный объект document содержит целый набор свойств и методов, с которыми достаточно плотно придётся работать JavaScript-программисту. Но это планида всех, кто занимается веб-разработкой на скриптовых языках, т. е. нужно глубоко погрузиться в HTML5, CSS и освоить некоторое множество методов и свойств JavaScript и браузеров. Замечу, что последние новости о JavaScript несколько настораживают – сверхбольшую нейросетевую модель GPT 4.0 научили писать простые сценарии на этом языке (и ещё почти на десятке других). Я попросил GPT 4.0 написать на JavaScript программу, реализующую так называемое шифрование кодом Цезаря. Получил вот такой текст:
def caesar_cipher(text, shift):
cipher_text = ""
for char in text:
if char.isalpha():
# Получаем номер символа в алфавите
char_num = ord(char.lower()) - ord('a')
# Сдвигаем номер символа на указанное количество позиций
shifted_char_num = (char_num + shift) % 26
# Получаем символ из сдвинутого номера
shifted_char = chr(shifted_char_num + ord('a'))
# Делаем символ заглавным, если он был таковым в первоначальном тексте
if char.isupper():
shifted_char = shifted_char.upper()
cipher_text += shifted_char
else:
cipher_text += char
return cipher_text
Пример использования функции:
text = "Hello, World!"
shift = 5
cipher_text = caesar_cipher(text, shift)
print("Encrypted:", cipher_text) # "Mjqqt, Btwqi!"
original_text = caesar_cipher(cipher_text, -shift) # сдвигаем на обратное значение назад
print("Decrypted:", original_text) # "Hello, World!"
Конечно, выдаваемый моделью код нужно тщательно проверять, но такая возможность может заметно ускорить разработку приложений.
Продолжим. Если щёлкнуть на веб-странице правой кнопкой мыши, то в появившемся ниспадающем меню вы увидите пункт «Показать код страницы». Код страницы появится либо в правой части окна, либо займет всё окно. В большинстве случаев это будет код на JavaScript, внедрённый в HTML-текст. Следует выбирать наиболее простые страницы, так называемые визитницы, поскольку иначе это будет довольно гремучая и трудно читаемая смесь.
Теперь о серверном JavaScript. Он имеет то же самое языковое ядро, что и клиентский JavaScript. Но, поскольку на сервере другая среда, то и JavaScript работает в ней иначе. Среди задач, которые могут быть запрограммированы в серверной среде, может быть установление соединения с реляционной базой данных, работа с файловой системой сервера и др. А это уже совсем другие объекты. Так серверный JavaScript включает объект database для соединения с внешней реляционной БД. Кроме того, серверное приложение может обрабатывать запросы от тысяч пользователей и работать с громадными объёмами данных. Серверный код JavaScript заключен в специальный тег </server> языка HTML, т. е. на странице может располагаться код, который будет выполняться либо на клиенте (тег </script>), либо на сервере. Поскольку задачи у клиентского и серверного JavaScript разные, то для каждой из сторон имеется свой большой набор предопределённых классов и объектов, которые исполняются только на конкретной стороне, но не работают на другой стороне. Но в целом, несмотря на перечисленные чудачества, JavaScript вполне элегантный и приятный язык.
Москва, май 2023 г.
Автор благодарен Владимиру Биллигу, инициатору написания этого текста и сделавшему по нему ряд полезных замечаний.
Об авторе: Директор Виртуального Компьютерного Музея
Помещена в музей с разрешения автора
2 июня 2023