Замыкания javascript. Что такое замыкание в javascript. Javascript-программирование в циклах

Подробнее про замыкания в JavaScript

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

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

Простое описание

Если говорить просто, то замыкания - это внутренние функции. Ведь javascript разрешает создавать функции по ходу выполнения скрипта. И эти функции имеют доступ к переменным внешней функции.

В этом примере создается внутренняя функция func , изнутри которой доступны как локальные переменные, так и переменные внешней функции outer :

function outer() { var outerVar; var func = function () { var innerVar ... x = innerVar + outerVar } return func }

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

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

Наиболее часто замыкания применяются для назначения функций-обработчиков событий:

Здесь динамически созданный обработчик события handler использует targetId из внешней функции для доступа к элементу.

Если Вы хотите углубиться поглубже и разбираться подольше..

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

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

[]

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

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

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

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

Общий поток выполнения выглядит так:

Кстати, для кода вне функции(и вообще глобальных переменных) роль объекта-контейнера [] выполняет объект window .

Область видимости вложенной функции

Когда одна функция создается внутри другой, то для нее создается ссылка на объект с локальными переменными [] внешней функции.

Именно за счет этого из внутренней функции можно получить переменные внешней функции - через ссылку на ее [] . Сначала ищем у себя, затем - во внешнем [] - и так далее по цепочке до самого объекта window .

Замыкание - это когда объект локальных переменных [] внешней функции остается жить после ее завершения.

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

Например, разберем работу функции, которая устанавливает обработчики событий:

function addHideHandler(sourceId, targetId) { // создан объект [] со свойствами sourceId, targetId // записать в [] свойство sourceNode var sourceNode = document.getElementById (sourceId) // записать в [] свойство handler var handler = function () { var targetNode = document.getElementById (targetId) targetNode.style .display = ‘none’ } sourceNode.onclick = handler // функция закончила выполнение // (***) и тут - самое интересное! }

При запуске функции все происходит стандартно:

  1. создается []
  2. туда записываются локальные переменные
  3. внутренняя функция получает ссылку на []

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

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

Вместо этого он просто оставляет весь [] внешней функции в живых.

Чтобы когда внутренняя функция запустится, если она вдруг не найдет какую-либо переменную в своем [] - она могла обратиться к [] внешней функции и нашла бы ее там.

Если внешняя функция была создана внутри еще одной (еще более внешней) функции - то в цепочку добавляется еще один консервированный [] и так - до глобальной области window .

Пример на понимание

В этом примере внешняя функция makeShout () создает внутреннюю shout ().

function makeShout() { var phrase = "Превед!" var shout = function () { alert (phrase) } phrase = "Готово!" return shout } shout = makeShout() // что выдаст? shout()

Функция shout () на правах внутренней функции имеет доступ к переменной phrase . Какое значение она выведет - первое или второе?

А вот - подробное описание происходящего в недрах javascript:

  1. Внутри makeShout ()
    1. создается []
    2. В [] пишется: phrase="Превед!"
    3. В [] пишется: shout=..функция..
    4. shout получает ссылку на [] внешней функции
    5. [].phrase меняется на новое значение "Готово!"
  2. При запуске shout()
    1. Создается свой собственный объект []
    2. Ищется phrase в [] - не найден
    3. Ищется phrase в [] внешней функции - найдено значение "Готово!"
    4. alert("Готово!")

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

Пример ошибочного использования

Функция addEvents принимает массив div "ов и ставит каждому вывод своего номера на onclick .

С вопроса "Почему это не работает?" люди обычно начинают изучение замыканий.

function addEvents(divs) { for (var i=0 ; i

Для тестового примера сделаем 10 разноцветных нумерованных div "ов с разными цветами:

function makeDivs(parentId) { for (var i=0 ;i<10 ;i++) { var j = 9 -i var div = document.createElement ("div" ) div.style .backgroundColor = "#" +i+i+j+j+j+i div.className ="closure-div" div.style .color = "#" +j+j+i+i+i+j document.getElementById (parentId) .appendChild (div) } }

Кнопка ниже создаст 10 дивов и вызовет для них addEvents

Если Вы покликаете на div"ы - они все выдают одинаковый alert.

Такой глюк возник из-за того, что все функции div[i].onclick получают значение i из одного на всех [] внешней функции. А это значение ([].i ) на момент активации onclick -обработчика равно 10 (цикл завершился как только i==10 ).

Чтобы все было в порядке, в таких случаях применяют специальный прием - выделение [] . Следующая функция работает правильно. В ней все то же самое, кроме div.onclick .

function addEvents2(divs) { for (var i=0 ; i

Теперь все должно быть в порядке - каждый div дает alert на свой номер.

Для присваивания div.onclick запускается временная функция function(x) {..} , принимающая аргумент x и возвращающая обработчик, который берет x из [] этой временной функции.

Function(x) {..} используется для создания функции, и тут же (i) - для запуска с аргументом i .

Вообще, javascript очень удобный в этом смысле язык. Допускает любые конструкции, например:

alert ( function a() { return [ 5 ] } () [ 0 ] ) // => выведет 5

Временная функция function(x) {..} заканчивает работать тут же, оставляя в своем [] правильное значение x , равное текущей переменной i цикла.

Когда обработчик активизируется - alert возьмет из [] ближайшей внешней функциии правильное значение x .

По идее, этих примеров должно хватать для понимания и практического использования замыканий.

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment ). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

Lexical scoping

Consider the following:

Function init() { var name = "Mozilla"; // name is a local variable created by init function displayName() { // displayName() is the inner function, a closure alert(name); // use variable declared in the parent function } displayName(); } init();

init() creates a local variable called name and a function called displayName() . The displayName() function is an inner function that is defined inside init() and is only available within the body of the init() function. Note that the displayName() function has no local variables of its own. However, since inner functions have access to the variables of outer functions, displayName() can access the variable name declared in the parent function, init() .

Var counter = (function() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } }; })(); console.log(counter.value()); // logs 0 counter.increment(); counter.increment(); console.log(counter.value()); // logs 2 counter.decrement(); console.log(counter.value()); // logs 1

In previous examples, each closure has had its own lexical environment. Here, though, we create a single lexical environment that is shared by three functions: counter.increment , counter.decrement , and counter.value .

The shared lexical environment is created in the body of an anonymous function, which is executed as soon as it has been defined. The lexical environment contains two private items: a variable called privateCounter and a function called changeBy . Neither of these private items can be accessed directly from outside the anonymous function. Instead, they must be accessed by the three public functions that are returned from the anonymous wrapper.

Those three public functions are closures that share the same environment. Thanks to JavaScript"s lexical scoping, they each have access to the privateCounter variable and changeBy function.

You"ll notice we"re defining an anonymous function that creates a counter, and then we call it immediately and assign the result to the counter variable. We could store this function in a separate variable makeCounter and use it to create several counters.

Var makeCounter = function() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } } }; var counter1 = makeCounter(); var counter2 = makeCounter(); alert(counter1.value()); /* Alerts 0 */ counter1.increment(); counter1.increment(); alert(counter1.value()); /* Alerts 2 */ counter1.decrement(); alert(counter1.value()); /* Alerts 1 */ alert(counter2.value()); /* Alerts 0 */

Notice how each of the two counters, counter1 and counter2 , maintains its independence from the other. Each closure references a different version of the privateCounter variable through its own closure. Each time one of the counters is called, its lexical environment changes by changing the value of this variable; however changes to the variable value in one closure do not affect the value in the other closure.

Using closures in this way provides a number of benefits that are normally associated with object-oriented programming -- in particular, data hiding and encapsulation.

Closure Scope Chain

For every closure we have three scopes:-

  • Local Scope (Own scope)
  • Outer Functions Scope
  • Global Scope

So, we have access to all three scopes for a closure but often make a common mistake when we have nested inner functions. Consider the following example:

// global scope var e = 10; function sum(a){ return function(b){ return function(c){ // outer functions scope return function(d){ // local scope return a + b + c + d + e; } } } } console.log(sum(1)(2)(3)(4)); // log 20 // We can also write without anonymous functions: // global scope var e = 10; function sum(a){ return function sum2(b){ return function sum3(c){ // outer functions scope return function sum4(d){ // local scope return a + b + c + d + e; } } } } var s = sum(1); var s1 = s(2); var s2 = s1(3); var s3 = s2(4); console.log(s3) //log 20

So, in the example above, we have a series of nested functions all of which have access to the outer functions" scope, but which mistakenly guess only for their immediate outer function scope. In this context, we can say all closures have access to all outer function scopes within which they were declared.

Creating closures in loops: A common mistake

function showHelp(help) { document.getElementById("help").innerHTML = help; } function setupHelp() { var helpText = [ {"id": "email", "help": "Your e-mail address"}, {"id": "name", "help": "Your full name"}, {"id": "age", "help": "Your age (you must be over 16)"} ]; helpText.forEach(function(text) { document.getElementById(text.id).onfocus = function() { showHelp(text.help); } }); } setupHelp();

Performance considerations

It is unwise to unnecessarily create functions within other functions if closures are not needed for a particular task, as it will negatively affect script performance both in terms of processing speed and memory consumption.

For instance, when creating a new object/class, methods should normally be associated to the object"s prototype rather than defined into the object constructor. The reason is that whenever the constructor is called, the methods would get reassigned (that is, for every object creation).

Consider the following case:

Function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); this.getName = function() { return this.name; }; this.getMessage = function() { return this.message; }; }

Because the previous code does not take advantage of the benefits of using closures in this particular instance, we could instead rewrite it to avoid using closure as follows:

Function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); } MyObject.prototype = { getName: function() { return this.name; }, getMessage: function() { return this.message; } };

However, redefining the prototype is not recommended. The following example instead appends to the existing prototype:

Function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); } MyObject.prototype.getName = function() { return this.name; }; MyObject.prototype.getMessage = function() { return this.message; };

In the two previous examples, the inherited prototype can be shared by all objects and the method definitions need not occur at every object creation. See

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

Лексическая область видимости

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

Function init() { var name = "Mozilla"; // name - локальная переменная, созданная в init function displayName() { // displayName() - внутренняя функция, замыкание alert (name); // displayName() использует переменную, объявленную в родительской функции } displayName(); } init();

init() создаёт локальную переменную name и определяет функцию displayName() . displayName() - это внутренняя функция - она определена внутри init() и доступна только внутри тела функции init() . Обратите внимание, что функция displayName() не имеет никаких собственных локальных переменных. Однако, поскольку внутренние функции имеют доступ к переменным внешних функций, displayName() может иметь доступ к переменной name , объявленной в родительской функции init() .

Var Counter = (function() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } }; })(); alert(Counter.value()); /* Alerts 0 */ Counter.increment(); Counter.increment(); alert(Counter.value()); /* Alerts 2 */ Counter.decrement(); alert(Counter.value()); /* Alerts 1 */

Тут много чего поменялось. В предыдущем примере каждое замыкание имело свой собственный контекст исполнения (окружение). Здесь мы создаем единое окружение для трех функций: Counter.increment , Counter.decrement , и Counter.value .

Единое окружение создается в теле анонимной функции, которая исполняется в момент описания. Это окружение содержит два приватных элемента: переменную privateCounter и фукцию changeBy(val) . Ни один из этих элементов не доступен напрямую, за пределами этой самой анонимной функции. Вместо этого они могут и должны использоваться тремя публичными функциями, которые возвращаются анонимным блоком кода (anonymous wrapper), выполняемым в той же анонимной функции.

Эти три публичные функции являются замыканиями, использующими общий контекст исполнения (окружение). Благодаря механизму lexical scoping в Javascript, все они имеют доступ к переменной privateCounter и функции changeBy .

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

Var makeCounter = function() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } } }; var Counter1 = makeCounter(); var Counter2 = makeCounter(); alert(Counter1.value()); /* Alerts 0 */ Counter1.increment(); Counter1.increment(); alert(Counter1.value()); /* Alerts 2 */ Counter1.decrement(); alert(Counter1.value()); /* Alerts 1 */ alert(Counter2.value()); /* Alerts 0 */

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

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

Создание замыканий в цикле: Очень частая ошибка

До того, как в версии ECMAScript 6 ввели ключевое слово let , постоянно возникала следующая проблема при создании замыканий внутри цикла. Рассмотрим пример:

Helpful notes will appear here

E-mail:

Name:

Age:

function showHelp(help) { document.getElementById("help").innerHTML = help; } function setupHelp() { var helpText = [ {"id": "email", "help": "Ваш адрес e-mail"}, {"id": "name", "help": "Ваше полное имя"}, {"id": "age", "help": "Ваш возраст (Вам должно быть больше 16)"} ]; for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; document.getElementById(item.id).onfocus = function() { showHelp(item.help); } } } setupHelp();

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

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

Проблема в том, что функции, присвоенные как обработчики события onfocus , являются замыканиями. Они состоят из описания функции и контекста исполнения (окружения), унаследованного от функции setupHelp . Было создано три замыкания, но все они были созданы с одним и тем же контекстом исполнения. К моменту возникновения события onfocus цикл уже давно отработал, а значит, переменная item (одна и та же для всех трех замыканий) указывает на последний элемент массива, который как раз в поле возраста.

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

Function showHelp(help) { document.getElementById("help").innerHTML = help; } function makeHelpCallback(help) { return function() { showHelp(help); }; } function setupHelp() { var helpText = [ {"id": "email", "help": "Ваш адрес e-mail"}, {"id": "name", "help": "Ваше полное имя"}, {"id": "age", "help": "Ваш возраст (Вам должно быть больше 16)"} ]; for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; document.getElementById(item.id).onfocus = makeHelpCallback(item.help); } } setupHelp();

Вот это работает как следует. Вместо того, чтобы делить на всех одно окружение, функция makeHelpCallback создает каждому из замыканий свое собственное, в котором переменная item указывает на правильный элемент массива helpText .

Соображения по производительности

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

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

Давайте рассмотрим не очень практичный, но показательный пример:

Function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); this.getName = function() { return this.name; }; this.getMessage = function() { return this.message; }; }

Поскольку вышеприведенный код никак не использует преимущества замыканий, его можно переписать следующим образом:

Function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); } MyObject.prototype = { getName: function() { return this.name; }, getMessage: function() { return this.message; } };

Методы вынесены в прототип. Тем не менее, переопределять прототип - само по себе является плохой привычкой, поэтому давайте перепишем всё так, чтобы новые методы просто добавились к уже существующему прототипу.

Function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); } MyObject.prototype.getName = function() { return this.name; }; MyObject.prototype.getMessage = function() { return this.message; };

Код выше можно сделать аккуратнее:

function MyObject( name, message) { this . name = name. toString( ) ; this . message = message. toString( ) ; } (function () { this . getName = function () { return this . name; } ; this . getMessage = function () { return this . message; } ; } ) . call( MyObject. prototype) ;

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

Function внешняя(x) { var tmp = 3; function внутренняя(y) { alert(x + y + (++tmp)); // выведет 16 } внутренняя(10); } внешняя(2);

Этот код всегда выдаёт 16, потому, что функция внутренняя видит x , который является переменной в функуции внешняя. В данном случае аргументом функции. Так же внутренняя() может видить tmp из внешней() .

Это и называется замыкание или closure. Если точнее, замыканием называется именно внешняя функция, а всё что внутри неё называется closure environment или среда замыкания.

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

Function foo(x) { var tmp = 3; return function (y) { alert(x + y + (++tmp)); // will also alert 16 } } var bar = foo(2); // bar is now a closure. bar(10);

Приведённая выше функция также выдаст 16, поскольку bar даже после завершения foo продолжает иметь доступ к x и tmp , пусть даже сама переменная bar и не находится внутри области видимости в которой они были объявлены.

При этом, поскольку переменная tmp всё ещё находится внутри замыкания bar , она продолжает увеличиваться при каждом вызове bar .

Вот простейший пример замыкания:

Var a = 10; function test() { console.log(a); // вывод 10 console.log(b); // вывод 6 } var b = 6; test();

При запуске функции в JavaScript, для неё создаётся окружение, то есть список всех видимых ей переменных, не только аргументов и переменных объявленных внутри неё, но и снаружи, в данном примере это "a" и "b".

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

Поскольку в нашем примере x это число, то его значение копируется в foo как его аргумент x .

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

Function foo(x) { var tmp = 3; return function (y) { alert(x + y + tmp); x.memb = x.memb ? x.memb + 1: 1; alert(x.memb); } } var age = new Number(2); var bar = foo(age); // bar теперь замыкание ссылающееся на age. bar(10);

Как и следовало ожидать, каждый вызов bar(10) увеличивает x.memb . Чего вы могли не ожидать, так это, что x продолжает ссылаться на тот же самый объект, что и age ! После двух вызовов bar , age.memb будет равен 2! Кстати, так и происходят утечки памяти в HTML объектах.

Переменные JavaScript могут принадлежать локальным или глобальном масштабе.

Глобальные переменные можно сделать локальными (частными) с замыканиями.

Глобальные переменные

Функция может получить доступ ко всем переменным, определенным внутри функции, например:

Пример

function myFunction() {
var a = 4;
return a * a;
}

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

Пример

var a = 4;
function myFunction() {
return a * a;
}

В последнем примере a является глобальной переменной.

В веб-странице глобальные переменные принадлежат объекту Window.

Глобальные переменные могут быть использованы (и изменены) всеми скриптами на странице (и в окне).

В первом примере a - локальная переменная .

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

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

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

Переменная продолжительность жизни

Глобальные переменные живут до тех пор, пока ваше приложение (ваше окно/ваша веб-страница) живет.

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

Встречная дилемма

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

Можно использовать глобальную переменную и функцию для увеличения счетчика:

Пример

// Initiate counter
var counter = 0;


function add() {
counter += 1;
}

// Call add() 3 times
add();
add();
add();

// The counter should now be 3

Проблема с решением выше: любой код на странице может изменить счетчик, без вызова Add ().

Счетчик должен быть локальным для функции Add (), чтобы предотвратить его изменение другим кодом:

Пример

// Initiate counter
var counter = 0;

// Function to increment counter
function add() {
var counter;
counter += 1;
}

// Call add() 3 times
add();
add();
add();

//The counter should now be 3. But it is 0

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

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

Пример

// Function to increment counter
function add() {
var counter;
counter += 1;
return counter;
}

// Call add() 3 times
add();
add();
add();

//The counter should now be 3. But it is 1.

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

Внутренняя функция JavaScript может решить эту проблему.

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

Все функции имеют доступ к глобальной области видимости.

В самом деле, в JavaScript, все функции имеют доступ к области "выше" их.

JavaScript поддерживает вложенные функции. Вложенные функции имеют доступ к области "выше" их.

В этом примере внутренняя функция Plus () имеет доступ к переменной Counter в родительской функции:

Пример

function add() {
var counter = 0;
function plus() {counter += 1;}
plus();
return counter;