Javascript reference
Содержание:
- 9) onReady()
- Функции == Комментарии
- Расширение типов
- Синтаксис
- new Function
- Outer variables
- Внутренняя реализация: Ссылочный тип
- Параметры по умолчанию
- Свойства функции
- Объявление и вызов функции
- Событие onclick javaScript и три способа обработки событий
- «Поднятие» переменных и функций
- Параметры функции
- Вызов функции как функции
- Примеры методов
- Функции-генераторы в «ES6»
- Выбор имени function
- Объект arguments
- JS Tutorial
- Проблема «несуществующего свойства»
- В интернете кто-то не прав
- Итого
- Итого
9) onReady()
Для инициализации страницы исторически использовалось событие window.onload, которое срабатывает после полной загрузки страницы и всех объектов на ней: счетчиков, картинок и т.п.
Событие — гораздо лучший выбор в 99% случаев. Это событие срабатывает, как только готов DOM документ, до загрузки картинок и других не влияющих на структуру документа объектов.
Это очень удобно, т.к. картинки могут загружаться долго, а обработчик может произвести необходимые изменения на странице и инициализацию интерфейсов тут же, не дожидаясь загрузки всего.
Для добавления обработчика можно использовать следующий кроссбраузерный код:
function bindReady(handler){ var called = false function ready() { // (1) if (called) return called = true handler() } if ( document.addEventListener ) { // (2) document.addEventListener( "DOMContentLoaded", function(){ ready() }, false ) } else if ( document.attachEvent ) { // (3) // (3.1) if ( document.documentElement.doScroll && window == window.top ) { function tryScroll(){ if (called) return if (!document.body) return try { document.documentElement.doScroll("left") ready() } catch(e) { setTimeout(tryScroll, 0) } } tryScroll() } // (3.2) document.attachEvent("onreadystatechange", function(){ if ( document.readyState === "complete" ) { ready() } }) } // (4) if (window.addEventListener) window.addEventListener('load', ready, false) else if (window.attachEvent) window.attachEvent('onload', ready) /* else // (4.1) window.onload=ready */ }
readyList = [] function onReady(handler) { if (!readyList.length) { bindReady(function() { for(var i=0; i<readyList.length; i++) { readyList() } }) } readyList.push(handler) }
Использование:
onReady(function() { // ... })
Подробное описание функций , и принципы их работы вы можете почерпнуть в статье Кроссбраузерное событие onDOMContentLoaded.
Функции == Комментарии
Функции должны быть короткими и делать только что-то одно. Если это что-то большое, имеет смысл разбить функцию на несколько меньших. Иногда следовать этому правилу непросто, но это определённо хорошее правило.
Небольшие функции не только облегчают тестирование и отладку – само существование таких функций выполняет роль хороших комментариев!
Например, сравним ниже две функции . Каждая из них выводит простое число до .
Первый вариант использует метку :
Второй вариант использует дополнительную функцию для проверки на простое:
Второй вариант легче для понимания, не правда ли? Вместо куска кода мы видим название действия (). Иногда разработчики называют такой код самодокументируемым.
Таким образом, допустимо создавать функции, даже если мы не планируем повторно использовать их. Такие функции структурируют код и делают его более понятным.
Расширение типов
Часто может возникнуть необходимость присвоить переменной одного числового типа значение переменной другого числового типа. Как же это сделать?
В Java есть 4 целочисленных типа:
Тип | Размер |
---|---|
Переменной большего размера всегда можно присваивать переменные меньшего размера.
Переменной типа спокойно можно присваивать переменные типа , и . Переменной типа можно присваивать переменные типа и . Ну и переменной типа можно присваивать переменные типа .
Примеры:
Код | Описание |
---|---|
Этот код отлично скомпилируется. |
Такое преобразование, от типа меньшего размера к большему, называется расширением типа.
А что насчет вещественных чисел?
С ними все аналогично — размер имеет значение:
Тип | Размер |
---|---|
Переменной типа можно без проблем присвоить переменную типа . А вот с целочисленными типами интереснее.
Переменной типа можно присвоить переменную любого целочисленного типа. Даже типа , длина которого 8 байт. А переменной типа можно присвоить вообще что угодно: переменную любого целочисленного типа и переменную типа :
Код | Примечание |
---|---|
Обратите внимание, что преобразование к вещественному типу может привести к потере точности из-за нехватки значащих цифр. При преобразовании из целых чисел в дробные могут отбрасываться самые младшие части числа
Но т.к. смысл дробного числа в том, чтобы хранить приблизительное значение, такое присваивание разрешается
При преобразовании из целых чисел в дробные могут отбрасываться самые младшие части числа. Но т.к. смысл дробного числа в том, чтобы хранить приблизительное значение, такое присваивание разрешается.
Синтаксис
Синтаксис для объявления функции:
Функция создаётся с заданными аргументами и телом .
Это проще понять на конкретном примере. Здесь объявлена функция с двумя аргументами:
А вот функция без аргументов, в этом случае достаточно указать только тело:
Главное отличие от других способов объявления функции, которые были рассмотрены ранее, заключается в том, что функция создаётся полностью «на лету» из строки, переданной во время выполнения.
Все предыдущие объявления требовали от нас, программистов, писать объявление функции в скрипте.
Но позволяет превратить любую строку в функцию. Например, можно получить новую функцию с сервера и затем выполнить её:
Это используется в очень специфических случаях, например, когда мы получаем код с сервера для динамической компиляции функции из шаблона, в сложных веб-приложениях.
new Function
Существует ещё один способ создания функции, который используется очень редко, но упомянем и его для полноты картины.
Он позволяет создавать функцию полностью «на лету» из строки, вот так:
То есть, функция создаётся вызовом :
- Параметры функции через запятую в виде строки.
- Код функции в виде строки.
Таким образом можно конструировать функцию, код которой неизвестен на момент написания программы, но строка с ним генерируется или подгружается динамически во время её выполнения.
Пример использования – динамическая компиляция шаблонов на JavaScript, мы встретимся с ней позже, при работе с интерфейсами.
Outer variables
A function can access an outer variable as well, for example:
The function has full access to the outer variable. It can modify it as well.
For instance:
The outer variable is only used if there’s no local one.
If a same-named variable is declared inside the function then it shadows the outer one. For instance, in the code below the function uses the local . The outer one is ignored:
Global variables
Variables declared outside of any function, such as the outer in the code above, are called global.
Global variables are visible from any function (unless shadowed by locals).
It’s a good practice to minimize the use of global variables. Modern code has few or no globals. Most variables reside in their functions. Sometimes though, they can be useful to store project-level data.
Внутренняя реализация: Ссылочный тип
Продвинутая возможность языка
Этот раздел объясняет сложную тему, чтобы лучше понимать некоторые запутанные случаи.
Если вы хотите продвигаться быстрее, его можно пропустить или отложить.
Некоторые хитрые способы вызова метода приводят к потере значения , например:
В последней строчке кода используется условный оператор , который определяет, какой будет вызван метод ( или ) в зависимости от выполнения условия. В данном случае будет выбран .
Затем метод тут же вызывается с помощью скобок . Но вызов не работает как положено!
Вы можете видеть, что при вызове будет ошибка, потому что значением внутри функции становится (полагаем, что у нас строгий режим).
Так работает (доступ к методу объекта через точку):
Так уже не работает (вызываемый метод вычисляется):
Почему? Если мы хотим понять, почему так происходит, давайте разберёмся (заглянем под капот), как работает вызов методов ().
Присмотревшись поближе, в выражении можно заметить две операции:
- Сначала оператор точка возвращает свойство объекта – его метод ().
- Затем скобки вызывают этот метод (исполняется код метода).
Итак, каким же образом информация о передаётся из первой части во вторую?
Если мы поместим эти операции в отдельные строки, то значение , естественно, будет потеряно:
Здесь сохраняет функцию в переменной, и далее в последней строке она вызывается полностью сама по себе, без объекта, так что нет .
Для работы вызовов типа , JavaScript использует трюк – точка возвращает не саму функцию, а специальное значение «ссылочного типа», называемого .
Этот ссылочный тип (Reference Type) является внутренним типом. Мы не можем явно использовать его, но он используется внутри языка.
Значение ссылочного типа – это «триплет»: комбинация из трёх значений , где:
- – это объект.
- – это имя свойства объекта.
- – это режим исполнения. Является true, если действует строгий режим ().
Результатом доступа к свойству является не функция, а значение ссылочного типа. Для в строгом режиме оно будет таким:
Когда скобки применяются к значению ссылочного типа (происходит вызов), то они получают полную информацию об объекте и его методе, и могут поставить правильный ( в данном случае, по ).
Ссылочный тип – исключительно внутренний, промежуточный, используемый, чтобы передать информацию от точки до вызывающих скобок .
При любой другой операции, например, присваивании , ссылочный тип заменяется на собственно значение (функцию), и дальше работа уже идёт только с ней. Поэтому дальнейший вызов происходит уже без .
Таким образом, значение передаётся правильно, только если функция вызывается напрямую с использованием синтаксиса точки или квадратных скобок (они делают то же самое). Позднее в этом учебнике мы изучим различные варианты решения проблемы потери значения . Например, такие как .
Параметры по умолчанию
Можно указывать параметры по умолчанию через равенство , например:
Параметр по умолчанию используется при отсутствующем аргументе или равном , например:
При передаче любого значения, кроме , включая пустую строку, ноль или , параметр считается переданным, и значение по умолчанию не используется.
Параметры по умолчанию могут быть не только значениями, но и выражениями.
Например:
Заметим, что значение выражения будет вычислено, и соответствующие функции вызваны – лишь в том случае, если это необходимо, то есть когда функция вызвана без параметра.
В частности, выражение по умолчанию не вычисляется при объявлении функции. В примере выше функция будет вызвана именно в последней строке, так как не передан параметр.
Свойства функции
Функция в JavaScript является объектом, поэтому можно присваивать свойства прямо к ней, вот так:
Свойства функции не стоит путать с переменными и параметрами. Они совершенно никак не связаны. Переменные доступны только внутри функции, они создаются в процессе её выполнения. Это – использование функции «как функции».
А свойство у функции – доступно отовсюду и всегда. Это – использование функции «как объекта».
Если хочется привязать значение к функции, то можно им воспользоваться вместо внешних переменных.
В качестве демонстрации, перепишем пример со счётчиком:
При запуске пример работает также.
Принципиальная разница – во внутренней механике и в том, что свойство функции, в отличие от переменной из замыкания – общедоступно, к нему имеет доступ любой, у кого есть объект функции.
Например, можно взять и поменять счётчик из внешнего кода:
Статические переменные
Иногда свойства, привязанные к функции, называют «статическими переменными».
В некоторых языках программирования можно объявлять переменную, которая сохраняет значение между вызовами функции. В JavaScript ближайший аналог – такое вот свойство функции.
Объявление и вызов функции
Операции с функцией в JavaScript можно разделить на 2 шага:
- объявление (создание) функции;
- вызов (выполнение) этой функции.
1. Объявление функции. Написание функции посредством Function Declaration начинается с написания ключевого слова . После этого указывается имя функции, круглые скобки в которых при необходимости перечисляются через запятую параметры и код функции, заключённый в фигурные скобки.
function имя (параметры) { // код функции }
Например:
// объявление функции someName function someName() { alert('Вы вызвали функцию someName!'); } // function - ключевое слово, которое означает что мы хотим создать функцию // someName - имя функции // () - круглые скобки внутри которых при необходимости мы можем поместить параметры через запятую // { ... } - код или тело функции
При составлении имени функции необходимо руководствоваться теме же правилами, что и при создании имени переменной. Т.е. оно может содержать буквы, цифры (0-9), знаки «$» и «_». В качестве букв рекомендуется использовать только буквы английского алфавита (a-z, A-Z). Имя функции, также как и имя переменной не может начинаться с цифры.
Параметров у функции может быть сколько угодно много или не быть вообще. Круглые скобки в любом случае указываются. Если параметров несколько, то их между собой необходимо разделить посредством запятой. Они позволяют более удобно (по имени) получить переданные аргументы функции при её вызове.
Код функции — это набор инструкций, заключенный в фигурные скобки, которые необходимо выполнить при её вызове. Код функции называют ещё её телом.
2. Вызов функции. Объявленная функция сама по себе не выполняется. Для того чтобы функцию запустить, её необходимо вызвать. Вызов функции осуществляется посредством указания её имени и двух круглых скобок. Внутри скобок при необходимости ей можно передать аргументы (дополнительные данные) отделяя их друг от друга с помощью запятой.
// выполнение функции, приведённой в предыдущем примере (без передачи ей аргументов) someName();
Событие onclick javaScript и три способа обработки событий
Событие происходит во время одинарного щелчка кнопкой мыши. Обычно для события назначается обработчик, то есть функция, которая сработает, как только событие произошло. Обработать событие, т.е. отреагировать на него посредством скрипта, можно тремя способами. Рассмотрим их:
Пример: По щелчку на кнопке вывести диалоговое окно с сообщением «Ура!»
- Через свойство объекта с использованием пользовательской функции:
Скрипт:
function message() { alert("Ура!"); } |
html-код:
<body> <form> <input type="button" name= "myButton" onclick="message()" value="Щелкни!"> <form> |
В данном примере в html-коде мы видим кнопку. У кнопки присутствует атрибут («по щелчку»), в значении которого стоит вызов функции с названием . Это пользовательская функция, описанная выше в скрипте. В самой функции выводится диалоговое окно, что и задано согласно заданию.
Скрипт при такой обработке события обычно находится в области документа
Через атрибут тега:
<body> <form name="myForm"> <input type="button" name="myButton" value="Щелкни!" onclick="javascript: alert('Ура!')"> <form> |
Это упрощенный вариант обработки события, он подходит только для небольшого кода, когда необходимо выполнить один-два оператора. Иначе код будет плохочитаемым.
В качестве атрибута кнопки указывается («по щелчку»), а в качестве значения пишется скрипт из операторов с указанием на каком языке он написан (). В нашем случае оператор для вывода модального окна со словом «Ура!»
Через регистрацию функции-обработчика в качестве свойства элемента:
html-код:
<form name="myForm"> <input type="button" value="Щелкни!" id="myButton"> <form> |
Скрипт:
document.myForm.myButton.onclick = message; function message() { alert('Ура!'); } |
В html-коде здесь присутствует кнопка с атрибутом , который необходим для обращения к кнопке через скрипт.
В скрипте, который обязательно находится ниже дерева элементов (можно перед закрытием тега ), находится обращение к кнопке (), для которой назначается обработчик события со значением ссылки на функцию. Обращение к кнопке может быть организовано через атрибут ()
Скобки после названия функции не ставятся. В данном случае это именно ссылка на функцию, иначе, при использовании скобок, функция была бы вызвана, а не назначена в качестве обработчика событий.
Именно такой способ обработки событий максимально приближен к тому, который происходит, например, в ОС windows.
Как лучше выводить результаты примеров?
Важно: При вызове после окончания загрузки страницы (при обработке событий onclick, oninput, …), страница перезапишется, поэтому вызывать этот метод не рекомендуется. Для примеров лучше использовать метод .
добавляет html во время построения DOM
блокируют выполнение JS, пока пользователь не нажмёт OK
Рассмотрим все простые способы вывода отладочной информации:
-
alert('str'); // показывает окошко
-
document.write('htmlstr'); // пишет на страницу
-
document.innerHTML += 'htmlstr'; // добавляет на страницу
-
console.log('str'); // выводит в консоль браузерах
Задание Js8_5. Выполните задание по инструкции:
- Создайте веб-страницу и расположите в ней тег с изображением грустного смайлика.
- Щелчок на изображении () вызывает заданный метод (пользовательская функция):
<img id="smileImg" src="smile1.jpg" onclick="sayHello()" > |
В скрипте опишите метод (функция ), который «спрашивает», как зовут пользователя, а затем приветствует его по имени, и меняет изображение на улыбающийся смайлик (свойство тега ):
function sayHello() { var userName=prompt("Как вас зовут?"); if(userName){ alert(...); document.getElementById("smileImg"). ...=...; } } |
=>>
«Поднятие» переменных и функций
Интерпретатор JavaScript всегда перемещает («поднимает») объявления функций и переменных в начало области видимости. Если переменная определена внутри функции, она поднимается к верхней части функции, а если переменная определена глобально — к верхней части глобального контекста. Рассмотрим, что это значит на примере:
Объявление переменной поднимается вверх без присваивания, перекрывая одноименную глобальную переменную, поэтому в первом случае значение переменной – .
В случае с функциями, поднимается вся функция целиком, если речь идет о функциях-объявлениях (declaration); функция-выражение (expression) не поднимается:
В этом этом примере поднимается только функция . Идентификатор «anomFunc» (переменная, которой присвоена функция) также поднимается, но сама анонимная функция при этом остаётся на месте (как и в случае с пременной).
Параметры функции
Функции можно запускать с любым числом параметров.
Если функции передано меньше параметров, чем есть в определении, то отсутствующие считаются .
Следующая функция возвращает время , необходимое на преодоление дистанции с равномерной скоростью .
При первом запуске функция работает с аргументами , . Обычно такая ситуация, если она поддерживается функцией, предусматривает значение по умолчанию:
// если speed - ложное значение(undefined, 0, false...) - подставить 10 speed = speed || 10
Оператор в яваскрипт возвращает не , а само значение (первое, которое приводится к ).
Поэтому его используют для задания значений по умолчанию. В нашем вызове будет вычислено как .
Поэтому результат будет .
Второй запуск — стандартный.
Третий запуск задает несколько дополнительных аргументов. В функции не предусмотрена работа с дополнительными аргументами, поэтому они просто игнорируются.
Ну и в последнем случае аргументов вообще нет, поэтому , и имеем результат деления (Not-A-Number, произошла ошибка).
Непосредственно перед входом в тело функции, автоматически создается объект , который содержит
- Аргументы вызова, начиная от нуля
- Длину в свойстве
- Ссылку на саму функцию в свойстве
Например,
function func() { for(var i=0;i<arguments.length;i++) { alert("arguments = "+arguments) } } func('a','b',true) // выведет // arguments = a // arguments = b // arguments = true
Свойство похоже на массив, т.к у него есть длина и числовые индексы. На самом деле не принадлежит классу и не содержит его методов, таких как , и других.
Если все же хочется воспользоваться этими методами, например, чтобы вызвать другую функцию с теми же аргументами, но кроме первого, можно создать из настоящий массив:
var args = Array.prototype.slice.call(arguments) // .. теперь args - настоящий массив аргументов .. args.shift() ...
Вызвать функцию для массива аргументов можно при помощи :
var func = function(a,b) { alert(a+b) } var arr = func.apply(null, arr) // => alert(3)
Вызов функции как функции
Пример
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, но это не очень хорошая практика.
Глобальные переменные, методы или функции могут легко создавать конфликты имен и ошибки в глобальном объекте.
Примеры методов
Для начала давайте научим нашего пользователя здороваться:
Здесь мы просто использовали Function Expression (функциональное выражение), чтобы создать функцию для приветствия, и присвоили её свойству нашего объекта.
Затем мы вызвали её. Теперь пользователь может говорить!
Функцию, которая является свойством объекта, называют методом этого объекта.
Итак, мы получили метод объекта .
Конечно, мы могли бы заранее объявить функцию и использовать её в качестве метода, примерно так:
Объектно-ориентированное программирование
Когда мы пишем наш код, используя объекты для представления сущностей реального мира, – это называется объектно-ориентированное программирование или сокращённо: «ООП».
ООП является большой предметной областью и интересной наукой само по себе. Как выбрать правильные сущности? Как организовать взаимодействие между ними? Это – создание архитектуры, и есть хорошие книги по этой теме, такие как «Приёмы объектно-ориентированного проектирования. Паттерны проектирования» авторов Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес или «Объектно-ориентированный анализ и проектирование с примерами приложений» Гради Буча, а также ещё множество других книг.
Существует более короткий синтаксис для методов в литерале объекта:
Как было показано, мы можем пропустить ключевое слово и просто написать .
Нужно отметить, что эти две записи не полностью эквивалентны
Есть тонкие различия, связанные с наследованием объектов (что будет рассмотрено позже), но на данном этапе изучения это неважно. В большинстве случаев сокращённый синтаксис предпочтителен
Функции-генераторы в «ES6»
Еще одно новое определение функции из стандарта «ES6» — функция-генератор. Она способна остановить и продолжить выполнение.
function *function_name(){}
Функция-генератор создаёт итератор (повторитель). Метод итератора «next» используется для выполнения кода внутри функции-генератора до тех пор, пока не будет достигнуто ключевое слово «yield». Затем значение после слова «yield» возвращается и выполнение приостанавливается.
Если ключевое слово «yield» не достигается, то происходит возврат значения «undefined» и выполнение итератора дальше не происходит.
function *randomIncrement(i) { yield i + 3; yield i + 5; yield i + 10; yield i + 6; } var itr = randomIncrement(4); console.log(itr.next().value); //7 console.log(itr.next().value); //9 console.log(itr.next().value); //14
Функции-генераторы полезны если требуется перебрать значения один за другим в разных точках кода, приостанавливая перебор.
Выбор имени function
При выборе имён в function применяют те же правила, что и когда выбирают имена переменной. Однако следует помнить, что именем должен быть глагол, ведь функция — это действие. Как правило, в качестве имени используют глагольные префиксы, плюс уточнения.
Функцию, которая что-то показывает, называют show (это лучший вариант для имени):
showMessage(..) // "показать" сообщение
Запуск function, которая что-то получает, называют get, вычисляет — calc и т. д.
Примеры, каким именем можно назвать функцию:
getAge(..) // get, "получает" возраст calcD(..) // calc, "вычисляет" дискриминант createForm(..) // create, "создаёт" форму checkPermission(..) // check, "проверяет" разрешение, возвращает true/false
Использование данного метода названия — удобная штука, ведь, взглянув на функцию, мы примерно поймём, что она делает, какое значение возвращает. И даже если эту функцию написал кто-то другой, вы будете иметь представление о ней.
Остаётся запомнить, что вне зависимости от метода названия, одна функция — это одно действие. Если функция подразумевает поддействия, желательно выделить их в отдельные функции.
Объект arguments
В JavaScript можно создавать функции с произвольным числом аргументов. Доступ ко всем указанным при вызове функции аргументам, в том числе к лишним аргументам, которым не были назначены параметры, осуществляется через объект arguments, который доступен только внутри тела функции.
Свойство этого объекта содержит число переданных аргументов.
Напишем функцию, вычисляющую сумму произвольного числа аргументов:
Выполнить код »
Скрыть результаты
Объект является массивоподобным объектом, который позволяет передать функции значения аргументов, извлекаемые не по имени, а по номеру.
Поскольку он похож на массив, обратиться к переданным функции аргументам можно так же, как и к элементам массива: первый аргумент будет доступен в теле функции как элемент массива arguments,
второй аргумент
arguments
Функция, приводимая в следующем примере, возвращает строку, содержащую значения параметров (переданные аргументы) и их общее количество, которые были указаны в вызове функции (не в ее определении):
Выполнить код »
Скрыть результаты
JS Tutorial
JS HOMEJS IntroductionJS Where ToJS OutputJS StatementsJS SyntaxJS CommentsJS VariablesJS LetJS ConstJS OperatorsJS ArithmeticJS AssignmentJS Data TypesJS FunctionsJS ObjectsJS EventsJS StringsJS String MethodsJS NumbersJS Number MethodsJS ArraysJS Array MethodsJS Array SortJS Array IterationJS DatesJS Date FormatsJS Date Get MethodsJS Date Set MethodsJS MathJS RandomJS BooleansJS ComparisonsJS ConditionsJS SwitchJS Loop ForJS Loop For InJS Loop For OfJS Loop WhileJS BreakJS Type ConversionJS BitwiseJS RegExpJS ErrorsJS ScopeJS HoistingJS Strict ModeJS this KeywordJS Arrow FunctionJS ClassesJS JSONJS DebuggingJS Style GuideJS Best PracticesJS MistakesJS PerformanceJS Reserved Words
Проблема «несуществующего свойства»
Если вы только начали читать учебник и изучать JavaScript, то, возможно, эта проблема вам пока незнакома, но она достаточно распространена.
Например, рассмотрим объекты для пользователей . У большинства пользователей есть адрес с улицей , но некоторые адрес не указали.
В этом случае при попытке получить свойство будет ошибка:
Это нормальный результат, так работает JavaScript, но во многих реальных ситуациях удобнее было бы получать не ошибку, а просто («нет улицы»).
Или ещё пример. В веб-разработке нам бывает нужно получить данные об HTML-элементе, который иногда может отсутствовать на странице:
До появления в языке для решения подобных проблем использовался оператор .
Например:
Использование логического И со всей цепочкой свойств гарантирует, что все они существуют (а если нет – вычисление прекращается), но это довольно длинная и громоздкая конструкция.
В интернете кто-то не прав
Все началось с простого вопроса в канале Telegram для изучающих JavaScript, в котором, помимо всего прочего, появился вопрос касательно обработчиков событий в браузере. Вопрос был в том, как они «навешиваются» и «снимаются» с DOM-элемента. Среди ответов от вполне опытного разработчика был следующий:
Далее ответ был подкреплен блоком кода похожим на этот:
element.addEventListener('click', function() { /* .. */ })element.removeEventListener('click', function() { /* .. */ })
На что в качестве возражения с моей стороны был приведен следующий блок кода, показывающий, что анонимная функция может быть удалена как обработчик:
const handleClick = () => { /* */ }element.addEventListener('click', handleClick)element.removeEventListener('click', handleClick)
Итого
Объявление функции имеет вид:
- Передаваемые значения копируются в параметры функции и становятся локальными переменными.
- Функции имеют доступ к внешним переменным. Но это работает только изнутри наружу. Код вне функции не имеет доступа к её локальным переменным.
- Функция может возвращать значение. Если этого не происходит, тогда результат равен .
Для того, чтобы сделать код более чистым и понятным, рекомендуется использовать локальные переменные и параметры функций, не пользоваться внешними переменными.
Функция, которая получает параметры, работает с ними и затем возвращает результат, гораздо понятнее функции, вызываемой без параметров, но изменяющей внешние переменные, что чревато побочными эффектами.
Именование функций:
- Имя функции должно понятно и чётко отражать, что она делает. Увидев её вызов в коде, вы должны тут же понимать, что она делает, и что возвращает.
- Функция – это действие, поэтому её имя обычно является глаголом.
- Есть много общепринятых префиксов, таких как: , , , и т.д. Пользуйтесь ими как подсказками, поясняющими, что делает функция.
Функции являются основными строительными блоками скриптов. Мы рассмотрели лишь основы функций в JavaScript, но уже сейчас можем создавать и использовать их. Это только начало пути. Мы будем неоднократно возвращаться к функциям и изучать их всё более и более глубоко.
Итого
Основные улучшения в функциях:
- Можно задавать параметры по умолчанию, а также использовать деструктуризацию для чтения приходящего объекта.
- Оператор spread (троеточие) в объявлении позволяет функции получать оставшиеся аргументы в массив: .
- Тот же оператор spread в вызове функции позволяет передать в неё массив как список аргументов (вместо ).
- У функции есть свойство , оно содержит имя, указанное при объявлении функции, либо, если его нет, то имя свойства или переменную, в которую она записана. Есть и некоторые другие ситуации, в которых интерпретатор подставляет «самое подходящее» имя.
- Объявление Function Declaration в блоке видно только в этом блоке.
- Появились функции-стрелки:
- Без фигурных скобок возвращают выражение : .
- С фигурными скобками требуют явного .
- Не имеют своих и , при обращении получают их из окружающего контекста.
- Не могут быть использованы как конструкторы, с .