Как вызвать функцию при клике? js
Есть вот такой вот код, который берёт инфу из localStorage и отрисовывает её на другой вкладке. Всё работает нормально до тех пор, пока я не повешу эту функцию на клик. Когда я вышаю на клик и перехожу на ту вкладку, где должна отрисовываться инфа, то мне пишет Cannot read property ‘addEventListener’ of null. ticketButton находится во вкладке, где нужно тыкнуть на эту кнопку и и отобразить инфу на на другую вкладку в блок ticketsContainer
ticketButton.addEventListener('click', () => < displayTickets(); >) function displayTickets() < let seatsItems = JSON.parse(localStorage.getItem('seats')); let time = localStorage.getItem('time'); let day = localStorage.getItem('day'); let ticketsContainer = document.querySelector('.ticketsContainer'); if(seatsItems && ticketsContainer) < ticketsContainer.innerHTML = ''; Object.values(seatsItems).map(item =>< ticketsContainer.innerHTML += ` Ваш ряд: $ Ваше место: $
$, $
`; >) > >
Отслеживать
Денис Коваль
задан 15 окт 2020 в 19:06
Денис Коваль Денис Коваль
45 6 6 бронзовых знаков
Тут приходится гадать, что за вкладки (браузера или самописные какие-то), где ticketButton и прочее. Отредактируйте вопрос, иначе ответы будут пальцем в небо пока вам не понравится.
– user347472
15 окт 2020 в 19:13
Всё, вроде бы написал понятно
15 окт 2020 в 19:17
Ну вы умалчиваете что за вкладки, почему ticketButton становится null не ясно. Возможно у вас этот код вызывается в каждой вкладке, например повешен на » tab.onchаnge » и во второй вкладке просто нет кнопки. В общем не ясно как отвечать, не хватает информации. Вкладок в вашем коде нет, заметьте, а вы про них говорите.
– user347472
15 окт 2020 в 19:21
У меня есть два html файла, в первом находится кнопка, во вторном контейнер, куда должна отрисовываться инфа. И функция работает как следует до тех пор, пока не повешу её на кнопку, которая находится в первом html файле. Второй html с контейнером так же как и первый подключён к одному js файлу
15 окт 2020 в 19:25
Возможно нужно второй html, который сблоком, подключить к отдельному js файлу, и уже в нём доставать эту инфу из localStorage, но мне ведь нужно повесить эту функцию на кнопку.
Пять способов вызвать функцию
Мне часто приходится сталкиваться с JavaScript-кодом, ошибки в котором вызваны неправильным понимаем того, как работают функции в JavaScript (кстати, значительная часть такого кода была написана мной самим). JavaScript — язык мультипарадигменный, и в нем имеются механизмы функционального программирования. Пора изучить эти возможности. В этой статье я расскажу вам о пяти способах вызова функций в JavaScript.
На первых этапах изучения JavaScript новички обычно думают, что функции в нем работают примерно так же, как, скажем, в C#. Но механизмы вызова функций в JavaScript имеют ряд важных отличий, и незнание их может вылиться в ошибки, которые будет непросто найти.
Давайте напишем простую функцию, которая возвращает массив из трех элементов — текущего значения this и двух аргументов, переданных в функцию.
function makeArray(arg1, arg2)
Самый распространенный способ: глобальный вызов
Новички часто объявляют функции так, как показано в примере выше. Вызвать эту функцию не составляет труда:
makeArray('one', 'two'); // => [ window, 'one', 'two' ]
Погодите. Откуда взялся объект window ? Почему это у нас this равен window ?
В JavaScript, неважно, выполняется ли скрипт в браузере или в ином окружении, всегда определен глобальный объект. Любой код в нашем скрипте, не «привязанный» к чему-либо (т.е. находящийся вне объявления объекта) на самом деле находится в контексте глобального объекта. В нашем случае, makeArray — не просто функция, «гуляющая» сама по себе. На самом деле, makeArray — метод глобального объекта (в случае исполнения кода в браузере) window . Доказать это легко:
alert( typeof window.methodThatDoesntExist ); // => undefined alert( typeof window.makeArray ); // => function
То есть вызов makeArray(‘one’, ‘two’); равносилен вызову window.makeArray(‘one’, ‘two’); .
Меня печалит тот факт, что этот способ вызова функций наиболее распространен, ведь он подразумевает наличие глобальной функции. А мы все знаем, что глобальные функции и переменные — не самый хороший тон в программировании. Особенно это справедливо для JavaScript. Избегайте глобальных определений, и не пожалеете.
Правило вызова функций №1: Если функция вызывается напрямую, без указания объекта (например, myFunction() ), значением this будет глобальный объект ( window в случае исполнения кода в браузере).
Вызов метода
Давайте создадим простой объект и сделаем makeArray его методом. Объект объявим с помощью литеральной нотации, а после вызовем наш метод:
// создаем объект var arrayMaker = < someProperty: 'какое-то значение', make: makeArray >; // вызываем метод make() arrayMaker.make('one', 'two'); // => [ arrayMaker, 'one', 'two' ] // альтернативный синтаксис, используем квадратные скобки arrayMaker['make']('one', 'two'); // => [ arrayMaker, 'one', 'two' ]
Видите разницу? Значение this в этом случае — сам объект. Почему не window , как в предыдущем случае, ведь объявление функции не изменилось? Весь секрет в том, как передаются функции в JavaScript. Function — это стандартный тип JavaScript, являющийся на самом деле объектом, и как и любой другой объект, функции можно передавать и копировать. В данном случае, мы как бы скопировали всю функцию, включая список аргументов и тело, и присвоили получившийся объект свойству make объекта arrayMaker . Это равносильно такому объявлению:
var arrayMaker = < someProperty: 'Какое-то значение'; make: function (arg1, arg2) < return [ this, arg1, arg2]; >>;
Правило вызова функций №2: В функции, вызванной с использованием синтаксиса вызова метода, например, obj.myFunction() или obj[‘myFunction’]() , this будет иметь значение obj .
Непонимание этого простого, в общем-то, принципа часто приводит к ошибкам при обработке событий:
Щелчок по первой кнопке покажет сообщение «btn1», потому что в данном случае мы вызываем функцию как метод, и this внутри функции получит значение объекта, которому этот метод принадлежит. Щелчок по второй кнопке выдаст «window», потому что в этом случае мы вызываем buttonClicked напрямую (т.е. не как obj.buttonClicked() ). То же самое происходит, когда мы назначаем обработчик события в тэге элемента, как в случае третьей кнопки. Щелчок по третьей кнопке покажет то же самое сообщение, что и для второй.
При использовании библиотек вроде jQuery думать об этом не надо. jQuery позаботится о том, чтобы переписать значение this в обработчике события так, чтобы значением this был элемент, вызвавший событие:
// используем jQuery $('#btn1').click( function() < alert( this.id ); // jQuery позаботится о том, чтобы 'this' являлась кнопкой >);
Каким образом jQuery удается изменить значение this ? Читайте ниже.
Еще два способа: apply() и call()
Логично, что чем чаще вы используете функции, тем чаще вам приходится передавать их и вызывать в разных контекстах. Зачастую возникает необходимость переопределить значение this . Если вы помните, функции в JavaScript являются объектами. На практике это означает, что у функций есть предопределенные методы. apply() и call() — два из них. Они позволяют переопределять значение this :
var car = < year: 2008, model: 'Dodge Bailout' >; makeArray.apply( car, [ 'one', 'two' ] ); // => [ car, 'one', 'two' ] makeArray.call( car, 'one', 'two' ); // => [ car, 'one', 'two' ]
Эти два метода очень похожи. Первый параметр переопределяет this . Различия между ними заключаются в последющих аргументах: Function.apply() принимает массив значений, которые будут переданы функции, а Function.call() принимает аргументы раздельно. На практике, по моему мнению, удобнее применять apply() .
Правило вызова функций №3: Если требуется переопределить значение this , не копируя функцию в другой объект, можно использовать myFunction.apply( obj ) или myFunction.call( obj ) .
Конструкторы
Я не буду подробно останавливаться на объявлении собственных типов в JavaScript, но считаю необходимым напомнить, что в JavaScript нет классов, а любой пользовательский тип нуждается в конструкторе. Кроме того, методы пользовательского типа лучше объявлять через prototype , который является свойством фукции-конструктора. Давайте создадим свой тип:
// объявляем конструктор function ArrayMaker(arg1, arg2) < this.someProperty = 'неважно'; this.theArray = [ this, arg1, arg2 ]; >// объявляем методы ArrayMaker.prototype = < someMethod: function () < alert('Вызван someMethod'); >, getArray: function () < return this.theArray; >>; var am = new ArrayMaker( 'one', 'two' ); var other = new ArrayMaker( 'first', 'second' ); am.getArray(); // => [ am, 'one', 'two' ]
Важным в этом примере является наличие оператора new перед вызовом функции. Если бы не он, это был бы глобальный вызов, и создаваемые в конструкторе свойства относились бы к глобальному объекту. Нам такого не надо. Кроме того, в конструкторах обычно не возвращают значения явно. Без оператора new конструктор вернул бы undefined , с ним он возвращает this . Хорошим стилем считается наименование конструкторов с заглавной буквы; это позволит вспомнить о необходимости оператора new .
В остальном, код внутри конструктора, скорее всего, будет похож на код, который вы написали бы на другом языке. Значение this в данном случае — это новый объект, который вы создаете.
Правило вызова функций №4: При вызове функции с оператором new , значением this будет новый объект, созданный средой исполнения JavaScript. Если эта функция не возвращает какой-либо объект явно, будет неявно возвращен this .
Заключение
Надеюсь, понимание разницы между разными способами вызова функций возволит вам улучшить ваш JavaScript-код. Иногда непросто отловить ошибки, связанные со значением this , поэтому имеет смысл предупреждать их возникновение заранее.
Создаём свою функцию
Эта статья призвана дать практический опыт на основе теоретических знаний приведённых в предыдущей статье. Попутно мы также объясним некоторые важные детали работы с функциями.
Предпосылки: | Базовая компьютерная грамотность, базовое понимание HTML и CSS, первые шаги в JavaScript, Функции — блоки кода используемые многократно. |
---|---|
Задача: | Научить создавать пользовательской функции и объяснить ещё несколько полезных деталей. |
Активное обучение: построение функции
Пользовательская функция, которую мы собираемся построить, будет называться displayMessage() . Она отобразит настраиваемое окно сообщения на веб-странице и будет действовать как настраиваемая замена встроенной в браузер функции alert(). Мы видели эту функцию раньше. Введите следующую команду в консоли JavaScript браузера на любой странице:
alert("This is a message");
Функция alert принимает один аргумент — строку, которая отображается в окне сообщения на веб-странице Попробуйте изменить строку, чтобы изменить сообщение.
Функция alert ограничена: вы можете изменить текст сообщения, но не получится изменить его стиль, например, цвет, значок или что-то ещё. Создадим сообщение, более интересное по стилю.
Примечание: Этот пример будет работать во всех современных браузерах, но стиль может выглядеть немного смешным в более старых браузерах. Мы рекомендуем вам выполнять это упражнение в современном браузере, таком как Firefox, Opera или Chrome.
Основная функция
Для начала давайте соберём основную функцию.
Примечание: Для согласований имён функций нужно следовать тем же правилам, что и правила именования переменных. Отличить имена функций от имён переменных просто: после имён функций указываются круглые скобки, а после имён переменных их нет.
- Откройте файл function-start.html и скопируйте его себе на компьютер. Код HTML в нем предельно прост: body содержит только одну кнопку. Также здесь представлен базовый CSS для создания настраиваемого окна сообщений и пустой элемент для размещения нашего JavaScript.
- Затем добавьте строку внутри элемента :
function displayMessage() >
var html = document.querySelector("html"); var panel = document.createElement("div"); panel.setAttribute("class", "msgBox"); html.appendChild(panel); var msg = document.createElement("p"); msg.textContent = "This is a message box"; panel.appendChild(msg); var closeBtn = document.createElement("button"); closeBtn.textContent = "x"; panel.appendChild(closeBtn); closeBtn.onclick = function () panel.parentNode.removeChild(panel); >;
Рассмотрим этот код по строкам (прим. — в оригинале статьи: «bit by bit»).
var html = document.querySelector("html");
Затем мы используем ещё одну функцию DOM API, называемую Element.setAttribute() , чтобы установить атрибут class на нашей панели со значением msgBox . Это упрощает стилизацию элемента. Если вы посмотрите на CSS на странице, вы увидите, что мы используем селектор класса .msgBox для стилизации окна сообщения и его содержимого.
Наконец, мы вызываем функцию DOM с именем Node.appendChild() в переменной html , которую мы сохранили ранее, которая вкладывает один элемент в другой как его дочерний элемент. Указываем панель как дочерний элемент, который мы хотим вложить внутрь элемента . То есть, когда мы создаём какой-то элемент, он не просто будет отображаться на странице сам по себе, нам нужно указать, куда его поместить.
var panel = document.createElement("div"); panel.setAttribute("class", "msgBox"); html.appendChild(panel);
В следующих двух разделах используются те же функции createElement() и appendChild() , которые мы уже видели, чтобы создать два новых элемента: и , и вставить их на страницу, как дочерних элементов панели . Мы используем свойство Node.textContent , которое представляет текстовое содержимое элемента, для вставки сообщения внутри абзаца и символ «x» внутрь кнопки. Нажатие/активация этой кнопки будет закрывать окно сообщения.
var msg = document.createElement("p"); msg.textContent = "This is a message box"; panel.appendChild(msg); var closeBtn = document.createElement("button"); closeBtn.textContent = "x"; panel.appendChild(closeBtn);
В заключении мы используем обработчик событий GlobalEventHandlers.onclick , чтобы при нажатии кнопки был запущен некоторый код для удаления всей панели со страницы, т.е. для закрытия окна сообщения.
Вкратце, обработчик onclick — это свойство, доступное для кнопки (или, фактически, для любого элемента страницы), которое можно установить в функцию, чтобы указать, какой код следует запускать при нажатии кнопки. Вы узнаете об этом больше в нашей статье о последующих событиях. Мы делаем обработчик onclick равным анонимной функции, которая содержит код, запускаемый при нажатии кнопки. Строка внутри функции использует функцию Node.removeChild() DOM API, чтобы указать, что мы хотим удалить определённый дочерний элемент внутри HTML — в данном случае панель .
.onclick = function () panel.parentNode.removeChild(panel); >;
В принципе, весь этот блок кода генерирует блок HTML, который выглядит так и вставляет его на страницу:
div class="msgBox"> p>This is a message boxp> button>xbutton> div>
Вам не обязательно запоминать сейчас, как работает каждый элемент во всем этом коде. Основная задача — понять структуру и использование функции, при этом мы хотели показать что-то интересное для этого примера.
Вызов функции
Теперь у вас есть определение функции, написанное в вашем элементе , но оно ничего не будет делать в том виде, в каком оно есть.
-
Попробуйте написать следующую строку под своей функцией, чтобы вызвать её:
displayMessage();
var btn = document.querySelector("button");
.onclick = displayMessage;
Возможно, вам интересно, почему мы не включили круглые скобки после имени функции. Это связано с тем, что нам нужно не сразу вызвать функцию, а только после нажатия кнопки. Если вы попытаетесь изменить строку на
.onclick = displayMessage();
сохраните и перезагрузите страницу, вы увидите, что окно сообщения появляется без нажатия кнопки! Скобки в этом контексте иногда называют «оператором вызова функции». Вы используете их только в том случае, если хотите немедленно запустить функцию в текущей области. В этом же отношении код внутри анонимной функции не запускается сразу, так как он находится внутри области функций.
Если вы пробовали последний эксперимент, перед тем, как продолжить, обязательно отмените последнее изменение.
Улучшение функции с параметрами
В нынешнем виде функция по-прежнему не очень полезна — мы не хотим показывать одно и то же сообщение по умолчанию каждый раз. Давайте улучшим нашу функцию, добавив некоторые параметры, позволяющие нам называть её различными вариантами.
-
Прежде всего, обновите первую строку функции:
function displayMessage()
function displayMessage(msgText, msgType)
.textContent = "This is a message box";
.textContent = msgText;
.onclick = displayMessage;
к этому блоку:
.onclick = function () displayMessage("Woo, this is a different message!"); >;
Более сложный параметр
Переход к следующему параметру. Это потребует немного больше работы. Установим его так, чтобы в зависимости от того, какой параметр msgType установлен, функция отображала другой значок и другой цвет фона.
-
Для начала, загрузите значки, необходимые для этого упражнения (warning и chat [тут чёрные иконки на чёрном фоне. тролли на GitHub]) из GitHub. Сохраните их в новой папке icons в том же месте, что и ваш HTML-файл.
Примечание: иконки warning и chat были найдены на iconfinder.com, и разработаны Nazarrudin Ansyari. Спасибо! (Фактические страницы значков были перемещены или удалены.)
width: 200px;
измените на:
width: 242px;
padding-left: 82px; background-position: 25px center; background-repeat: no-repeat;
if (msgType === "warning") msg.style.backgroundImage = "url(icons/warning.png)"; panel.style.backgroundColor = "red"; > else if (msgType === "chat") msg.style.backgroundImage = "url(icons/chat.png)"; panel.style.backgroundColor = "aqua"; > else msg.style.paddingLeft = "20px"; >
displayMessage("Woo, this is a different message!");
к одному из них:
displayMessage("Your inbox is almost full — delete some mails", "warning"); displayMessage("Brian: Hi there, how are you today?", "chat");
Примечание: Если у вас возникли проблемы с запуском примера, не стесняйтесь проверять свой код на готовой версии GitHub (см. также в режиме реального времени) или обратитесь к нам за помощью.
Вывод
В этой статье мы познакомились со всем процессом создания практической пользовательской функции, которую с небольшими доработками можно перенести в реальный проект. В следующей статье мы рассмотрим ещё одну важную концепцию — возвращаемые значения функций.
В этом модуле
- Принятие решений в вашем коде — условные конструкции
- Зацикливание кода
- Функции — Переиспользуемые блоки кода
- Создайте свою собственную функцию
- Возвращаемое значение функции
- Введение в события
- Создание галереи
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 3 авг. 2023 г. by MDN contributors.
Your blueprint for a better internet.
Вызов функций JavaScript
Код внутри функции JavaScript не выполняется, когда эта функция определяется. Он выполняться только тогда, когда эта функция будет «запущена».
Обычно говорят «вызвать функцию» или «выполнить функцию».
Запуск функции как функции
function myFunction(a, b) < return a * b; >myFunction(10, 2); // вернет 20
Функция в предыдущем примере не принадлежит какому-либо объекту. Однако в JavaScript всегда существует «дефолтный» глобальный объект.
В HTML таким глобальным объектом является HTML страница, таким образом, функция из предыдущего примера «принадлежит» текущей HTML странице.
В браузере объект страницы — это окно браузера или объект window. Так, функция из примера автоматически становится функцией объекта window. Таким образом, myFunction() и window.myFunction() это одна и та же функция:
function myFunction(a, b) < return a * b; >window.myFunction(10, 2); // также вернет 20
Это обычный способ вызывать функции JavaScript. Однако, это не очень хорошая практика. Глобальные переменные, методы или функции могут создавать конфликты имен и приводить к сбоям в глобальном объекте.
Ключевое слово this
В JavaScript ключевое слово this — это объект, который «владеет» текущим кодом.
При использовании в функции значением ключевого слова this является объект, который «владеет» данной функцией.
Обратите внимание, что this — это не переменная, а ключевое слово. Вы не можете изменять его значение.
Глобальный объект
Когда функция вызывается без объекта-владельца, значением ключевого слова this становится глобальный объект.
В браузере глобальный объект — это окно браузера (объект window).
В следующем примере функция возвращает объект window:
var x = myFunction(); // значением x будет объект window function myFunction()
Внимание! Вызов функции как глобальной, устанавливает this на глобальный объект. Использование объекта window в качестве переменной может привести к краху вашей программы.
Вызов функции как метода
В JavaScript вы можете определять функции как методы объектов.
В следующем примере создается объект (myObject) с двумя свойствами (firstName и lastName) и одним методом (fullName):
var myObject = < firstName:"John", lastName: "Doe", fullName: function () < return this.firstName + " " + this.lastName; >> myObject.fullName(); // вернет "John Doe"
Метод fullName — функция. Эта функция принадлежит объекту. Объект myObject — владелец функции fullName.
Ключевое слово this указывает на объект, который «владеет» данным кодом JavaScript. В данном случае значением ключевого слова this является объект myObject:
var myObject = < firstName:"John", lastName: "Doe", fullName: function () < return this; >> myObject.fullName(); // вернет [object Object] (объект-владелец)
Вызов функции как метод объекта устанавливает в качестве значения ключевого слова this сам объект.
Вызов функции как конструктора объекта
Если перед вызовом функции стоит ключевое слово new, то это вызывается конструктор объекта.
Выглядит так, будто вы создаете новую функцию, но так как функции в JavaScript являются объектами, вы на самом деле создаете новый объект:
// Это функция конструктор: function myFunction(arg1, arg2) < this.firstName = arg1; this.lastName = arg2; >// Это создает новый объект var x = new myFunction("John", "Doe"); x.firstName; // вернет "John"
Вызов конструктора создает новый объект. Новый объект наследует свойства и методы своего конструктора.
У ключевого слова this в конструкторе нет значения. Значением ключевого слова this станет новый объект, созданный при вызове функции конструктора.