Обработка событий в javascript

Основы бэкенд

Как уже упоминалось, еще 10 лет назад JS использовался только для фронтенд-разработки. Теперь, благодаря Node.js, JavaScript работает и на серверной стороне.

SSR, CSR, изоморфные приложения

SSR — Server-Side Rendering – формирование страницы на стороне сервера.

CSR — Client Side Rendering – формирование страницы на стороне клиента (в браузере).

Какие проблемы имеются у этих способов?

SSR имеет ряд ограничений (скорость интернета у клиента, количество одновременных пользователей и т.д.). Это заметно снижало скорость, но это годилось для SEO оптимизации (так как при запросе к серверу робот получал сформированную страницу).

CSR – избавился от проблем скорости SSR (быстрый рендеринг, кеширование), появились одностраничные Single Page Application (SPA).  Но для таких одностраничных приложений CSR SEO оптимизация не годилась, так как весь контент передается клиенту и формируется в браузере (после инициализации начинается загрузка контента), а поисковый робот при запросе на сервер получает лишь пустую страницу.

Node.js

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

Теперь с помощью NodeJS стало возможным написать логику на серверной стороне, и она будет работать и на сервере (при первом обращении посетителя или поискового робота генерировался HTML с контентом страницы) и в браузере (последующие переходы посетителя). Это и называется изоморфное, универсальное приложение.

Схема функционирования простая: при первом заходе посетитель отправляет запрос на сервер NodeJS, который обращается к API-серверу, берёт данные в виде JSON и формирует страницу HTML, возвращая её клиенту. Теперь приложение работает на клиентской стороне, в браузере: при переходе на другие страницы приложение обращается за данными к API-серверу, и отрисовывает страницу уже в браузере.

В React (см. дальше) реализация этой схемы осуществляется разными и сложными путями. В качестве готовых решений есть для этого, например, фреймворк Next.js. В документации Vue (см. дальше) есть целый раздел, посвященный SSR. Там указан фреймворк Nuxt — Vue + SSR, при помощи которого можно быстро создавать универсальные приложения.

Серверы, HTTP, Express.js

Изучив Node, можно более глубже изучить бэкенд-разработку и разобраться в серверах и маршрутизации. Акцент делать на портах, протоколах HTTP. Затем можно просмотреть  Express-Node-библиотеку для обработки запросов.

Асинхронный JavaScript

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

Базы данных, СУБД, схемы, модели и ORM

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

Нужно научиться различать реляционные и нереляционные базы данных и разобраться в типах связей. Затем изучить SQL и быть в курсе разных систем управления базами данных. Знание ORM тоже не помешает.

Веб-сокеты

Не стоит пренебрегать этой темой. Веб-сокеты очень полезны. В отличие от протокола HTTP WebSocket позволяет работать с двунаправленным потоком данных. Самой распространённой реализацией является библиотека socket.io .

Также нужно разобраться в механизме взаимодействия приложения с пользователем, обработки им входа в учетную запись, отслеживания личности при помощи cookies — небольших текстовых файлов, которые передаются от сервера браузеру по HTTP-запросу. Связь между БД и страницей авторизации использует библиотеку express-session.

Дробление

Некоторые типы событий могут запускаться много раз в течение короткого периода времени (например, «mousemove» и javascript scroll event). При обработке таких событий, нужно быть осторожным, чтобы это не происходило очень долго, иначе обработчик будет выполнять действие столько времени, что взаимодействие с документом станет медленным и скачкообразным.

Если нужно сделать что-то нестандартное в таком обработчике, можно использовать setTimeout, чтобы быть уверенными, что это не растянется слишком надолго. Это обычно называют дроблением события. Существует несколько отличающихся друг от друга подходов к дроблению.

В первом примере мы хотим сделать что-то, когда пользователь печатает. Но не хотим делать это после каждого события нажатия клавиши. Когда пользователь быстро печатает, нужно подождать, пока не произойдет пауза. Вместо немедленного выполнения действия в обработчике события мы устанавливаем задержку. Мы также очищаем предыдущую задержку (если таковая имеется). Если события происходят через короткие интервалы времени (меньше, чем установленная нами задержка), то задержка от предыдущего события отменяется:

<textarea>Напечатайте что-нибудь здесь...</textarea>
<script>
  var textarea = document.querySelector("textarea");
  var timeout;
  textarea.addEventListener("keydown", function() {
    clearTimeout(timeout);
    timeout = setTimeout(function() {
      console.log("Вы перестали печатать.");
    }, 500);
  });
</script>

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

Можно использовать иной сценарий, если нужно разделить ответы небольшим промежутком времени. Но чтобы при этом они запускались во время серии событий, а не только после нее. Например, можно отправлять в ответ на события «mousemove» (JavaScript mouse events) текущие координаты мыши, но только через каждые 250 миллисекунд:

<script>
  function displayCoords(event) {
    document.body.textContent =
      "мышь находится в точке " + event.pageX + ", " + event.pageY;
  }

  var scheduled = false, lastEvent;
  addEventListener("mousemove", function(event) {
    lastEvent = event;
    if (!scheduled) {
      scheduled = true;
      setTimeout(function() {
        scheduled = false;
        displayCoords(lastEvent);
      }, 250);
    }
  });
</script>

Основы JavaScript — теория

И начнем как обычно с основ, т.е. с определения, что такое JavaScript? JavaScript – это скриптовый язык программирования, код которого выполняется на стороне клиента (пользователя). Применяется обычно для организации на сайте динамических HTML страниц, без перезагрузки самой страницы, т.е. без обращения к серверу.

Зачем нужен JavaScript?

А зачем Вы спросите организовывать динамические страницы?

Во-первых, это красиво, удобно и современно.

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

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

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

В процессе формирования HTML страницы браузером, сам браузер не только отрисовывает ее, но и формирует так называемое дерево элементов, которое состоит из узлов. А каждый узел формируется на основе кода HTML. Исходя из всего сказанного, можно сказать, что JavaScript может изменять это дерево и соответственно изменять сам код HTML, а как следствие изменять отображение HTML страницы в браузере. Под изменением дерева элементов понимается как само изменение некоторых узлов, так и удаление, добавление этих самых узлов. Чтобы было понятней, узел формируется на основе элементов в HTML, другими словами, тегов или самого содержимого, т.е. текста. Например, следующий код HTML можно отобразить в виде дерева элементов.

Код HTML:

   
   <html>
     <body>
       <p>Привет</p>
     </body>
   </html>

Узлы этого кода:

Корневой Узел – html

Дочерний Узел узла HTML — body

Дочерний Узел узла body – p

Дочерний Узел узла p —  сам текст (текст является отдельным узлом, это нужно помнить при добавлении, удалении и изменении текста).

Надеюсь с этим понятно, перейдем непосредственно к синтаксису и написанию первых программ на JavaScript.

По началу мне показалось, что JavaScript очень схож, с серверным языком программирования PHP, но это только в некоторых конструкциях, да, кстати, он также схож и с просто языком программирования JAVA, но на самом деле схоже написание нескольких конструкций и называние этих языков, но в остальном, имеется в виду в принципах программирования, это две разные вещи. Кстати, JavaScript никак не связан с языком JAVA, если только названием, поэтому не путайте JavaScript — это один язык программирования, а Java — это совсем другой. Но почему его назвали именно JavaScript? Да потому что в то время, когда разрабатывали JavaScript, был сильно популярен язык Java, и поэтому разработчики JavaScript решили переименовать свой язык LiveScript (так он изначально назывался) в JavaScript, а также изменили написание базовых конструкций, похожих на Java. Кстати, JavaScript официально называется ECMAScript, существует одноименный стандарт. Это для того чтобы не было проблем с владельцами торговой марки Java. Таким образом, JavaScript и JAVA — это совершенно два разных языка программирования. А почему у всех на устах название JavaScript? Да потому что просто так привыкли, и все называют язык ECMAScript языком JavaScript.

Объявление событий:

Всего есть три способа для объявления события, через HTML атрибут, через метод, через функцию , рассмотрим их все.

JS события через HTML атрибуты:

Перед тем как показать такой способ, нужно сказать, что он уже не используется и считается дурным тоном, но в некоторых JS фреймворках, например в React.js используется подобный механизм.

Вот не большой пример кода.

XHTML

1 <p onclick=»alert(‘Вы кликнули на тег p’)»>На меня надо нажать</p>

Вам тут надо просто кликнуть на текст, тогда у вас появится сообщение с надписью, «Вы кликнули на тег p»

На самом деле это всё что нужно знать о таком способе.

JS события через методы:

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

XHTML

1
2
3
4
5
6
7

<p>На меня надо нажать</p>

<script>
    let p = document.querySelector(«p»);
    p.onclick = function() {
        alert(«Вы кликнули на тег p»);
    }
</script>

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

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

Теперь осталось перечислить, какие методы есть.

  • onclick — Клик мышью;
  • oncontextmenu — Клик правой кнопкой мыши;
  • onmousemove — Перемещение мыши на элементе;
  • onmouseup — Отпускание кнопки мыши;
  • onmousedown —  Нажатие на кнопку мыши;
  • onkedown — Нажатие на клавишу;
  • onkeyup — Отпускание клавиши;
  • onkeypress — Зажатие клавиши;

Это не все доступные события, но самые популярные, их вы будите использовать чаще всего.

JS события через addEventListener:

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

Default

1
2
3
4
5
6
7

<p>Наменянадонажать<p>

<script>

letp=document.querySelector(«p»);

p.addEventListener(«click»,function(){

alert(«Вы кликнули на тег p»);

});

<script>

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

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

Вот вам весь список событий которые нужно вписывать в первый параметр:

  • click — Клик мышью;
  • contextmenu — Клик правой кнопкой мыши;
  • mousemove — Перемещение мыши на элементе;
  • mouseup — Отпускание кнопки мыши;
  • mousedown —  Нажатие на кнопку мыши;
  • kedown — Нажатие на клавишу;
  • keyup — Отпускание клавиши;
  • keypress — Зажатие клавиши;

Возможно вы заметили, но все названия событий, почти точно такие же, как и название методов, но без приставке «on».

Список функций

Название Описание
$.contains() Проверяет, содержится ли один элемент страницы внутри 
другого.
$.extend()  Объединяет два или более javascript-объекта.
$.globalEval() Выполняет заданный скрипт в глобальной области 
видимости.
$.grep() Ищет в заданном массиве элементы удовлетворяющие 
условиям.
$.inArray() Ищет в заданном массиве конкретный элемент и 
возвращает его индекс (или -1 в случае отсутствия 
элемента).
$.isArray() Проверяет, является ли заданный элемент массивом.
$.isEmptyObject() Проверяет наличие (точнее отсутствие) содержимого в 
заданном объекте.
$.isFunction() Проверяет, является ли заданный элемент функцией.
$.isNumeric()  Проверяет, является ли заданный элемент числом.
$.isPlainObject() Проверяет, является ли заданный элемент 
пользовательским объектом (задан 
средствами «{}» или «new Object»).
$.isWindow() Проверяет, является ли заданный элемент объектом типа 
window.
$.isXMLDoc() Проверяет, находится ли DOM-объект внутри XML-документа (или сам является XML-документом).
$.makeArray()  Конвертирует массиво подобные объекты, в массивы.
$.map() Выполняет заданную функцию для каждого элемента 
массива или каждого поля объекта в отдельности.
$.merge() Объединяет содержимое нескольких массивов, записывая 
его в первый из них.
$.noop()  Пустая функция.
$.parseJSON()  Конвертирует строку с json-данными в javascript-объект.
$.parseXML() Конвертирует строку xml в xml-документ.
$.proxy() По заданной функции, создает другую, внутри которой 
переменная this будет равна заданному значению.
$.trim()  Удаляет пробелы из начала и конца заданной строки.
$.type() Определяет класс заданного объекта (речь идет о 
внутренних классах javascript: string, boolean и т.д.).
$.unique() Сортирует заданный массив с DOM-элементами, 
выстраивая их в порядке расположения в DOM, а так же 
удаляя повторения.

Объект-обработчик: handleEvent

Мы можем назначить обработчиком не только функцию, но и объект при помощи addEventListener . В этом случае, когда происходит событие, вызывается метод объекта handleEvent .

Как видим, если addEventListener получает объект в качестве обработчика, он вызывает object.handleEvent(event) , когда происходит событие.

Мы также можем использовать класс для этого:

Здесь один и тот же объект обрабатывает оба события

Обратите внимание, мы должны явно назначить оба обработчика через addEventListener. Тогда объект menu будет получать события mousedown и mouseup , но не другие (не назначенные) типы событий

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

Теперь обработка событий разделена по методам, что упрощает поддержку кода.

События объектов:

Событие Описание
bubbles показывает является ли событие — bubbles событием;
cancelable показывает является ли событие — cancelable событием;
currentTarget возвращает элемент, событие которого было вызвано;
defaultPrevented показывает был вызван метод preventDefault() для события;
eventPhase возвращает текущую фазу потока события;
isTrusted показывает является ли событие — trusted событием;
target возвращает элемент, который вызвал событие;
timeStamp возвращает время с момента срабатывания события;
type возвращает имя события элемента;
view возвращает ссылку объекту Window, где произошло событие;
preventDefault() предотвращает реагирование объекта на событие;
stopImmediatePropagation() предотвращает реагирование на прослушивание объекта 
stopPropagation() предотвращает реагирование объекта на дальнейшие события.

Что такое Event loop

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

Идея Event loop очень проста. Есть бесконечный цикл, в котором движок JavaScript ожидает задачи, исполняет их и снова ожидает появления новых.

Задачи в очереди не обрабатываются одинаково. Они делятся на микрозадачи и макрозадания. Вместо того чтобы смешиваться, эти два типа задач занимают разные очереди.

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

Одна макро-задача выполняется из очереди макро-задачи (Task) внутри очереди. По завершении этой задачи цикл событий переходит в очередь микрозадач (Job). «Цикл событий» не просматривает следующее действие до завершения всей очереди микрозадач (заданий). Он завершает всю очередь микро-задач, а затем возвращается в очередь макро-задач.

Очередь задач → Микро-задача → Рендеринг → Макро-задача

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

Более упрощённый алгоритм событийного цикла:

  • выбрать и исполнить самую старую задачу из очереди макрозадач (например, «script»);
  • выполнить все микрозадачи;
  • пока очередь микрозадач не пуста; выбрать из очереди и исполнить самую старую микрозадачу;
  • отрисовать изменения страницы, если они есть;
  • если очередь макрозадач пуста – подождать, пока появится макрозадача;
  • Перейти к шагу 1.

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

Подробнее о Event loop здесь.

Всплывающие события

Рассмотрим следующий код:

Обработчик щелчка привязывается ко всем элементам в документе (чего вы никогда не должны делать в реальном коде), а также для document и window. Что произойдёт, когда вы щёлкните по элементу <a>, который находится внутри других элементов? На деле, событие click сработает для элемента <a>, а также для всех элементов, которые содержат <a> — весь путь до document и window.

Такое поведение называется всплывающее событие — событие срабатывает на элементе, по которому пользователь щёлкнул и если вы не вызовите .stopPropagation() для объекта события, то запустится весь путь вверх по DOM.

Вы можете увидеть это более наглядно, когда проанализируете такую разметку:

И следующий код:

При щелчке по «Я ссылка!» вы на самом деле щёлкаете не на <a>, а на <span> внутри ссылки. Вместе с тем, всплывающее событие дойдёт до <a> и сработает связанный с ним обработчик click.

Виды событий в JavaScript

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

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

Вторая группа событий — это семантические события — высокоуровневые события. Они более сложны — это уже не просто какие-то сигналы, а, как правило, результат выполнения какой-то операции. Например, завершение загрузки страницы в браузер.

Часто такие события являются результатом выполнения одного или нескольких
низкоуровневых событий. Например, когда пользователь щелкает по кнопке SUBMIT,
вызываются три обработчика событий ввода:
(нажатие кнопки мыши), (отпускание кнопки мыши) и
(щелчок кнопки мыши). И в итоге щелчок по кнопке мыши
приводит к тому, что HTML-форма, на которой находится кнопка SUBMIT,
генерирует высокоуровневое событие .

Кроме того, существуют аппаратно-зависимые и аппаратно-независимые события. Аппаратно-зависимые связаны с аппаратной частью (обычно это мышь и клавиатура). Аппаратно-независимые события могут быть вызваны несколькими способами.

Например, ввод данных в поле с помощью клавиатуры — это аппаратно-зависимое событие. Обычно к аппаратно-зависимым относятся события ввода.

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

Вообще о событиях и их обработчиках можно говорить очень долго. У этой статьи другая цель — просто познакомить вас с событиями. Поэтому я приведу небольшой пример и закончу на этом.

<input type="button" 
       value="Это кнопка" 
       onclick="document.write('Вы щёлкнули по кнопке');">

Это пример простейшего использования событий. В данном случае мы
“отлавливаем” событие onclick (щёлчок по кнопке), и, когда это событие происходит, вызывается и выполняется обработчик этого события, код которого прописан после наименования события.

Если обработчик события содержит большое количество строк кода, то лучше
определить его в виде функции, а для атрибута HTML уже прописать не код обработчика, а имя этой функции-обработчика. Например:

<script>
<!--

function Calc22()
{
  document.write("2 + 2 = 4" );
}

// -->
</script>

<input type="button" 
       value="Сколько будет 2 + 2 ?" 
       onclick="Calc22();">

Повторюсь — события в JavaScript — это очень объёмная тема. В книгах по JavaScript ей посвящены целые разделы. Конечно, рассказать обо всём в одной статье невозможно. Если хотите знать больше, то вам сюда:

Scope и Scope Chain

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

function a() {
  function b() {
    console.log(foo); // logs 'bar'
  }

  var foo = 'bar';
  b();
}

a();

При достижении console.log(foo), движок JavaScript сначала проверит, есть ли переменная foo в области контекста выполнения b(). Поскольку там ее нет, он перейдет в «родительский» контекст выполнения, который является контекстом выполнения a(), просто потому, что b() объявлен внутри a(). В области видимости этого контекста выполнения он найдет foo и выведет ее значение.

Если мы определим b() вне a(), вот так:

function a() {
  var foo = 'bar';
  b();
}

function b() {
  console.log(foo); // throws ReferenceError: foo is not defined
}

a();

Будет сгенерировано ReferenceError, хотя единственное различие между ними заключается в месте, где объявлено b().

«Родительская» область действия b() теперь является глобальной областью контекста выполнения, поскольку она объявляется на глобальном уровне вне какой-либо функции, и там нет переменной foo.

Я могу понять, почему это может сбивать с толку, потому что, если вы посмотрите на стек выполнения, это выглядит так:

JavaScript execution stack

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

В первом примере контекст выполнения a() действительно является «родительским» контекстом выполнения b(). Не потому, что a() является следующим элементом в стеке выполнения, чуть ниже b(), а просто потому, что b() объявлен внутри a().

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

Просто помните: не важно, где вызывается функция, важно, где она объявлена. Но что произойдет, если она не сможет найти переменную в области «родительского» контекста выполнения?

Но что произойдет, если она не сможет найти переменную в области «родительского» контекста выполнения?

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

Если его там тоже нет, он попробует следующий и т. д., пока в конце концов не достигнет глобальной области контекста выполнения. Если он не сможет найти его там, он выдаст ReferenceError.

Это называется цепочкой областей действия (scope chain), и это именно то, что происходит в следующем примере:

function a() {
  function b() {
    function c() {
      console.log(foo);
    }
    
    c();
  }
  
  var foo = 'bar';
  b();
}

a();

Сначала он пытается найти foo в области контекста выполнения c(), затем b(), а затем, в конце концов, a(), где он его найдет.

Примечание: Помните, что движок переходит только от c() к b() и a(), потому что они объявлены внутри другого, а не потому, что их соответствующие контексты выполнения располагаются поверх другого в стеке выполнения.

Если они не будут объявлены внутри другого, тогда «родительский» контекст выполнения будет другим, как объяснено выше.

Однако, если бы внутри c() или b() была другая переменная foo, ее значение было бы выведено на консоль, потому что движок прекратит «поиск» «родительских» контекстов выполнения, как только найдет переменную.

То же самое относится и к функциям, а не только к переменным, и то же относится к глобальным переменным.

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

Контекст выполнения функции

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

Эти правила определяются организацией по стандартизации Ecma International, и вместе они образуют документ спецификации языка (вы можете найти последнюю версию здесь).

Таким образом, когда движок преобразует код JavaScript в машинный код, он должен учитывать спецификации.

Что если код содержит недопустимое присваивание или он пытается получить доступ к переменной, которая, согласно спецификации языка, не должна быть доступна из этой конкретной части кода?

Каждый раз, когда вызывается функция, ей нужно все это понять. Это достигается путем создания оболочки, называемой контекстом выполнения (execution contex).

Чтобы быть более конкретным и избежать путаницы в будущем, я буду называть этот контекст выполнения функции (function execution context), потому что он создается каждый раз, когда вызывается функция. Не пугайтесь этого термина и не думайте о нем слишком много сейчас, он будет подробно описано позже.

Просто помните, что он определяет такие вещи, как: «Какие переменные доступны в этой конкретной функции, какое значение this внутри нее, какие переменные и функции объявлены внутри нее?»

Методы интерфейса

Метод Описание Chrome Firefox Opera Safari IExplorer Edge
composedPath() Возвращает путь события, представляющий собой массив объектов, на которых будут вызваны обработчики событий. 53.0 52.0 40.0 10.0 Нет Нет
preventDefault() Если этот метод вызывается, то действие события по умолчанию не будет срабатывать (отменяет действие события по умолчанию). Событие продолжает распространяться как обычно, только с тем исключением, что событие ничего не делает. Да Да Да Да 9.0 Да
stopImmediatePropagation() Прекращает дальнейшую передачу текущего события (предотвращает всплытие по дереву DOM) и останавливает цепочку вызова событий для текущего элемента. Да Да Да Да 9.0 Да
stopPropagation() Прекращает дальнейшую передачу текущего события (предотвращает всплытие по дереву DOM). Да Да Да Да 9.0 Да

Объект-обработчик: handleEvent

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

К примеру:

Как видим, если получает объект в качестве обработчика, он вызывает , когда происходит событие.

Мы также можем использовать класс для этого:

Здесь один и тот же объект обрабатывает оба события

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

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

Теперь обработка событий разделена по методам, что упрощает поддержку кода.

Этапы контекста выполнения функции

Теперь, когда мы знакомы с жизненным циклом выполнения JavaScript-программы, давайте еще немного углубимся в то, как именно создается контекст выполнения функции.

Это происходит в два этапа: этап создания и этап выполнения.

Этап создания «настраивает» так, что код может быть выполнен, а этап выполнения фактически выполняет его.

На этапе создания происходят две вещи, которые очень важны:

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

Каждый из них подробно описан в следующих двух соответствующих разделах.

Что такое функция карри

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

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

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

Подробнее о каррировании здесь, также здесь.

Проверка формы на JavaScript

И в конец данной статьи разберём простой пример обработки формы. Обработка формы на JavaScript, во-первых, уменьшает загрузку на сервер и во-вторых придаёт дополнительный плюс к юзабилити сайта.

Форма состоится из одного поля для логина, и кнопки отправить. При отправке формы, будем проверять длину логина. Его длина должна быть больше трёх символов.

Начнём, мы с HTML структуры данной формы.

<form method="GET" name="myform" action="" >

    <p>
        <input type="text" name="login" />
    </p>

    <p>
        <input type="submit" name="send" value="Отправить" />
    </p>
    
</form>

Теперь, тегу формы добавим в качестве атрибута обработчик onsubmit, события submit. Следующим образом:

<form method="GET" name="myform" action="" onsubmit = "return checkForm(this)" >

Событие submit срабатывает при отправке формы. Оператора return мы написали для того чтобы запретить отправку формы, в случае обнаружения ошибки в вводе данных. Если функция вернёт значение false, то значение обработчика onsubmit будет «return false», это значит, что форма не отправиться на сервер. В противном случае, если форма вернёт true, то значение обработчика будет «return true» и форма отправится без проблем.

Иногда бывает необходимо чтобы полностью запретить отправку формы, в таком случае значение обработчика onsubmit будет таким:

onsubmit = "checkForm(this); return false;" 

Как Вы наверняка уже догадались, checkForm это название функции, которая вызовется, когда сработает событие submit. Вы можете назвать её как хотите, следуя правилам наименования функции.

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

function checkForm(form){

    //Получаем значение поля формы, у которой name равен login
    var login = form.login.value;

    //Проверяем, если длина логина меньше трёх символов то выводим сообщение об ошибке и отменяем отправку формы.
    if( login.length > 3){
        alert('Длина логина должна быть больше трёх символов');
        return false;
    }else{
        return true;
    }

}

Сохраняем документ, открываем его в браузере и тестируем.

Таким вот образом можно проверить форму на языке JavaScript и отменить её отправку в случае ошибки.

Ну и на этом всё дорогие читатели. Подведём итоги. События используются очень часто, поэтому Вы должны уметь работать с ними на все 100.

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

Задачи

  1. Создайте простой калькулятор сложения цифр.

    • Создайте форму с двумя числовыми полями(type=»number») для ввода чисел и кнопку с надписью «Сложить»
    • При нажатии на кнопку отправить, вызовите функцию обработки данного события.
    • Внутри функции получите значения полей и методом alert, выведите результат сложения введённых чисел.
    • Сделайте так чтобы форма не отправлялось после нажатия по кнопке.

Тогда поделитесь ею с друзьями и подпишитесь на новые интересные статьи.

Поделиться с друзьями:

Подписаться на новые статьи:

Поддержите пожалуйста мой проект!

Добавляйтесь ко мне в друзья в:

  • — ВКонтакте

  • — Facebook
  • — Одноклассниках

Добавляйтесь в мои группы:

  • — Группа в ВКонтакте
  • — Группа в Facebook
  • — Группа в Одноклассниках

Подпишитесь на мои каналы:

  • — Мой канал на Youtube
  • — Мой канал на Google+

Автор статьи: Мунтян Сергей

Копирование материалов с сайта sozdatisite.ru ЗАПРЕЩЕНО!!!

Дата добавления: %date%

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Люкс-хост
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: