Function
Содержание:
- Область видимости переменных. Javascript глобальные и локальные переменные в функции
- Function Expressions
- Пользовательские Javascript функции
- Свойство «length»
- Naming a function
- Сборка мусора
- Объявление и вызов функции
- Параметры и аргументы
- Объявление и вызов функции
- new Function
- Оператор spread вместо arguments
- Рекурсивная функция javascript
- Примеры методов
- Default values
- Итого: замыкания
Область видимости переменных. Javascript глобальные и локальные переменные в функции
Область видимости переменной — область кода, в котором переменная доступна для использования.
- Глобальные переменные — создаются на уровне сценария и сохраняются до конца сценария;— объявляются до описания javascript функции:
var a = 1; function ... ... |
— могут быть причиной сложно находимых ошибок;
Локальные переменные
— создаются внутри фрагментов кода и не видны извне;
for (var i=1;i<5;i++){ // i - локальная ... } if (x<5) { var a=5; // a - локальная } |
— явно объявляются в теле javascript функции;
function findA(){ var a = 2*2 // a - локальная } |
— аргументы (параметры) функции — всегда локальные переменные;
— лучше использовать локальные переменные, так как доступ к ним больше контролируется.
Задание js4_9. Дополните код согласно заданию:
Создать 2 переменные глобальной и локальной области видимости (то есть внутри функции ) с именами: , .
Переменной присвоить текст “Привет, ”, а — “Мир”. Используя переменные, выведите их значения дважды: в основной программе и в теле функции.
function func() { } func(); |
Область видимости переменных
Рассмотрим конкретные примеры области видимости переменных в javascript при использовании глобальных и локальных переменных.
-
1 2 3 4 5 6 7 8
var S = 2; // Глобальная переменная S function plRectangle(width, height){ var S = width * height; return S // Локальная переменная S } z = plRectangle(2, 3); alert(z); alert(S);
Пример: Значение равно 6, а значение осталось равным 2, то есть значению глобальной переменной, определенной во внешней программе
-
1 2 3 4 5 6 7 8 9 10 11
function plRectangle(width, height) { var s = width * height; // аргументы всегда локальны width = width + 10; return s } width = 2; height = 3; z = plRectangle(width, height); alert(z); alert(width);
Пример: Значение равно 6; значение переменной равно 2, то есть осталось без изменений
-
1 2 3 4 5 6 7 8 9 10
var S = 2; // Глобальная переменная S function plRectangle(width, height) { S = width * height; // заменяем глобальную переменную: return S // S - глобальная переменная (т.к. без определения var) } var z = plRectangle(2, 3); alert(z); alert(S);
Пример: Значения и и равны 6; — глобальная переменная
-
1 2 3 4 5 6 7 8
function Plrectangle(width, height){ S = width * height; //глобальная переменная return S } z = Plrectangle(2, 3); S=2; // изменяем глобальную переменную alert(z); alert (S);
Пример: Значение равно 6, а значение равно 2, то есть значению измененной глобальной переменной, определенной во внешней программе
-
1 2 3 4 5 6 7 8 9 10
function plRectangle(width, height) { var S = width * height; var x = 17; return S } z = plRectangle(2,3); alert(z); alert(x); // не определена во внешней программе alert (S); // не определена во внешней программе
Пример: Значение равно 6; переменная во внешней программе не определена; переменная во внешней программе не определена
Задание js4_10. Что выведет на экран следующий код?
1 2 3 4 5 6 7 |
var variable = "Глобальная переменная"; function f() { var variable = "Локальная переменная"; document.write(variable + "<br/>"); } f(); document.write(variable); |
Вопросы для самоконтроля:
- Какова разница между локальными и глобальными переменными?
- Зачем в программировании существует необходимость деления переменных на локальные и глобальные?
Function Expressions
A JavaScript function can also be defined using an expression.
A function expression can be stored in a variable:
Example
var x = function (a, b) {return a * b};
After a function expression has been stored in a variable, the variable can
be used as a function:
Example
var x = function (a, b) {return a * b};
var z = x(4, 3);
The function above is actually an anonymous function (a function without a
name).
Functions stored in variables do not need function names. They are always
invoked (called) using the variable name.
The function above ends with a semicolon because it is a part of an executable statement.
Пользовательские Javascript функции
Пользовательские функции прежде всего необходимы в ситуации, когда в разных частях программы необходимо выполнять одни и те же действия несколько раз. В таком случае повторяемые операторы оформляются в виде функции, к которой можно обращаться и вызывать ее выполнение из разных частей программы.
В javascript предусмотрены два варианта функций: функции, которые при их вызове выполняют какие-то действия (например, выводят сообщение), и функции, которые возвращают значение (число, строку, …).
Функция в роли процедуры
Если функция выполняет какие-либо действия и не возвращает значение:Важно: Если аргументы у функции отсутствуют, то после имени функции ставятся пустые скобки :
function имя_функции(){ код; }
Вызов функции:
Пример: Создать функцию для вывода модального окна со словом hello. Осуществить вызов функции.
Решение:
Создайте код и протестируйте его в браузере:
function sayHello() { alert("hello"); } sayHello(); |
Если функция возвращает значение:
Важно: В javascript — директива, которая завершает выполнение функции и возвращает значение
Вызов функции:
Пример: Рассмотрите фрагмент кода и поясните, что выполняется в данном скрипте:
1 2 3 4 5 6 7 8 |
function sayHello() { alert("1"); return "привет!"; alert("2"); } var a=sayHello(); alert(a); |
Решение:
- Рассмотрите работу функции:
1 2 3 4 5 6 |
function sayHello() { alert("1");// выполнится return "привет!";// завершаем выполнение функции alert("2");// не выполнится, т.к. после return } |
Как видно из примера, после функция действительно завершает свою работу. Поэтому оператор выполняться уже не будет.
Проанализируйте вызов функции:
var a=sayHello(); alert(a); |
Вызов функции происходит через присваивание
Вызов в данном примере можно также организовать так: , но это не рекомендуемый вариант.
Важно: Таким образом, директива указывает на возвращаемое значение функции, которое будет передано переменной при следующей форме вызова:
переменная = имя_функции();
Важно: может использоваться без значения, чтобы прекратить выполнение функции и выйти из нее:
1 2 3 4 5 |
function checkName() { var name=prompt('введите имя') if (!name) { return; // если имя не заполнено, то выходим из функции } |
Задание js4_2. Дополните код согласно заданию: В переменную povtor присвоить результат выполнения функции , которая выводит фразу «Пройти заполнение еще раз?» и принимает ответ пользователя (ок или отмена).
Фрагмент кода:
1 2 3 4 5 6 7 |
function say() { document.write("Вы здесь?" + "<br/>"); } do { say(); povtor = ... } while (povtor); |
Задание js4_3. Создать функцию без параметров, которая вычисляет разность двух вводимых пользователем в диалоговые окна числа. Выполнить задание двумя способами: 1) функция выводит сообщение с результатом; 2) в функции выполняется разность, а сообщение с результатом выводится в основной программе.
Примерный фрагмент кода для одного из способов:
1 2 3 4 5 6 |
function raznost() { var a = ... var b = ... ... } ... |
Вопросы для самоконтроля:
- Для чего используются функции?
- Объясните в чем разница использования функции в роли процедуры и функции с классическим оформлением?
- Опишите синтаксис вызова функции в роли процедуры.
- Опишите синтаксис вызова функции с классическим оформлением.
- Для чего служит директива ?
Свойство «length»
Ещё одно встроенное свойство «length» содержит количество параметров функции в её объявлении. Например:
Как мы видим, троеточие, обозначающее «остаточные параметры», здесь как бы «не считается»
Свойство иногда используется для интроспекций в функциях, которые работают с другими функциями.
Например, в коде ниже функция принимает в качестве параметров вопрос и произвольное количество функций-обработчиков ответа .
Когда пользователь отвечает на вопрос, функция вызывает обработчики. Мы можем передать два типа обработчиков:
- Функцию без аргументов, которая будет вызываться только в случае положительного ответа.
- Функцию с аргументами, которая будет вызываться в обоих случаях и возвращать ответ.
Чтобы вызвать обработчик правильно, будем проверять свойство .
Идея состоит в том, чтобы иметь простой синтаксис обработчика без аргументов для положительных ответов (наиболее распространённый случай), но также и возможность передавать универсальные обработчики:
Это частный случай так называемого – обработка аргументов в зависимости от их типа или, как в нашем случае – от значения . Эта идея имеет применение в библиотеках JavaScript.
Naming a function
Functions are actions. So their name is usually a verb. It should be brief, as accurate as possible and describe what the function does, so that someone reading the code gets an indication of what the function does.
It is a widespread practice to start a function with a verbal prefix which vaguely describes the action. There must be an agreement within the team on the meaning of the prefixes.
For instance, functions that start with usually show something.
Function starting with…
- – return a value,
- – calculate something,
- – create something,
- – check something and return a boolean, etc.
Examples of such names:
With prefixes in place, a glance at a function name gives an understanding what kind of work it does and what kind of value it returns.
One function – one action
A function should do exactly what is suggested by its name, no more.
Two independent actions usually deserve two functions, even if they are usually called together (in that case we can make a 3rd function that calls those two).
A few examples of breaking this rule:
- – would be bad if it shows an with the age (should only get).
- – would be bad if it modifies the document, adding a form to it (should only create it and return).
- – would be bad if it displays the message (should only perform the check and return the result).
These examples assume common meanings of prefixes. You and your team are free to agree on other meanings, but usually they’re not much different. In any case, you should have a firm understanding of what a prefix means, what a prefixed function can and cannot do. All same-prefixed functions should obey the rules. And the team should share the knowledge.
Ultrashort function names
Functions that are used very often sometimes have ultrashort names.
For example, the jQuery framework defines a function with . The Lodash library has its core function named .
These are exceptions. Generally function names should be concise and descriptive.
Сборка мусора
Обычно лексическое окружение очищается и удаляется после того, как функция выполнилась. Например:
Здесь два значения, которые технически являются свойствами лексического окружения. Но после того, как завершится, это лексическое окружение станет недоступно, поэтому оно удалится из памяти.
…Но, если есть вложенная функция, которая всё ещё доступна после выполнения , то у неё есть свойство , которое ссылается на внешнее лексическое окружение, тем самым оставляя его достижимым, «живым»:
Обратите внимание, если вызывается несколько раз и возвращаемые функции сохраняются, тогда все соответствующие объекты лексического окружения продолжат держаться в памяти. Вот три такие функции в коде ниже:. Объект лексического окружения умирает, когда становится недоступным (как и любой другой объект)
Другими словами, он существует только до того момента, пока есть хотя бы одна вложенная функция, которая ссылается на него
Объект лексического окружения умирает, когда становится недоступным (как и любой другой объект). Другими словами, он существует только до того момента, пока есть хотя бы одна вложенная функция, которая ссылается на него.
В следующем коде, после того как станет недоступным, лексическое окружение функции (и, соответственно, ) будет удалено из памяти;
Как мы видели, в теории, пока функция жива, все внешние переменные тоже сохраняются.
Но на практике движки JavaScript пытаются это оптимизировать. Они анализируют использование переменных и, если легко по коду понять, что внешняя переменная не используется – она удаляется.
Одним из важных побочных эффектов в V8 (Chrome, Opera) является то, что такая переменная становится недоступной при отладке.
Попробуйте запустить следующий пример в Chrome с открытой Developer Tools.
Когда код будет поставлен на паузу, напишите в консоли .
Как вы можете видеть – такой переменной не существует! В теории, она должна быть доступна, но попала под оптимизацию движка.
Это может приводить к забавным (если удаётся решить быстро) проблемам при отладке. Одна из них – мы можем увидеть не ту внешнюю переменную при совпадающих названиях:
До встречи!
Эту особенность V8 полезно знать. Если вы занимаетесь отладкой в Chrome/Opera, рано или поздно вы с ней встретитесь.
Это не баг в отладчике, а скорее особенность V8. Возможно со временем это изменится.
Вы всегда можете проверить это, запустив пример на этой странице.
Объявление и вызов функции
Операции с функцией в JavaScript можно разделить на 2 шага:
- объявление (создание) функции;
- вызов (выполнение) этой функции.
1. Объявление функции. Написание функции посредством Function Declaration начинается с написания ключевого слова . После этого указывается имя функции, круглые скобки в которых при необходимости перечисляются через запятую параметры и код функции, заключённый в фигурные скобки.
function имя (параметры) { // код функции }
Например:
// объявление функции someName function someName() { alert('Вы вызвали функцию someName!'); } // function - ключевое слово, которое означает что мы хотим создать функцию // someName - имя функции // () - круглые скобки внутри которых при необходимости мы можем поместить параметры через запятую // { ... } - код или тело функции
При составлении имени функции необходимо руководствоваться теме же правилами, что и при создании имени переменной. Т.е. оно может содержать буквы, цифры (0-9), знаки «$» и «_». В качестве букв рекомендуется использовать только буквы английского алфавита (a-z, A-Z). Имя функции, также как и имя переменной не может начинаться с цифры.
Параметров у функции может быть сколько угодно много или не быть вообще. Круглые скобки в любом случае указываются. Если параметров несколько, то их между собой необходимо разделить посредством запятой. Они позволяют более удобно (по имени) получить переданные аргументы функции при её вызове.
Код функции — это набор инструкций, заключенный в фигурные скобки, которые необходимо выполнить при её вызове. Код функции называют ещё её телом.
2. Вызов функции. Объявленная функция сама по себе не выполняется. Для того чтобы функцию запустить, её необходимо вызвать. Вызов функции осуществляется посредством указания её имени и двух круглых скобок. Внутри скобок при необходимости ей можно передать аргументы (дополнительные данные) отделяя их друг от друга с помощью запятой.
// выполнение функции, приведённой в предыдущем примере (без передачи ей аргументов) someName();
Параметры и аргументы
Параметр функции – это переменная в функции, которая будет содержать передаваемое снаружи входное значение. Параметры функции перечислены внутри круглых скобок в определении функции.
Для определения параметров функции используется следующий синтаксис:
Параметры следует рассматривать как объявления локальных переменных в теле функции, каждая из которых инициализируются в момент вызова функции соответствующим значением из списка аргументов (или значением по умолчанию).
Аргументы функции — это значения, которые вы предоставляете функции в момент её вызова.
Для вызова функции с передачей ей аргументов используется следующий синтаксис:
Например, при вызове функции sum ей передаются два аргумента:
Выполнить код »
Скрыть результаты
Аргументы, передаваемые функции при её вызове, присваиваются параметрам функции в том порядке, в каком они указаны: первый аргумент присваивается первому параметру, второй аргумент – второму параметру и т. д.
Важной особенностью функций в JavaScript является то, что функция может вызываться с произвольным количеством аргументов вне зависимости от того, сколько параметров было указано при её объявлении:
- Если при вызове функции ей передаётся больше аргументов, чем задано параметров, то «лишние» аргументы просто игнорируются и не присваиваются ни одному из параметров данной функции.
- Если количество аргументов, передаваемых функции при её вызове меньше, чем было указано параметров при объявлении, то параметрам без соответствующих аргументов присваивается значение . Подобное поведение JavaScript удобно использовать, если некоторые аргументы функции необязательны и могут опускаться.
Типы аргументов, передаваемых функции при её вызове, могут быть как примитивами (строки, числа, логические величины (boolean)), так и объектами (в т.ч. массивы и функции).
Важно помнить, что при передаче функции аргументов, представляющих собой примитивные значения, в теле функции создается копия переданного значения и оригинал не изменяется. Иными словами, если аргумент будет изменён внутри функции, после ее завершения эта локальная переменная уничтожается, а оригинальная переменная остается прежней
Выполнить код »
Скрыть результаты
Выполнить код »
Скрыть результаты
В этом примере мы видим, что внутри функции был изменен объект , и эти изменения повлияли на этот объект за пределами функции.
Объявление и вызов функции
Функция (как и всякий объект) должна быть объявлена (определена) перед её использованием.
Функция JavaScript определяется с помощью ключевого слова , за которым указываются следующие компоненты:
- Идентификатор, определяющий имя функции. Чаще всего в качестве имен функций выбираются глаголы или фразы, начинающиеся с глаголов. По общепринятому соглашению имена функций начинаются со строчной буквы.
- Пара круглых скобок , которые могут включать имена параметров, разделенных запятыми ( параметр1, параметр2, … ). Эти имена параметров в теле функции могут использоваться как локальные переменные.
- Пара фигурных скобок с инструкциями JavaScript внутри. Эти инструкции составляют тело функции: они выполняются при каждом вызове функции.
Синтаксис функции JavaScript:
Программный код, расположенный в теле функции, выполняется не в момент объявления функции, а в момент её вызова. Будучи один раз определенной, функция может сколько угодно раз вызываться с помощью оператора (вызов функции):
Выполнить код »
Скрыть результаты
Этот код выведет нам приветствие в диалоговом окне два раза. Применение функции позволило нам избавиться от дублирования кода.
Обратите внимание, что несмотря на отсутствие параметров, в объявлении функции все равно нужно ставить скобки после имени. При вызове, после имени функции, также указываются пустые скобки
Интерпретатор JavaScript, встречая ключевое слово , создаёт функцию и переменную с именем этой функции. Переменной присваивается ссылка на функцию.
Обратившись к переменной с именем созданной функции можно увидеть, что в качестве значения там находится функция (а точнее ссылка на неё):
Ссылку на функцию вы можете сохранить в любой переменной, например:
«Классическое» объявление функции называется в спецификации языка «Function Declaration».
Существует альтернативный синтаксис для объявления функции «Function Expression» (функциональное выражение) – это объявление функции, которое является частью какого-либо выражения (например присваивания):
Как видите, эта конструкция уже не выглядит стандартной: функция не имеет имени и находится в правой части команды присваивания переменной . Эту функцию тоже можно вызвать – на этот раз через переменную .
Если у функции нет имени, как в предыдущем примере, она называется «анонимной».
Разница между представленными объявлениями заключается в том, что функции, объявленные как «Function Declaration», создаются интерпретатором до начала выполнения кода (на этапе анализа), поэтому их можно вызвать до объявления:
Функции «Function Expression» (функциональные выражения) создаются в процессе выполнения выражения, в следующем примере функция будет создана при операции присваивания , поэтому вызов функции до её объявления приведёт к ошибке:
new Function
Существует ещё один способ создания функции, который используется очень редко, но упомянем и его для полноты картины.
Он позволяет создавать функцию полностью «на лету» из строки, вот так:
То есть, функция создаётся вызовом :
- Параметры функции через запятую в виде строки.
- Код функции в виде строки.
Таким образом можно конструировать функцию, код которой неизвестен на момент написания программы, но строка с ним генерируется или подгружается динамически во время её выполнения.
Пример использования – динамическая компиляция шаблонов на JavaScript, мы встретимся с ней позже, при работе с интерфейсами.
Оператор spread вместо arguments
Чтобы получить массив аргументов, можно использовать оператор , например:
В попадёт массив всех аргументов, начиная с третьего.
Заметим, что – настоящий массив, с методами , и другими, в отличие от .
Оператор … должен быть в конце
Оператор собирает «все оставшиеся» аргументы, поэтому такое объявление не имеет смысла:
Параметр должен быть в конце функции.
Выше мы увидели использование для чтения параметров в объявлении функции. Но этот же оператор можно использовать и при вызове функции, для передачи массива параметров как списка, например:
Формально говоря, эти два вызова делают одно и то же:
Похоже, что первый – короче и красивее.
Рекурсивная функция javascript
Важно: В информатике и программировании, а, соответственно, и в javascript, рекурсия — это вызов функции из самой же функции, т.е. функция в функции. Бывают также косвенная или сложная рекурсия, когда функция вызывается не непосредственно из самой себя, а из вложенной в нее функции: например, функция вызывает функцию , а функция — функцию
Количество вложенных вызовов функции или процедуры называется глубиной рекурсии
Бывают также косвенная или сложная рекурсия, когда функция вызывается не непосредственно из самой себя, а из вложенной в нее функции: например, функция вызывает функцию , а функция — функцию . Количество вложенных вызовов функции или процедуры называется глубиной рекурсии.
Для организации рекурсии необходимо наличие нескольких условий:
- начальное условие (известное значение для переменной, отправной момент рекурсии);
- рекурсивное правило;
- условие окончания рекурсии.
Рекурсия javascript рассмотрена ниже на примере возведения числа в степень.Для начала рассмотрим итерационный вариант возведения в степень, т.е. с использованием :
Пример: Используя функцию, необходимо вычислять возведение числа в степень. Выполнить задание, используя цикл
Показать решение:
1 2 3 4 5 6 7 8 |
var chislo,stepen; function degree(chislo,stepen) { for(var result = 1; stepen > ; stepen--) { result *= chislo; } return result; } document.write(degree(2,4)); // выводит 16 |
Пример: Выполнить возведение числа в степень через рекурсию. Оба значения запрашивать у пользователя. Выдавать результат в виде:
2 в степени 4 = 16
Решение:
- Объявите глобальные переменные для числа и степени и запросите их:
var chislo,stepen; chislo = parseInt(prompt('число: ')); stepen = parseInt(prompt('степень: ')); |
Создайте функцию с двумя аргументами для числа и степени:
function degree(chislo,stepen) { } |
Поскольку известно, что любое число в степени 0 равно единице, то сделаем это начальным условием. То есть если степень = 0, то функция возвращает 1:
function degree(chislo,stepen) { if(stepen) { … } return 1; // если степень равна нулю то возвращаем 1 } |
Создадим рекуррентное правило: если степень не равна 0, то нужно число умножить на число в степени на единицу меньше (вызов функции со степенью на единицу меньше):
function degree(chislo,stepen) { if(stepen) { return chislo*degree(chislo,stepen-1); } return 1; } |
Вызовите функцию, оформив вывод:
document.write(chislo,' в степени ', stepen, ' = ', degree(chislo,stepen)); |
Протестируйте результат в браузере.
Задание js4_11. Что выведет на экран следующий код?
1 2 3 4 5 6 7 8 |
function f(counter) { counter--; document.write(counter + "<br/>"); if (counter != ) f(counter); document.write(counter + "<br/>"); } f(2); |
Задание js4_12. Вычислить факториал числа с использованием рекурсии, беря за образец пример
Пример: Вычисление факториала числа итерационным методом с использованием :
Показать решение:
1 2 3 4 5 6 7 8 9 10 11 |
var m = 2; x = factorial(m); document.write(x); function factorial(n){ if(n <= 1) return 1; rezult = 2; // result - переменная для результата for (i = 3; i <=n; i++) { rezult = rezult*i; } return result; } |
Вопросы для самоконтроля:
- Что такое рекурсия?
- Назовите основные условия организации рекурсии, как вы их понимаете?
Примеры методов
Для начала давайте научим нашего пользователя здороваться:
Здесь мы просто использовали Function Expression (функциональное выражение), чтобы создать функцию для приветствия, и присвоили её свойству нашего объекта.
Затем мы вызвали её. Теперь пользователь может говорить!
Функцию, которая является свойством объекта, называют методом этого объекта.
Итак, мы получили метод объекта .
Конечно, мы могли бы заранее объявить функцию и использовать её в качестве метода, примерно так:
Объектно-ориентированное программирование
Когда мы пишем наш код, используя объекты для представления сущностей реального мира, – это называется объектно-ориентированное программирование или сокращённо: «ООП».
ООП является большой предметной областью и интересной наукой само по себе. Как выбрать правильные сущности? Как организовать взаимодействие между ними? Это – создание архитектуры, и есть хорошие книги по этой теме, такие как «Приёмы объектно-ориентированного проектирования. Паттерны проектирования» авторов Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес или «Объектно-ориентированный анализ и проектирование с примерами приложений» Гради Буча, а также ещё множество других книг.
Существует более короткий синтаксис для методов в литерале объекта:
Как было показано, мы можем пропустить ключевое слово и просто написать .
Нужно отметить, что эти две записи не полностью эквивалентны
Есть тонкие различия, связанные с наследованием объектов (что будет рассмотрено позже), но на данном этапе изучения это неважно. В большинстве случаев сокращённый синтаксис предпочтителен
Default values
If a parameter is not provided, then its value becomes .
For instance, the aforementioned function can be called with a single argument:
That’s not an error. Such a call would output . There’s no , so it’s assumed that .
If we want to use a “default” in this case, then we can specify it after :
Now if the parameter is not passed, it will get the value
Here is a string, but it can be a more complex expression, which is only evaluated and assigned if the parameter is missing. So, this is also possible:
Evaluation of default parameters
In JavaScript, a default parameter is evaluated every time the function is called without the respective parameter.
In the example above, is called every time is called without the parameter.
Sometimes it makes sense to set default values for parameters not in the function declaration, but at a later stage, during its execution.
To check for an omitted parameter, we can compare it with :
…Or we could use the operator:
Modern JavaScript engines support the nullish coalescing operator , it’s better when falsy values, such as , are considered regular:
Итого: замыкания
Замыкание – это функция вместе со всеми внешними переменными, которые ей доступны.
Таково стандартное определение, которое есть в Wikipedia и большинстве серьёзных источников по программированию. То есть, замыкание – это функция + внешние переменные.
Тем не менее, в JavaScript есть небольшая терминологическая особенность.
Обычно, говоря «замыкание функции», подразумевают не саму эту функцию, а именно внешние переменные.
Иногда говорят «переменная берётся из замыкания». Это означает – из внешнего объекта переменных.
Что это такое – «понимать замыкания?»
Иногда говорят «Вася молодец, понимает замыкания!». Что это такое – «понимать замыкания», какой смысл обычно вкладывают в эти слова?
«Понимать замыкания» в JavaScript означает понимать следующие вещи:
- Все переменные и параметры функций являются свойствами объекта переменных . Каждый запуск функции создаёт новый такой объект. На верхнем уровне им является «глобальный объект», в браузере – .
- При создании функция получает системное свойство , которое ссылается на , в котором она была создана.
- При вызове функции, куда бы её ни передали в коде – она будет искать переменные сначала у себя, а затем во внешних с места своего «рождения».
В следующих главах мы углубим это понимание дополнительными примерами, а также рассмотрим, что происходит с памятью.