Замыкание

Вызов функций

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

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

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

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

Метод — это не что иное, как функция, которая хранится в виде свойства объекта. Если имеется функция func и объект obj, то можно определить метод объекта obj с именем method, как показано ниже:

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

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

Однако вызов метода имеет одно важное отличие: контекст вызова. Выражение обращения к свойству состоит из двух частей: объекта (в данном случае obj) и имени свойства (method)

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

Методы и ключевое слово this занимают центральное место в парадигме объектно-ориентированного программирования. Любая функция, используемая как метод, фактически получает неявный аргумент — объект, относительно которого она была вызвана. Как правило, методы выполняют некоторые действия с объектом, и синтаксис вызова метода наглядно отражает тот факт, что функция оперирует объектом.

Обратите внимание: this — это именно ключевое слово, а не имя переменной или свойства. Синтаксис JavaScript не допускает возможность присваивания значений элементу this

Остаточные параметры (…)

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

Например:

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

Остаточные параметры могут быть обозначены через три точки . Буквально это значит: «собери оставшиеся параметры и положи их в массив».

Например, соберём все аргументы в массив :

Мы можем положить первые несколько параметров в переменные, а остальные – собрать в массив.

В примере ниже первые два аргумента функции станут именем и фамилией, а третий и последующие превратятся в массив :

Остаточные параметры должны располагаться в конце

Остаточные параметры собирают все остальные аргументы, поэтому бессмысленно писать что-либо после них. Это вызовет ошибку:

должен всегда быть последним.

Событие onclick javaScript и три способа обработки событий

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

Пример: По щелчку на кнопке вывести диалоговое окно с сообщением «Ура!»

  1. Через свойство объекта с использованием пользовательской функции:

Скрипт:

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

Рассмотрим все простые способы вывода отладочной информации:

  1. alert('str'); // показывает окошко
  2. document.write('htmlstr'); // пишет на страницу
  3. document.innerHTML += 'htmlstr'; // добавляет на страницу
  4. console.log('str'); // выводит в консоль браузерах

Задание Js8_5. Выполните задание по инструкции:

  1. Создайте веб-страницу и расположите в ней тег с изображением грустного смайлика.
  2. Щелчок на изображении () вызывает заданный метод (пользовательская функция):
<img id="smileImg" src="smile1.jpg" onclick="sayHello()" >

В скрипте опишите метод (функция ), который «спрашивает», как зовут пользователя, а затем приветствует его по имени, и меняет изображение на улыбающийся смайлик (свойство тега ):

function sayHello() { 
	var userName=prompt("Как вас зовут?");
	if(userName){
		alert(...);
		document.getElementById("smileImg"). ...=...;
	}
}

 =>>

Замыкание

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

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

Сравним это с обычным объявлением:

Эта особенность выглядит странно, но оказывается очень полезной на практике.

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

Наша новая функция должна взаимодействовать с основным скриптом.

Что если бы она имела доступ к внешним переменным?

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

Например, если в функции объявляется переменная , то минификатор изменяет её на (или другую букву, если она не занята) и изменяет её везде. Обычно так делать безопасно, потому что переменная является локальной, и никто снаружи не имеет к ней доступ. И внутри функции минификатор заменяет каждое её упоминание. Минификаторы достаточно умные. Они не просто осуществляют «тупой» поиск-замену, они анализируют структуру кода, и поэтому ничего не ломается.

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

Если бы имела доступ к внешним переменным, при этом были бы проблемы с минификаторами.

Кроме того, такой код был бы архитектурно хуже и более подвержен ошибкам.

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

Оператор spread вместо arguments

Чтобы получить массив аргументов, можно использовать оператор , например:

В попадёт массив всех аргументов, начиная с третьего.

Заметим, что – настоящий массив, с методами , и другими, в отличие от .

Оператор … должен быть в конце

Оператор собирает «все оставшиеся» аргументы, поэтому такое объявление не имеет смысла:

Параметр должен быть в конце функции.

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

Формально говоря, эти два вызова делают одно и то же:

Похоже, что первый – короче и красивее.

Параметры, которые можно вызвать функцией

При вызове function ей можно отправить данные для обработки. Например, нижеследующий код выведет 2 сообщения:

 function showMessage(from, text) { // параметры from, text
 from = "** " + from + " **"; // здесь вставляем сложный код оформления
 alert(from + ': ' + text);
}
showMessage('Петя', 'Привет!');
showMessage('Петя', 'Как дела?');

Помните, что когда код будет передан, параметры скопируются в локальные переменные. Также функцию можно вызвать практически с любым количеством аргументов, а если при вызове параметр не будет передан, он считается равным undefined. К примеру, функцию отображения сообщений showMessage(from, text) можно без проблем вызвать, используя один аргумент:

showMessage("Петя");

Functions are Objects

The operator in JavaScript returns «function» for
functions.

But, JavaScript functions can best be described as objects.

JavaScript functions have both properties and
methods.

The property returns the number of arguments received when
the function was invoked:

Example

function myFunction(a, b) {  return arguments.length;}

The method returns the function as a string:

Example

function myFunction(a, b) {  return a * b;}var txt = myFunction.toString();

A function defined as the property of an object, is called a method to the object.
A function designed to create new objects, is called an object constructor.

Definition and Usage

The function statement declares a function.

A declared function is «saved for later use», and will be executed later,
when it is invoked (called).

In JavaScript, functions are objects, and they have both properties and
methods.

A function can also be defined using an expression (See
Function Definitions).

Read our JavaScript Tutorial to learn all you need to know about functions.
Start with the introduction chapter about
JavaScript Functions and
JavaScript Scope. For more detailed
information, see our Function Section on
Function Definitions,
Parameters,
Invocation and
Closures.

Tip: Use the return statement
to return a value from the function.

Вложенные функции

Функция называется «вложенной», когда она создаётся внутри другой функции.

Это очень легко сделать в JavaScript.

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

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

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

Не важно где, она всё так же будет иметь доступ к тем же внешним переменным

Например, здесь, вложенная функция присваивается новому объекту в конструкторе:

А здесь мы просто создаём и возвращаем функцию «счётчик»:

Давайте продолжим с примером . Он создаёт функцию «counter», которая возвращает следующее число при каждом вызове. Несмотря на простоту, немного модифицированные варианты этого кода применяются на практике, например, в генераторе псевдослучайных чисел и во многих других случаях.

Как же это работает изнутри?

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

  1. Локальные переменные вложенной функции…
  2. Переменные внешней функции…
  3. И так далее, пока не будут достигнуты глобальные переменные.

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

Теперь рассмотрим два вопроса:

  1. Можем ли мы каким-нибудь образом сбросить счётчик из кода, который не принадлежит ? Например, после вызова в коде выше.
  2. Если мы вызываем несколько раз – нам возвращается много функций . Они независимы или разделяют одну и ту же переменную ?

Попробуйте ответить на эти вопросы перед тем, как продолжить чтение.

Готовы?

Хорошо, давайте ответим на вопросы.

  1. Такой возможности нет: – локальная переменная функции, мы не можем получить к ней доступ извне.
  2. Для каждого вызова создаётся новое лексическое окружение функции, со своим собственным . Так что, получившиеся функции – независимы.

Вот демо:

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

JavaScript Функции

Функция (function) – это самостоятельный фрагмент кода, решающий определенную задачу. Каждой функции присваивается уникальное имя, по которому ее можно идентифицировать и «вызвать» в нужный момент.

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

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

Объявление и вызов функции

Функция (как и всякий объект) должна быть объявлена (определена) перед её использованием.

Функция JavaScript определяется с помощью ключевого слова , за которым указываются следующие компоненты:

  • Идентификатор, определяющий имя функции. Чаще всего в качестве имен функций выбираются глаголы или фразы, начинающиеся с глаголов. По общепринятому соглашению имена функций начинаются со строчной буквы.
  • Пара круглых скобок , которые могут включать имена параметров, разделенных запятыми ( параметр1, параметр2, … ). Эти имена параметров в теле функции могут использоваться как локальные переменные.
  • Пара фигурных скобок с инструкциями JavaScript внутри. Эти инструкции составляют тело функции: они выполняются при каждом вызове функции.

Синтаксис функции JavaScript:

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

Выполнить код »
Скрыть результаты

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

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

Интерпретатор JavaScript, встречая ключевое слово , создаёт функцию и переменную с именем этой функции. Переменной присваивается ссылка на функцию.

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

Ссылку на функцию вы можете сохранить в любой переменной, например:

«Классическое» объявление функции называется в спецификации языка «Function Declaration».

Существует альтернативный синтаксис для объявления функции «Function Expression» (функциональное выражение) – это объявление функции, которое является частью какого-либо выражения (например присваивания):

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

Если у функции нет имени, как в предыдущем примере, она называется «анонимной».

Разница между представленными объявлениями заключается в том, что функции, объявленные как «Function Declaration», создаются интерпретатором до начала выполнения кода (на этапе анализа), поэтому их можно вызвать до объявления:

Функции «Function Expression» (функциональные выражения) создаются в процессе выполнения выражения, в следующем примере функция будет создана при операции присваивания , поэтому вызов функции до её объявления приведёт к ошибке:

Функции — объекты

В javascript функции являются полноценными объектами встроенного класса Function. Именно поэтому их можно присваивать переменным, передавать и, конечно, у них есть свойства:

function f() {
	...
}
f.test = 6
...
alert(f.test) // 6

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

Например,

function func() {
	var funcObj = arguments.callee

	funcObj.test++
	alert(funcObj.test)
}
func.test = 1
func()
func()

В начале работы каждая функция создает внутри себя переменную и присваивает ссылку на себя. Так что — свойство , т.е статическая переменная test.

В примере нельзя было сделать присвоение:

var test = arguments.callee.test
test++

так как при этом операция сработала бы на локальной переменной , а не на свойстве объекта функции.

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

Неотложные функции

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

Есть два наиболее распространенных синтаксиса:

(function optional_function_name() {
  //body
}());
(function optional_function_name() {
  //body
})();

Могут всречаться и другие способы:

// Другие способы
!function() { /* ... */ }();
+function() { /* ... */ }();
new function() { /* ... */ };

Неотложные функции идеально подходят для написания кода, который должен выполниться только один раз: пространство имен, создание замыканий, создание частных переменных и многое другое. Для примера, представьте что с помощью JavaScript требуется получить язык страницы, а сделать это можно только проделав какие-то вычисления (например, ajax запрос).

var page_language = (function () {
  var lang;
  // Код для получения языка страницы
  return lang;
})();

«Поднятие» переменных и функций

Интерпретатор JavaScript всегда перемещает («поднимает») объявления функций и переменных в начало области видимости. Если переменная определена внутри функции, она поднимается к верхней части функции, а если переменная определена глобально — к верхней части глобального контекста. Рассмотрим, что это значит на примере:

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

В случае с функциями, поднимается вся функция целиком, если речь идет о функциях-объявлениях (declaration); функция-выражение (expression) не поднимается:

В этом этом примере поднимается только функция . Идентификатор «anomFunc» (переменная, которой присвоена функция) также поднимается, но сама анонимная функция при этом остаётся на месте (как и в случае с пременной).

Переменная «arguments»

Все аргументы функции находятся в псевдомассиве под своими порядковыми номерами.

Например:

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

Но у него есть один недостаток. Хотя похож на массив, и его тоже можно перебирать, это всё же не массив. Он не поддерживает методы массивов, поэтому мы не можем, например, вызвать .

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

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

Стрелочные функции не имеют

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

Пример:

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

Свойство «name»

Объект функции содержит несколько полезных свойств.

Например, имя функции нам доступно как свойство «name»:

Что довольно забавно, логика назначения весьма умная. Она присваивает корректное имя даже в случае, когда функция создаётся без имени и тут же присваивается, вот так:

Это работает даже в случае присваивания значения по умолчанию:

В спецификации это называется «контекстное имя»: если функция не имеет name, то JavaScript пытается определить его из контекста.

Также имена имеют и методы объекта:

В этом нет никакой магии. Бывает, что корректное имя определить невозможно. В таких случаях свойство name имеет пустое значение. Например:

Впрочем, на практике такое бывает редко, обычно функции имеют .

Возвращаемые значения

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

Инструкция return имеет следующий синтаксис:

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

Выполнить код »
Скрыть результаты

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

Инструкция может быть расположена в любом месте функции. После инструкции происходит выход из функции. Все операторы, расположенные в коде по­сле инструкции , не будут выполнены, например:

Выполнить код »
Скрыть результаты

В инструкции можно указать сразу выражение, перепишем нашу
функцию :

Выполнить код »
Скрыть результаты

Внутри функции можно использовать несколько инструкций :

Выполнить код »
Скрыть результаты

В случае, если в функции нет инструкции или указана без аргументов, то функция вернёт значение :

Выполнить код »
Скрыть результаты

Параметры по умолчанию

Можно указывать параметры по умолчанию через равенство , например:

Параметр по умолчанию используется при отсутствующем аргументе или равном , например:

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

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

Например:

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

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

Свойства функции

Функция в JavaScript является объектом, поэтому можно присваивать свойства прямо к ней, вот так:

Свойства функции не стоит путать с переменными и параметрами. Они совершенно никак не связаны. Переменные доступны только внутри функции, они создаются в процессе её выполнения. Это – использование функции «как функции».

А свойство у функции – доступно отовсюду и всегда. Это – использование функции «как объекта».

Если хочется привязать значение к функции, то можно им воспользоваться вместо внешних переменных.

В качестве демонстрации, перепишем пример со счётчиком:

При запуске пример работает также.

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

Например, можно взять и поменять счётчик из внешнего кода:

Статические переменные

Иногда свойства, привязанные к функции, называют «статическими переменными».

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

Итого

Когда мы видим в коде, это могут быть как остаточные параметры, так и оператор расширения.

Как отличить их друг от друга:

  • Если располагается в конце списка аргументов функции, то это «остаточные параметры». Он собирает остальные неуказанные аргументы и делает из них массив.
  • Если встретился в вызове функции или где-либо ещё, то это «оператор расширения». Он извлекает элементы из массива.

Полезно запомнить:

  • Остаточные параметры используются, чтобы создавать новые функции с неопределённым числом аргументов.
  • С помощью оператора расширения можно вставить массив в функцию, которая по умолчанию работает с обычным списком аргументов.

Вместе эти конструкции помогают легко преобразовывать наборы значений в массивы и обратно.

К аргументам функции можно обращаться и по-старому — через псевдомассив .

Итого

Основные улучшения в функциях:

  • Можно задавать параметры по умолчанию, а также использовать деструктуризацию для чтения приходящего объекта.
  • Оператор spread (троеточие) в объявлении позволяет функции получать оставшиеся аргументы в массив: .
  • Тот же оператор spread в вызове функции позволяет передать в неё массив как список аргументов (вместо ).
  • У функции есть свойство , оно содержит имя, указанное при объявлении функции, либо, если его нет, то имя свойства или переменную, в которую она записана. Есть и некоторые другие ситуации, в которых интерпретатор подставляет «самое подходящее» имя.
  • Объявление Function Declaration в блоке видно только в этом блоке.
  • Появились функции-стрелки:
    • Без фигурных скобок возвращают выражение : .
    • С фигурными скобками требуют явного .
    • Не имеют своих и , при обращении получают их из окружающего контекста.
    • Не могут быть использованы как конструкторы, с .

Итоги

  • «Классическое» объявление функции («Function Declaration») обрабатывается рань­ше остального кода. Такую функцию можно вызвать до её объявления.
  • Функциональные выражения («Function Expression») обрабатыва­ются вместе с остальным кодом. Такую функцию нельзя вызвать до её объявления.
  • Функции в JavaScript являются значениями. Их можно присваивать, передавать, создавать в любом месте кода. В отличие от других видов значений функцию можно вызвать для выполнения кода, содержащегося в ее теле.
  • Процесс вызова функции, созданной по объ­явлению («Function Declaration»), не отличается от процесса вызова функции, созданной по выражению («Function Expression»).
  • Ссылки на функции могут храниться в пе­ременных.
  • Передаваемые при вызове функции аргументы копируются в параметры функции и становятся локальными переменными.
  • Функция может возврвщать значение с помощью инструкции .
  • После инструкции происходит выход из функции.
  • Если оператор вызван без значения, или в теле функции не указан , то её результат равен .
  • Функция представляет из себя определённое действие, поэтому в качестве имен функций выбираются глаголы или фразы, начинающиеся с глаголов.

Итого: замыкания

Замыкание – это функция вместе со всеми внешними переменными, которые ей доступны.

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

Тем не менее, в JavaScript есть небольшая терминологическая особенность.

Обычно, говоря «замыкание функции», подразумевают не саму эту функцию, а именно внешние переменные.

Иногда говорят «переменная берётся из замыкания». Это означает – из внешнего объекта переменных.

Что это такое – «понимать замыкания?»

Иногда говорят «Вася молодец, понимает замыкания!». Что это такое – «понимать замыкания», какой смысл обычно вкладывают в эти слова?

«Понимать замыкания» в JavaScript означает понимать следующие вещи:

  1. Все переменные и параметры функций являются свойствами объекта переменных . Каждый запуск функции создаёт новый такой объект. На верхнем уровне им является «глобальный объект», в браузере – .
  2. При создании функция получает системное свойство , которое ссылается на , в котором она была создана.
  3. При вызове функции, куда бы её ни передали в коде – она будет искать переменные сначала у себя, а затем во внешних с места своего «рождения».

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *