Как работает javascript в браузере
JavaScript – это язык программирования, который добавляет интерактивность на ваш веб-сайт (например: игры, отклик при нажатии кнопок или при вводе данных в формы, динамические стили, анимация). Эта статья поможет вам начать работать с этим захватывающим языком и даст вам представление о том, на что он способен.
Что такое JavaScript на самом деле?
JavaScript ("JS" для краткости) — это полноценный динамический язык программирования, который применяется к HTML документу, и может обеспечить динамическую интерактивность на веб-сайтах. Его разработал Brendan Eich, сооснователь проекта Mozilla, Mozilla Foundation и Mozilla Corporation.
JavaScript невероятно универсален и дружелюбен к новичкам. Обладая большим опытом, вы сможете создавать игры, анимированную 2D и 3D графику, полномасштабные приложения с базами данных и многое другое!
JavaScript сам по себе довольно компактный, но очень гибкий. Разработчиками написано большое количество инструментов поверх основного языка JavaScript, которые разблокируют огромное количество дополнительных функций с очень небольшим усилием. К ним относятся:
- Программные интерфейсы приложения (API), встроенные в браузеры, обеспечивающие различные функциональные возможности, такие как динамическое создание HTML и установку CSS стилей, захват и манипуляция видеопотоком, работа с веб-камерой пользователя или генерация 3D графики и аудио сэмплов.
- Сторонние API позволяют разработчикам внедрять функциональность в свои сайты от других разработчиков, таких как Twitter или Facebook.
- Также вы можете применить к вашему HTML сторонние фреймворки и библиотеки, что позволит вам ускорить создание сайтов и приложений.
Поскольку эта статья должна быть только лёгким введением в JavaScript, мы не собираемся путать вас на этом этапе, подробно рассказывая о том, какая разница между основным языком JavaScript и различными инструментами, перечисленными выше. Вы можете подробно изучить все это позже, в нашей учебной области JavaScript и в остальной части MDN.
Ниже мы познакомим вас с некоторыми аспектами основного языка, и вы также будете играть с несколькими функциями API браузера. Веселитесь!
Пример "hello world"
Предыдущий раздел звучит очень многообещающе, и это на самом деле так — JavaScript является одной из самых перспективных веб-технологий, и когда вы освоитесь и начнёте использовать его, ваши веб-сайты перейдут в новое измерение мощи и креативности.
Тем не менее, с JavaScript немного более сложно освоиться, чем с HTML и CSS. Вам придётся начать с малого, продолжая изучение небольшими шагами. Для начала мы покажем вам, как добавить некоторые основы JavaScript на вашу страницу, чтобы создать "hello world!" пример (стандарт в начальных примерах программирования).
Важно: Если вы не следили за остальным нашим курсом, скачайте этот пример кода и используйте его в качестве стартовой точки.
- Для начала перейдите на ваш тестовый сайт и создайте папку с именем 'scripts' (без кавычек). Затем, в новой папке скриптов, которую вы только что создали, создайте новый файл с именем main.js . Сохраните его в вашей папке scripts .
- Далее перейдите в ваш index.html файл и введите следующий элемент на новой строке прямо перед закрывающим тегом :
Что произошло?
Итак, ваш заголовок текста был изменён на "Hello world!" с помощью JavaScript. Мы сделали это с помощью вызова функции querySelector() , захватив ссылку на наш заголовок и сохранив её в переменной, названной myHeading . Это очень похоже на то, что мы делали в CSS с помощью селекторов. Если вы хотите что-то сделать с элементом, то для начала вам нужно его выбрать.
После этого, вы устанавливаете значение переменной myHeading в textContent свойство (которое представляет собой контент заголовка) "Hello world!".
Ускоренный курс по основам языка
Давайте познакомимся с некоторыми основными возможностями языка JavaScript, чтобы дать вам больше понимания, как это всё работает. Более того, эти возможности являются общими для всех языков программирования. Если вы сможете понять эти основы, вы будете в состоянии начать программировать, как ни в чём не бывало!
Важно: В этой статье попробуйте вводить примеры строк кода в вашей JavaScript консоли, чтобы увидеть, что происходит. Для более подробной информации о JavaScript консоли смотрите статью Откройте для себя браузерные инструменты разработчика.
Переменные
Переменные — это контейнеры, внутри которых вы можете хранить значения. Вы начинаете с того, что объявляете переменную с помощью ключевого слова var (не рекомендуется, продолжайте читать, чтобы получить объяснения) или let , за которым следует любое имя, которым вы захотите её назвать:
Примечание: Точка с запятой в конце строки указывает, где заканчивается оператор. Точку с запятой нужно обязательно использовать для разеделения операторов, располагающихся на одной строке. Однако некоторые люди считают, что хорошая практика — указывать её в конце каждого оператора. Существуют и другие правила, когда нужно ставить точку с запятой, а когда нет. Смотрите более подробно в статье ваше руководство по точкам с запятой в JavaScript.
Примечание: вы можете назвать переменную практически как угодно, но есть некоторые ограничения для её имени (смотрите в правилах именования переменных.) Если вы не уверены, вы можете проверить имя вашей переменной, чтобы увидеть корректно ли оно.
Примечание: JavaScript чувствителен к регистру — myVariable отличается от переменной myvariable . Если у вас возникают проблемы в вашем коде, проверьте регистр!
Примечание: Для получения более подробной информации о разнице между var и let, смотрите: Разница между var и let.
После объявления переменной вы можете присвоить ей значение:
Вы можете сделать обе эти операции на одной и той же строке, если вы захотите:
Вы можете получить значение, просто вызвав переменную по имени:
После установки значения переменной вы можете изменить его позже:
Обратите внимание, что переменные имеют разные типы данных:
Переменная | Пояснение | Пример |
---|---|---|
String | Последовательность текста, называемая строкой. Чтобы указать, что это значение является строкой, вы должны заключить его в кавычки. | var myVariable = 'Bob'; |
Number | Числа. Числа не имеют кавычек вокруг них. | var myVariable = 10; |
Boolean | Значение True(Правда)/False(Ложь). Слова true и false специальные ключевые слова в JS, и не нуждаются в кавычках. | var myVariable = true; |
Array | Массив, который позволяет хранить несколько значений в одной ссылке. | var myVariable = [1,'Bob','Steve',10]; Обратиться к каждому элементу массива можно так: myVariable[0] , myVariable[1] , и т.д. |
Object | В принципе, что угодно. Все в JavaScript является объектом, и может храниться в переменной. Имейте это в виду, пока вы учитесь. | var myVariable = document.querySelector('h1'); Все это из вышеприведённых примеров. |
Комментарии
Комментарии - это, по сути, короткие фрагменты текста, которые могут быть добавлены в код, и которые игнорируются браузером. Вы можете поместить комментарии в JavaScript-код, так же как вы делали это в CSS:
Если ваш комментарий не содержит переноса строк, то зачастую легче поставить две косые черты, как тут:
Операторы
operator (en-US) — это математический символ, который производит результат, основанный на двух значениях (или переменных). В приведённой ниже таблице вы можете увидеть некоторые из наиболее простых операторов, наряду с некоторыми примерами, которые опробуете в JavaScript консоли.
Основное выражение true , но сравнение возвращает false , потому что мы отрицаем его:
var myVariable = 3;
!(myVariable === 3);
Здесь мы проверяем " myVariable НЕ равно 3". Это возвращает false , потому что myVariable равно 3.
var myVariable = 3;
myVariable !== 3;
Существует намного больше операторов для изучения, но этих пока хватит. Смотрите их полный список в разделе выражения и операторы.
Примечание: Смешивание типов данных может привести к некоторым неожиданным результатам при выполнении вычислений, поэтому будьте осторожны, правильно ссылайтесь на ваши переменные, чтобы получать ожидаемые результаты. Например, введите "35" + "25" в вашу консоль. Почему вы не получили результат, который вы ожидали? Потому, что кавычки превратили числа в строки, так что у вас в итоге получилась конкатенация строк, а не сложение чисел. Если вы введёте, 35 + 25 , то получите правильный результат.
Условия
Условия — это конструкции в коде, которые позволяют проверить истинность или ложность выражения и выполнить другой код в зависимости от полученного результата. Самая распространённая форма условия — инструкция if . else . Например:
Выражение внутри if ( . ) — это проверка, которая использует тождественный оператор (как описано выше), чтобы сравнить переменную iceCream со строкой chocolate и увидеть равны ли они. Если это сравнение возвращает true , выполнится первый блок кода. Если нет, этот код пропустится и выполнится второй блок кода, после инструкции else .
Функции
Функции - способ упаковки функциональности, которую вы хотите использовать повторно. Всякий раз, когда вам нужна определённая процедура, вы можете просто вызвать функцию по её имени, а не переписывать весь код каждый раз. Вы уже видели некоторые функции, описанные выше, например:
Эти функции, document.querySelector и alert , встроены в браузер для того, чтобы вы использовали их всякий раз, когда вам это необходимо.
Если вы видите что-то, что выглядит как имя переменной, но имеет после него скобки — () , скорее всего, это функция. Функции часто принимают аргументы — биты данных, которые им необходимы для выполнения своей работы. Они находятся в скобках, и разделяются запятыми, если присутствует более одного аргумента.
Например, функция alert() вызывает всплывающий блок, появляющийся в окне браузера, но мы должны дать ему строку в качестве аргумента, чтобы сказать функции, что писать во всплывающем блоке.
Хорошая новость заключается в том, что вы можете определить свои собственные функции — в следующем примере мы напишем простую функцию, которая принимает два числа в качестве аргументов и умножает их:
Попробуйте запустить вышеупомянутую функцию в консоли, затем попробуйте изменить аргументы, например:
Примечание: Инструкция return сообщает браузеру, что нужно вернуть переменную result из функции, которую можно будет использовать. Это необходимо потому, что переменные, определённые внутри функций, доступны только внутри этих функций. Это называется областью видимости (en-US) переменной. (Читайте больше об области видимости переменных.)
События
Для создания действительной интерактивности на веб-сайте вам необходимы события. События — это структура, которая следит за тем, что происходит в браузере, а затем позволяет вам запускать код в ответ на это. Наиболее очевидным является событие клика (en-US), которое вызывается браузером, когда мы щёлкаем по чему-то мышью. Для демонстрации этого события введите следующую команду в вашу консоль, а затем щёлкните по текущей веб-странице:
Существуют множество способов прикрепить событие к элементу. Здесь мы выбираем элемент и устанавливаем ему обработчик свойства onclick (en-US) анонимной функцией (т.е. безымянной) которая содержит код, который мы хотим запустить для события клика.
Обратите внимание, что
Просто так короче.
Прокачаем пример нашего веб-сайта
Теперь, когда мы прошли некоторые основы JavaScript, давайте добавим несколько крутых несложных функций в пример нашего сайта, чтобы дать вам некоторое представление о принципах работы.
Добавление смены изображения
В этом разделе мы добавим ещё одно изображение на наш сайт и добавим некоторый простой JavaScript для переключения между двумя изображениями, когда по ним щёлкнули.
- В первую очередь найдите другое изображение, которые вы хотели бы показать на вашем сайте. Убедитесь что оно такого же размера, как ваше первое изображение или максимально близкое к нему.
- Сохраните изображение в вашу папку images .
- Переименуйте это изображение в 'firefox2.jpg' (без кавычек).
- Перейдите в ваш файл main.js и введите следующий JavaScript. (Если ваш "hello world" JavaScript по-прежнему существует, удалите его.)
- Мы получаем значение из атрибута src изображения.
- Мы используем условие для проверки значения src, равен ли путь к исходному изображению:
- Если это так, мы меняем значение src на путь ко 2-му изображению, заставляя другое изображение загружаться внутри элемента .
- Если это не так (значит, оно должно было уже измениться), мы меняем значение src , возвращаясь к первоначальному пути изображения, каким он был изначально.
-
В index.html , добавьте следующую строку перед элементом :
Заключение
Если вы следовали всем инструкциям в этой статье, в конечном итоге вы должны получить страницу, которая выглядит примерно так (вы также можете посмотреть нашу версию здесь):
Если вы застряли, вы всегда можете сравнить свою работу с нашим готовым примером кода на Github.
Здесь мы узнали только самую поверхность JavaScript. Если вам понравился этот язык и вы хотите изучить его поглубже, перейдите к нашему разделу изучение JavaScript.
В переводе двенадцатой части серии материалов о JavaScript и его экосистеме, который мы сегодня публикуем, речь пойдёт о сетевой подсистеме браузеров и об оптимизации производительности и безопасности сетевых операций. Автор материала говорит, что разница между хорошим и отличным JS-разработчиком заключается не только в уровне освоения языка, но и в том, насколько хорошо он разбирается в механизмах, не входящих в язык, но используемых им. Собственно говоря, работа с сетью — это один из таких механизмов.
Немного истории
49 лет назад была создана компьютерная сеть ARPAnet, объединяющая несколько научных учреждений. Это была одна из первых сетей с коммутацией пакетов, и первая сеть, в который была реализована модель TCP/IP. Двадцатью годами позже Тим Бернес-Ли предложил проект известный как Всемирная паутина. За годы, которые прошли с запуска ARPAnet, интернет прошёл долгий путь — от пары компьютеров, обменивающихся пакетами данных, до более чем 75 миллионов серверов, примерно 1.3 миллиарда веб-сайтов и 3.8 миллиарда пользователей.
Количество пользователей интернета в мире
В этом материале мы поговорим о том, какие механизмы используют браузеры для того, чтобы повысить производительность работы с сетью (эти механизмы скрыты в их недрах, вероятно, вы о них, работая с сетью в JS, даже и не думаете). Кроме того, мы обратим особое внимание на сетевой уровень браузеров и приведём здесь несколько рекомендаций, касающихся того, как разработчик может помочь браузеру повысить производительность сетевой подсистемы, которую задействуют веб-приложения.
Обзор
При разработке современных веб-браузеров особое внимание уделяется быстрой, эффективной и безопасной загрузке в них страниц веб-сайтов и веб-приложений. Работу браузеров обеспечивают сотни компонентов, выполняющихся на различных уровнях и решающих широкий спектр задач, среди которых — управление процессами, безопасное выполнение кода, декодирование и воспроизведение аудио и видео, взаимодействие с видеоподсистемой компьютера и многое другое. Всё это делает браузеры больше похожими на операционные системы, а не на обычные приложения.
Общая производительность браузера зависит от целого ряда компонентов, среди которых, если рассмотреть их укрупнённо, можно отметить подсистемы, решающие задачи разбора загружаемого кода, формирования макетов страниц, применения стилей, выполнения JavaScript и WebAssembly-кода. Конечно же, сюда входят и система визуализации информации, и реализованный в браузере сетевой стек.
Программисты часто думают, что узким местом браузера является именно его сетевая подсистема. Часто так и бывает, так как все ресурсы, прежде чем с ними можно будет что-то сделать, сначала должны быть загружены из сети. Для того чтобы сетевой уровень браузера был эффективным, ему нужны возможности, позволяющие играть роль чего-то большего, нежели роль простого средства для работы с сокетами. Сетевой уровень даёт нам очень простой механизм загрузки данных, но, на самом деле, за этой внешней простотой скрывается целая платформа с собственными критериями оптимизации, API и службами.
Сетевая подсистема браузера
Занимаясь веб-разработкой, мы можем не беспокоиться об отдельных TCP или UDP-пакетах, о форматировании запросов, о кэшировании, и обо всём остальном, что происходит в ходе взаимодействия браузера с сервером. Решением всех этих сложных задач занимается браузер, что даёт нам возможность сосредоточиться на разработке приложений. Однако, знание того, что происходит в недрах браузера, может помочь нам в деле создания более быстрых и безопасных программ.
Поговорим о том, как выглядит обычный сеанс взаимодействия пользователя с браузером. В целом, он состоит из следующих операций:
Жизненный цикл запроса
Весь процесс обмена данными по сети очень сложен, он представлен множеством уровней, каждый из которых может стать узким местом. Именно поэтому браузеры стремятся к тому, чтобы улучшить производительность на своей стороне, используя различные подходы. Это помогает снизить, до минимально возможных значений, воздействие особенностей сетей на производительность сайтов.
Управление сокетами
Прежде чем говорить об управлении сокетами, рассмотрим некоторые важные понятия:
На самом деле, современные браузеры не жалеют сил на раздельное управление запросами и сокетами. Сокеты организованы в пулы, которые сгруппированы по источнику. В каждом пуле применяются собственные лимиты соединений и ограничения, касающиеся безопасности. Запросы, выполняемые к источнику, ставятся в очередь, приоритизируются, а затем привязываются к конкретным сокетам в пуле. Если только сервер не закроет соединение намеренно, один и тот же сокет может быть автоматически переиспользован для выполнения многих запросов.
Очереди запросов и система управления сокетами
Так как открытие нового TCP-соединения требует определённых затрат системных ресурсов и некоторого времени, переиспользование соединений, само по себе, является отличным средством повышения производительности. По умолчанию браузер использует так называемый механизм «keepalive», который позволяет экономить время на открытии соединения к серверу при выполнении нового запроса. Вот средние показатели времени, необходимого для открытия нового TCP-соединения:
- Локальные запросы: 23 мс.
- Трансконтинентальные запросы: 120 мс.
- Интерконтинентальные запросы: 225 мс.
Как уже было сказано, всё это управляется браузером и не требует усилий со стороны программиста. Однако это не означает, что программист не может сделать ничего для того, чтобы помочь браузеру. Так, например, выбор подходящих шаблонов сетевого взаимодействия, частоты передачи данных, выбор протокола, настройка и оптимизация серверного стека, могут сыграть значительную роль в повышении общей производительности приложения.
Некоторые браузеры в деле оптимизации сетевых соединений идут ещё дальше. Например, Chrome может «самообучаться» по мере его использования, что ускоряет работу с веб-ресурсами. Он анализирует посещённые сайты и типичные шаблоны работы в интернете, что даёт ему возможность прогнозировать поведение пользователя и предпринимать какие-то меры ещё до того, как пользователь что-либо сделает. Самый простой пример — это предварительный рендеринг страницы в тот момент, когда пользователь наводит указатель мыши на ссылку. Если вам интересны внутренние механизмы оптимизации, применяемые в Chrome, вот — полезный материал на эту тему.
Сетевая безопасность и ограничения
У того, что браузеру позволено управлять отдельными сокетами, есть, помимо оптимизации производительности, ещё одна важная цель: благодаря такому подходу браузер может применять единообразный набор ограничений и правил, касающихся безопасности, при работе с недоверенными ресурсами приложений. Например, браузер не даёт прямого доступа к сокетам, так как это позволило бы любому потенциально опасному приложению выполнять произвольные соединения с любыми сетевыми системами. Браузер, кроме того, применяет ограничение на число соединений, что защищает сервер и клиент от чрезмерного использования сетевых ресурсов.
Браузер форматирует все исходящие запросы для защиты сервера от запросов, которые могут быть сформированы неправильно. Точно так же браузер относится и к ответам серверов, автоматически декодируя их и принимая меры для защиты пользователя от возможных угроз, исходящих со стороны сервера.
Процедура TLS-согласования
TLS (Transport Layer Security, протокол защиты транспортного уровня), это криптографический протокол, который обеспечивает безопасность передачи данных по компьютерным сетям. Он нашёл широкое использование во множестве областей, одна из которых — работа с веб-сайтами. Веб-сайты могут использовать TLS для защиты всех сеансов взаимодействия между серверами и веб-браузерами.
Вот как, в общих чертах, выглядит процедура TLS-рукопожатия:
Принцип одного источника
В соответствии с принципом одного источника (Same-origin policy), две страницы имеют один и тот же источник, если их протокол, порт (если задан) и хост совпадают.
Вот несколько примеров ресурсов, которые могут быть встроены в страницу с несоблюдением принципа одного источника:
Стоит отметить, что не существует единственной концепции «принципа единого источника». Вместо этого имеется набор связанных механизмов, которые применяют ограничения по доступу к DOM, по управлению куки-файлами и состоянием сессии, по работе с сетевыми ресурсами и с другими компонентами браузера.
Кэширование
Самый лучший, самый быстрый запрос — это запрос, который не ушёл в сеть, а был обработан локально. Прежде чем ставить запрос в очередь на выполнение, браузер автоматически проверяет свой кэш ресурсов, выполняет проверку найденных там ресурсов на предмет актуальности и возвращает локальные копии ресурсов в том случае, если они соответствуют определённому набору требований. Если же ресурсов в кэше нет, выполняется сетевой запрос, а полученные в ответ на него материалы, если их можно кэшировать, помещаются в кэш для последующего использования. В процессе работы с кэшем браузер выполняет следующие действия:
- Он автоматически оценивает директивы кэширования на ресурсах, с которыми ведётся работа.
- Он автоматически, при наличии такой возможности, перепроверяет ресурсы, срок кэширования которых истёк.
- Он самостоятельно управляет размером кэша и удаляет из него ненужные ресурсы.
Пример
Вот простой, но наглядный пример удобства отложенного управления состоянием сессии в браузере. Аутентифицированная сессия может совместно использоваться в нескольких вкладках или окнах браузера, и наоборот; завершение сессии в одной из вкладок приводит к тому, что сессия окажется недействительной и во всех остальных.
API и протоколы
Советы по оптимизации производительности и безопасности сетевых подсистем веб-приложений
Вот несколько советов, которые помогут вам повысить производительность и безопасность сетевых подсистем ваших веб-приложений.
- Всегда используйте в запросах заголовок «Connection: Keep-Alive». Браузеры, кстати, используют его по умолчанию. Проверьте, чтобы и сервер использовал тот же самый механизм.
- Используйте подходящие заголовки Cache-Control, Etag и Last-Modified при работе с ресурсами. Это позволит ускорить загрузку страниц при повторных обращениях к ним из того же браузера и сэкономить трафик.
- Потратьте время на настройку и оптимизацию сервера. В этой области, кстати, можно увидеть настоящие чудеса. Помните о том, что процесс подобной настройки очень сильно зависит от особенностей конкретного приложения и от типа передаваемых данных.
- Всегда используйте TLS. В особенности — если в вашем веб-приложении используются какие-либо механизмы аутентификации пользователя.
- Выясните, какие политики безопасности предоставляют браузеры, и используйте их в своих приложениях.
Итоги
Браузеры берут на себя большую часть сложных задач по управлению всем тем, что связано с сетевым взаимодействием. Однако это не значит, что разработчик может совершенно не обращать на всё это внимание. Тот, кто хотя бы в общих чертах знает о том, что происходит в недрах браузера, может вникнуть в необходимые детали и своими действиями помочь браузеру, а значит — сделать так, чтобы его веб-приложения работали быстрее.
Предыдущие части цикла статей:
Популярность JavaScript растёт, его возможности используют на разных уровнях применяемых разработчиками стеков технологий и на множестве платформ. На JS делают фронтенд и бэкенд, пишут гибридные и встраиваемые приложения, а также многое другое.
Анализ статистики GitHub показывает, что по показателям активных репозиториев и push-запросов, JavaScript находится на первом месте, да и в других категориях он показывает довольно высокие позиции.
Статистические сведения по JavaScript с GitHubС другой системой статистических сведений по GitHub можно ознакомиться здесь, она подтверждает то, что было сказано выше.
Если множество проектов плотно завязаны на JavaScript, значит, разработчикам необходимо как можно более эффективно использовать всё, что даёт им язык и его экосистема, стремясь, на пути разработки замечательных программ, к глубокому пониманию внутренних механизмов языка.
Обзор
Почти все слышали, в самых общих чертах, о JS-движке V8, и большинству разработчиков известно, что JavaScript — однопоточный язык, или то, что он использует очередь функций обратного вызова.
Здесь мы поговорим, на довольно высоком уровне, о выполнении JS-кода. Зная о том, что, на самом деле, происходит при выполнении JavaScript, вы сможете писать более качественные программы, которые выполняются без «подвисаний» и разумно используют имеющиеся API.
Если вы недавно начали писать на JavaScript, этот материал поможет вам понять, почему JS, в сравнении с другими языками, может показаться довольно-таки странным.
Если вы — опытный JS-разработчик, надеемся, этот материал поможет вам лучше понять, как на самом деле работает то, чем вы пользуетесь каждый день.
Движок JavaScript
V8 от Google — это широко известный JS-движок. Он используется, например, в браузере Chrome и в Node.js. Вот как его, очень упрощённо, можно представить:
Упрощённое представление движка V8На нашей схеме движок представлен состоящим из двух основных компонентов:
- Куча (Memory Heap) — то место, где происходит выделение памяти.
- Стек вызовов (Call Stack) — то место, куда в процессе выполнения кода попадают так называемые стековые кадры.
Механизмы времени выполнения
Если говорить о применении JavaScript в браузере, то здесь существуют API, например, что-то вроде функции setTimeout , которые использует практически каждый JS-разработчик. Однако, эти API предоставляет не движок.
Откуда же они берутся? Оказывается, что реальность выглядит немного сложнее, чем может показаться на первый взгляд.
Движок, цикл событий, очередь функций обратного вызова и API, предоставляемые браузеромИтак, помимо движка у нас есть ещё очень много всего. Скажем — так называемые Web API, которые предоставляет нам браузер — средства для работы с DOM, инструменты для выполнения AJAX-запросов, нечто вроде функции setTimeout , и многое другое.
Стек вызовов
JavaScript — однопоточный язык программирования. Это означает, что у него один стек вызовов. Таким образом, в некий момент времени он может выполнять лишь какую-то одну задачу.
Стек вызовов — это структура данных, которая, говоря упрощённо, записывает сведения о месте в программе, где мы находимся. Если мы переходим в функцию, мы помещаем запись о ней в верхнюю часть стека. Когда мы из функции возвращаемся, мы вытаскиваем из стека самый верхний элемент и оказываемся там, откуда вызывали эту функцию. Это — всё, что умеет стек.
Рассмотрим пример. Взгляните на следующий код:
Когда движок только начинает выполнять этот код, стек вызовов пуст. После этого происходит следующее:
Стек вызовов в ходе выполнения программыКаждая запись в стеке вызовов называется стековым кадром.
На механизме анализа стековых кадров основана информация о стеке вызовов, трассировка стека, выдаваемая при возникновении исключения. Трассировка стека представляет собой состояние стека в момент исключения. Взгляните на следующий код:
Если выполнить это в Chrome (предполагается, что код находится в файле foo.js ), мы увидим следующие сведения о стеке:
Трассировка стека после возникновения ошибкиЕсли будет достигнут максимальный размер стека, возникнет так называемое переполнение стека. Произойти такое может довольно просто, например, при необдуманном использовании рекурсии. Взгляните на этот фрагмент кода:
Когда движок приступает к выполнению этого кода, всё начинается с вызова функции foo . Это — рекурсивная функция, которая не содержит условия прекращения рекурсии. Она бесконтрольно вызывает сама себя. В результате на каждом шаге выполнения в стек вызовов снова и снова добавляется информация об одной и той же функции. Выглядит это примерно так:
Переполнение стекаВ определённый момент, однако, объём данных о вызовах функции превысит размер стека вызовов и браузер решит вмешаться, выдав ошибку:
Превышение максимального размера стека вызововМодель выполнения кода в однопоточном режиме облегчает жизнь разработчика. Ему не нужно принимать во внимание сложные схемы взаимодействия программных механизмов, вроде возможности взаимной блокировки потоков, которые возникают в многопоточных окружениях.
Однако, и у исполнения кода в однопоточном режиме тоже есть определённые ограничения. Учитывая то, что у JavaScript имеется один стек вызовов, поговорим о том, что происходит, когда программа «тормозит».
Параллельное выполнение кода и цикл событий
Что происходит, когда в стеке вызовов имеется функция, на выполнение которой нужно очень много времени? Например, представьте, что вам надо выполнить какое-то сложно преобразование изображения с помощью JavaScript в браузере.
«А в чём тут проблема?», — спросите вы. Проблема заключается в том, что до тех пор, пока в стеке вызовов имеется выполняющаяся функция, браузер не может выполнять другие задачи — он оказывается заблокированным. Это означает, что браузер не может выводить ничего на экран, не может выполнять другой код. Он просто останавливается. Подобные эффекты, например, несовместимы с интерактивными интерфейсами.
Однако, это — не единственная проблема. Если браузер начинает заниматься обработкой тяжёлых задач, он может на достаточно долгое время перестать реагировать на какие-либо воздействия. Большинство браузеров в подобной ситуации выдают ошибку, спрашивая пользователя о том, хочет ли он завершить выполнение сценария и закрыть страницу.
Браузер предлагает завершить выполнение страницы
Пользователям подобные вещи точно не понравятся.
Итак, как же выполнять тяжёлые вычисления, не блокируя пользовательский интерфейс и не подвешивая браузер? Решение этой проблемы заключается в использовании асинхронных функций обратного вызова. Это — тема для отдельного разговора.
Итоги
Мы, в общих чертах, рассмотрели устройство JS-движка, механизмов времени выполнения и стека вызовов. Понимание изложенных здесь концепций позволяет улучшить качество кода.
В этой части учебника мы изучаем собственно JavaScript, сам язык.
Но нам нужна рабочая среда для запуска наших скриптов, и, поскольку это онлайн-книга, то браузер будет хорошим выбором. В этой главе мы сократим количество специфичных для браузера команд (например, alert ) до минимума, чтобы вы не тратили на них время, если планируете сосредоточиться на другой среде (например, Node.js). А на использовании JavaScript в браузере мы сосредоточимся в следующей части учебника.
Итак, сначала давайте посмотрим, как выполнить скрипт на странице. Для серверных сред (например, Node.js), вы можете выполнить скрипт с помощью команды типа "node my.js" . Для браузера всё немного иначе.
Тег «script»
Программы на JavaScript могут быть вставлены в любое место HTML-документа с помощью тега .
Вы можете запустить пример, нажав на кнопку «Play» в правом верхнем углу блока с кодом выше.
Тег содержит JavaScript-код, который автоматически выполнится, когда браузер его обработает.
Современная разметка
Тег имеет несколько атрибутов, которые редко используются, но всё ещё могут встретиться в старом коде:
Старый стандарт HTML, HTML4, требовал наличия этого атрибута в теге . Обычно он имел значение type="text/javascript" . На текущий момент этого больше не требуется. Более того, в современном стандарте HTML смысл этого атрибута полностью изменился. Теперь он может использоваться для JavaScript-модулей. Но это тема не для начального уровня, и о ней мы поговорим в другой части учебника.
Атрибут language : language=…>
Этот атрибут должен был задавать язык, на котором написан скрипт. Но так как JavaScript является языком по умолчанию, в этом атрибуте уже нет необходимости.
Обёртывание скрипта в HTML-комментарии.
В очень древних книгах и руководствах вы сможете найти комментарии внутри тега , например, такие:
Этот комментарий скрывал код JavaScript в старых браузерах, которые не знали, как обрабатывать тег . Поскольку все браузеры, выпущенные за последние 15 лет, не содержат данной проблемы, такие комментарии уже не нужны. Если они есть, то это признак, что перед нами очень древний код.
Внешние скрипты
Если у вас много JavaScript-кода, вы можете поместить его в отдельный файл.
Давайте посмотрим, что такого особенного в JavaScript, чего можно достичь с его помощью и какие другие технологии хорошо с ним работают.
Что такое JavaScript?
Изначально JavaScript был создан, чтобы «сделать веб-страницы живыми».
Программы на этом языке называются скриптами. Они могут встраиваться в HTML и выполняться автоматически при загрузке веб-страницы.
Скрипты распространяются и выполняются, как простой текст. Им не нужна специальная подготовка или компиляция для запуска.
Это отличает JavaScript от другого языка – Java.
Когда JavaScript создавался, у него было другое имя – «LiveScript». Однако, язык Java был очень популярен в то время, и было решено, что позиционирование JavaScript как «младшего брата» Java будет полезно.
Со временем JavaScript стал полностью независимым языком со своей собственной спецификацией, называющейся ECMAScript, и сейчас не имеет никакого отношения к Java.
Сегодня JavaScript может выполняться не только в браузере, но и на сервере или на любом другом устройстве, которое имеет специальную программу, называющуюся «движком» JavaScript.
У браузера есть собственный движок, который иногда называют «виртуальная машина JavaScript».
Разные движки имеют разные «кодовые имена». Например:
-
– в Chrome, Opera и Edge. – в Firefox.
- …Ещё есть «Chakra» для IE, «JavaScriptCore», «Nitro» и «SquirrelFish» для Safari и т.д.
- Движок (встроенный, если это браузер) читает («парсит») текст скрипта.
- Затем он преобразует («компилирует») скрипт в машинный язык.
- После этого машинный код запускается и работает достаточно быстро.
- Полная интеграция с HTML/CSS.
- Простые вещи делаются просто.
- Поддерживается всеми основными браузерами и включён по умолчанию.
Эти названия полезно знать, так как они часто используются в статьях для разработчиков. Мы тоже будем их использовать. Например, если «функциональность X поддерживается V8», тогда «Х», скорее всего, работает в Chrome, Opera и Edge.
Движки сложны. Но основы понять легко.
Движок применяет оптимизации на каждом этапе. Он даже просматривает скомпилированный скрипт во время его работы, анализируя проходящие через него данные, и применяет оптимизации к машинному коду, полагаясь на полученные знания. В результате скрипты работают очень быстро.
Что может JavaScript в браузере?
Современный JavaScript – это «безопасный» язык программирования. Он не предоставляет низкоуровневый доступ к памяти или процессору, потому что изначально был создан для браузеров, не требующих этого.
Возможности JavaScript сильно зависят от окружения, в котором он работает. Например, Node.JS поддерживает функции чтения/записи произвольных файлов, выполнения сетевых запросов и т.д.
В браузере для JavaScript доступно всё, что связано с манипулированием веб-страницами, взаимодействием с пользователем и веб-сервером.
Например, в браузере JavaScript может:
Чего НЕ может JavaScript в браузере?
Возможности JavaScript в браузере ограничены ради безопасности пользователя. Цель заключается в предотвращении доступа недобросовестной веб-страницы к личной информации или нанесения ущерба данным пользователя.
Примеры таких ограничений включают в себя:
JavaScript на веб-странице не может читать/записывать произвольные файлы на жёстком диске, копировать их или запускать программы. Он не имеет прямого доступа к системным функциям ОС.
Современные браузеры позволяют ему работать с файлами, но с ограниченным доступом, и предоставляют его, только если пользователь выполняет определённые действия, такие как «перетаскивание» файла в окно браузера или его выбор с помощью тега .
Существуют способы взаимодействия с камерой/микрофоном и другими устройствами, но они требуют явного разрешения пользователя. Таким образом, страница с поддержкой JavaScript не может незаметно включить веб-камеру, наблюдать за происходящим и отправлять информацию в ФСБ.
Различные окна/вкладки не знают друг о друге. Иногда одно окно, используя JavaScript, открывает другое окно. Но даже в этом случае JavaScript с одной страницы не имеет доступа к другой, если они пришли с разных сайтов (с другого домена, протокола или порта).
Это называется «Политика одинакового источника» (Same Origin Policy). Чтобы обойти это ограничение, обе страницы должны согласиться с этим и содержать JavaScript-код, который специальным образом обменивается данными.
Подобные ограничения не действуют, если JavaScript используется вне браузера, например — на сервере. Современные браузеры предоставляют плагины/расширения, с помощью которых можно запрашивать дополнительные разрешения.
Что делает JavaScript особенным?
Как минимум, три сильные стороны JavaScript:
JavaScript – это единственная браузерная технология, сочетающая в себе все эти три вещи.
Вот что делает JavaScript особенным. Вот почему это самый распространённый инструмент для создания интерфейсов в браузере.
Хотя, конечно, JavaScript позволяет делать приложения не только в браузерах, но и на сервере, на мобильных устройствах и т.п.
Языки «над» JavaScript
Синтаксис JavaScript подходит не под все нужды. Разные люди хотят иметь разные возможности.
Это естественно, потому что проекты разные и требования к ним тоже разные.
Так, в последнее время появилось много новых языков, которые транспилируются (конвертируются) в JavaScript, прежде чем запустятся в браузере.
Современные инструменты делают транспиляцию очень быстрой и прозрачной, фактически позволяя разработчикам писать код на другом языке, автоматически преобразуя его в JavaScript «под капотом».
Примеры таких языков:
-
добавляет «синтаксический сахар» для JavaScript. Он вводит более короткий синтаксис, который позволяет писать чистый и лаконичный код. Обычно такое нравится Ruby-программистам. концентрируется на добавлении «строгой типизации» для упрощения разработки и поддержки больших и сложных систем. Разработан Microsoft. тоже добавляет типизацию, но иначе. Разработан Facebook. стоит особняком, потому что имеет собственный движок, работающий вне браузера (например, в мобильных приложениях). Первоначально был предложен Google, как замена JavaScript, но на данный момент необходима его транспиляция для запуска так же, как для вышеперечисленных языков. транспилирует Python в JavaScript, что позволяет писать приложения на чистом Python без JavaScript.
Есть и другие. Но даже если мы используем один из этих языков, мы должны знать JavaScript, чтобы действительно понимать, что мы делаем.
Читайте также: