Как сделать переменную глобальной js

Добавил пользователь Алексей Ф.
Обновлено: 10.09.2024

Области видимости в JavaScript всегда были непростой темой, особенно в сравнении с более строго организованными языками, такими, как C и Java. В течение многих лет области видимости в JS особенно широко не обсуждались, так как в языке попросту не было средств, которые позволяли бы существенно повлиять на сложившуюся ситуацию. Но в ECMAScript 6 появились некоторые новые возможности, которые позволяют разработчикам лучше контролировать области видимости переменных. Эти возможности в наши дни уже очень хорошо поддерживают браузеры, они вполне доступны для большинства разработчиков. Однако новые ключевые слова для объявления переменных, учитывая ещё и то, что старое ключевое слово var никуда не делось, означают не только новые возможности, но и появление новых вопросов. Когда использовать ключевые слова let и const ? Как они себя ведут? В каких ситуациях всё ещё актуально ключевое слово var ? Материал, перевод которого мы сегодня публикуем, направлен на исследование проблемы областей видимости переменных в JavaScript.

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

Взгляните на следующий пример:


Что выведет метод console.log ? Ответ на этот вопрос никого не удивит: он выведет 2 . Переменная myVar объявлена за пределами какой-либо функции, что говорит нам о том, что она объявлена в глобальной области видимости. Следовательно, любая функция, объявленная в той же области видимости, сможет обратиться к myVar . На самом деле, если речь идёт о коде, выполняемом в браузере, доступ к этой переменной будет даже у функций, объявленных в других файлах, подключённых к странице.

Теперь взглянем на следующий код:



Что попадёт в консоль после его выполнения? Понятно, что внутри цикла будут выводиться значения увеличивающегося счётчика i : 0 , 1 и 2 . После того, как цикл завершается, программа продолжает выполняться. Теперь мы пытаемся обратиться к той же самой переменной-счётчику, которая была объявлена в цикле for , за пределами этого цикла. Что из этого выйдет?

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

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


Что попадёт в консоль теперь? 2 и 2 . Мы объявляем переменную, инициализируем её числом 1, а затем пытаемся переопределить ту же переменную внутри выражения if . Так как два эти объявления существуют в одной и той же области видимости, мы не можем объявить новую переменную с тем же именем, даже хотя мы, очевидно, хотим сделать именно это. В результате первая переменная перезаписывается внутри выражения if .

Вот в этом-то и заключается самый большой недостаток ключевого слова var . Область видимости переменных, объявленных с его использованием, оказывается слишком большой. Это может привести к непреднамеренной перезаписи данных и к другим ошибкам. Большие области видимости часто ведут к появлению неаккуратных программ. В целом, переменная должна иметь область видимости, ограниченную её нуждами, но не превышающую их. Хорошо было бы иметь возможность объявлять переменные, область видимости которых не так велика, как при использовании var , что позволило бы, при необходимости, применять более стабильные и лучше защищённые от ошибок программные конструкции. Собственно говоря, такие возможности нам даёт ECMAScript 6.

Стандарт ECMAScript 6 (новый набор возможностей JavaScript, известный ещё как ES6 и ES2015) даёт нам два новых способа объявления переменных, отличающихся ограниченной, по сравнению с var , областью видимости и имеющих ещё некоторые особенности. Это — ключевые слова let и const . И то и другое даёт нам так называемую блочную область видимости. Это означает, что область видимости при их использовании может быть ограничена блоком кода, таким, как цикл for или выражение if . Это даёт разработчику больше гибкости в выборе областей видимости переменных. Рассмотрим новые ключевые слова.

Использование ключевого слова let

Ключевое слово let очень похоже на var , основное отличие — ограниченная область видимости переменных, объявляемых с его помощью. Перепишем один из вышеприведённых примеров, заменив var на let :


В данном случае в консоль попадут числа 2 и 1 . Происходит это из-за того, что выражение if задаёт новую область видимости для переменной, объявленной с помощью ключевого слова let . Это приводит к тому, что вторая объявленная переменная — это совершенно самостоятельная сущность, не связанная с первой. С ними можно работать независимо друг от друга. Однако это не значит, что вложенные блоки кода, вроде нашего выражения if , полностью отрезаны от переменных, объявленных с помощью ключевого слова let в той области видимости, в которой находятся они сами. Взгляните на следующий код:


В этом примере в консоль попадёт число 1 . У кода, находящегося внутри выражения if есть доступ к переменной, которую мы создали за его пределами. Поэтому он и выводит её значение в консоль. А что произойдёт, если попытаться перемешать области видимости? Например, сделать так:


Может показаться, что первый вызов console.log выведет 1 , но на самом деле при попытке выполнить этот код появится ошибка ReferenceError , которая сообщает нам о том, что переменная myVar для данной области видимости не определена или не инициализирована (текст этой ошибки различается в разных браузерах). В JavaScript существует такое явление, как поднятие переменных в верхнюю часть их области видимости. То есть, если в некоей области видимости объявляют переменную, JavaScript резервирует место для неё ещё до того, как будет выполнена команда её объявления. То, как именно это происходит, различается при использовании var и let .

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


В обоих случаях мы пытаемся воспользоваться в переменной до её объявления. Но команды вывода данных в консоль ведут себя по-разному. Первая, использующая переменную, которая позже будет объявлена с помощью ключевого слова var , выведет undefined — то есть то, что будет записано в эту переменную. Вторая же команда, которая пытается обратиться к переменной, которая позже будет объявлена с помощью ключевого слова let , выдаст ReferenceError и сообщит нам, что мы пытаемся использовать переменную до её объявления или инициализации. В чём дело?

А дело тут в том, что перед выполнением кода механизмы, ответственные за его выполнение, просматривают этот код, выясняют, будут ли в нём объявляться какие-то переменные, и, если это так, осуществляют их поднятие с резервированием места для них. При этом переменные, объявленные с помощью ключевого слова var , инициализируются значением undefined в пределах своей области видимости, даже если к ним обращаются до того, как они будут объявлены. Основная проблема тут заключается в том, что значение undefined в переменной не всегда указывает на то, что переменной пытаются воспользоваться до её объявления. Взгляните на следующий пример:


В данном случае, несмотря на то, что var1 и var2 объявлены по-разному, оба вызова console.log выведут undefined . Дело здесь в том, что в переменные, объявленные с помощью var , но не инициализированные, автоматически записывается значение undefined . При этом, как мы уже говорили, переменные, объявленные с помощью var , к которым обращаются до момента их объявления, так же содержат undefined . В результате, если в подобном коде что-то пойдёт не так, нельзя будет понять, что именно является источником ошибки — использование неинициализированной переменной или использование переменной до её объявления.

Место для переменных, объявляемых с помощью ключевого слова let , резервируется в их блоке, но, до их объявления, они попадают во временную мёртвую зону (TDZ, Temporal Dead Zone). Это приводит к тому, что ими, до их объявления, пользоваться нельзя, а попытка обращения к такой переменной приводит к ошибке. Однако система точно знает причину проблемы и сообщает об этом. Это хорошо видно на данном примере:


Здесь первый вызов console.log выведет undefined , а второй вызовет ошибку ReferenceError , сообщая нам о том, что переменная пока не объявлена или не инициализирована.

В результате, если при использовании var появляется undefined , мы не знаем причину подобного поведения программы. Переменная может быть либо объявлена и неинициализирована, либо может быть ещё не объявлена в данной области видимости, но будет объявлена в коде, который расположен ниже команды обращения к ней. При использовании ключевого слова let мы можем понять — что именно происходит, а это гораздо полезнее для отладки.

Использование ключевого слова const

Ключевое слово const очень похоже на let , но у них есть одно важное различие. Это ключевое слово используется для объявления констант. Значения констант после их инициализации менять нельзя. Нужно отметить, что это относится лишь к значениям примитивных типов, воде строки или числа. Если константа является чем-то более сложным, например — объектом или массивом, внутреннюю структуру подобной сущности модифицировать можно, нельзя лишь заменить её саму на другую. Взгляните на следующий код:


Этот код будет выполняться вплоть до последней строки. Попытка назначить новое значение константе приведёт к появлению ошибки TypeError . Именно так ведут себя константы, но, как уже было сказано, объекты, которыми инициализируют константы, можно менять, они могут подвергаться мутациям, что способно приводить к неожиданностям.

Возможно вам, как JavaScript-разработчику, интересно, почему иммутабельность переменных — это важно. Константы — это новое явление в JavaScript, в то время как они являются важнейшей частью таких языков, как C или Java. Почему эта концепция так популярна? Дело в том, что использование констант заставляет нас думать о том, как именно работает наш код. В некоторых ситуациях изменение значения переменной может нарушить работу кода, например, если в ней записано число Пи и к ней постоянно обращаются, или если в переменной имеется ссылка на некий HTML-элемент, с которым постоянно нужно работать. Скажем, вот константа, в которую записана ссылка на некую кнопку:


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

Когда я только начал использовать ключевые слова let и const , я, в основном, применял let , прибегая к const лишь тогда, когда запись нового значения в переменную, объявленную с помощью let , могла бы навредить программе. Но, всё больше узнавая о программировании, я изменил своё мнение по этому вопросу. Теперь мой основной инструмент — это const , а let я использую только тогда, когда значение переменной нужно перезаписывать. Это заставляет меня думать о том, действительно ли необходимо менять значение некоей переменной. В большинстве случаев делать этого не нужно.

Ключевые слова let и const способствуют применению более ответственного подхода к программированию. Существуют ли ситуации, в которых всё ещё нужно ключевое слово var ? Да, существуют. Есть несколько ситуаций, в которых это ключевое слово нам ещё пригодится. Как следует поразмыслите над тем, о чём мы сейчас поговорим, прежде чем менять var на let или const .

Уровень поддержки ключевого слова var браузерами

Переменные, объявленные с помощью ключевого слова var , отличаются одной очень важной особенностью, отсутствующей у let и const . А именно, речь идёт о том, что это ключевое слово поддерживают абсолютно все браузеры. Хотя поддержка браузерами let и const весьма хороша, однако, существует риск того, что ваша программа попадёт в браузер, их не поддерживающий. Для того чтобы понять последствия подобного происшествия, нужно учитывать то, как браузеры обходятся с неподдерживаемым JavaScript-кодом, в противовес, например, тому, как они реагируют на непонятный им CSS-код.

Если браузер не поддерживает какую-то возможность CSS, то это, в основном, ведёт к некоторым искажениям того, что будет выведено на экран. Сайт в браузере, который не поддерживает какие-то из используемых сайтом стилей, будет выглядеть не так, как ожидается, но им, весьма вероятно, можно будет пользоваться. Если же вы используете, например, let , а браузер это ключевое слово не поддерживает, то ваш JS-код там просто не будет работать. Не будет — и всё. Учитывая то, что JavaScript является одной из важных составных частей современного веба, это может стать серьёзнейшей проблемой в том случае, если вам надо, чтобы ваши программы работали бы в устаревших браузерах.

Если вам нужно поддерживать по-настоящему старые браузеры, но вы хотите при этом использовать let , const и другие новые возможности ES6, одним из вариантов решения проблемы является применение JavaScript-транспилятора наподобие Babel. Транспиляторы обеспечивают перевод нового кода в то, что будет понятно старым браузерам. Применяя Babel, можно писать современный код, использующий самые свежие возможности языка, а затем преобразовывать его в код, который могут выполнять устаревшие браузеры.

Звучит слишком хорошо, чтобы быть правдой? На самом деле, использование транспиляторов таит в себе некоторые неприятные особенности. Так, это значительно увеличивает объём готового кода, если сравнить его с тем, что можно было бы получить, написав его вручную. Как результат, растёт объём файлов. Кроме того, если вы начали использовать некий транспилятор, ваш проект оказывается привязанным к нему. Даже если вы пишете ES6-код, который совершенно правильно обрабатывается Babel, отказ от Babel приведёт к тому, что вам придётся перепроверять весь код, тщательно тестировать его. Если ваш проект работает как часы, эта идея вряд ли понравится тем, кто занимается его разработкой и поддержкой. Тут придётся задаваться некоторыми вопросами. Когда планируется переработать кодовую базу? Когда поддержка чего-то вроде IE8 уже не будет иметь значения? Возможно, ответы на эти вопросы и не повлияют на отказ от транспилятора, но их, в любом случае, надо учитывать, решаясь на столь серьёзный шаг.

Использование var для решения одной специфической задачи

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


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


Когда переменная объявляется в глобальной области видимости с использованием var , она автоматически привязывается к глобальному объекту window . Ключевые слова let и const этого не делают. Эта особенность однажды выручила меня в ситуации, когда сборочный скрипт проверял JS-код перед объединением файлов, а ссылка на глобальную переменную в одном из файлов (который, после сборки, был бы объединён с другими) выдавала ошибку, что не давало собрать проект.

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


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

Итак, что выбрать? Как расставить приоритеты? Вот некоторые соображения по этому поводу:

  • Вы собираетесь поддерживать IE10 или по-настоящему старые браузеры? Если вы даёте на этот вопрос положительный ответ и не собираетесь пользоваться транспиляторами — отказывайтесь от новых возможностей и используйте var .
  • Если вы можете позволить себе использование новых возможностей JavaScript, начать стоит с того, чтобы везде, где раньше применялось ключевое слово var , использовать const . Если где-то нужна возможность перезаписи значения переменной (хотя, если вы попытаетесь переписать свой код, то эта возможность может вам и не понадобиться) — используйте let .

Область действия (или область видимости) определяет доступность (видимость) переменных.

JavaScript имеет 3 типа области действия:

  • Область действия блока
  • Область действия функции
  • Область действия глобальная

Область действия блока

До ES6 (2015) в JavaScript были только Глобальная область действия и Область действия функции.

ES6 представил два важных новых ключевых слова JavaScript: let и const .

Эти два ключевых слова обеспечивают область действия блока в JavaScript.

К переменным, объявленным внутри блока < >, нельзя получить доступ извне блока:

Пример

Переменные, объявленные с помощью ключевого слова var НЕ могут иметь область действия блока.

К переменным, объявленным внутри блока < >, можно получить доступ извне блока.

Пример

Локальная область действия

Переменные, объявленные в функции JavaScript, становятся ЛОКАЛЬНЫМИ для функции.

Пример

// код здесь НЕ может использовать carName

function myFunction() let carName = "Volvo";
// код здесь МОЖЕТ использовать carName
>

// код здесь НЕ может использовать carName

Локальные переменные имеют Область действия функции:

Доступ к ним можно получить только из функции.

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

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

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

JavaScript имеет область действия функции: каждая функция создает новую область действия.

Переменные, определенные внутри функции, недоступны (видимы) вне функции.

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

Они все имеют Область действия функции:

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

Переменная, объявленная вне функции, становится ГЛОБАЛЬНОЙ.

Пример

let carName = "Volvo";
// код здесь может использовать carName

function myFunction() // код здесь также может использовать carName
>

Глобальная переменная имеет Глобальную область действия:

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

Глобальная область действия

Переменные, объявленные Глобально (вне какой-либо функции), имеют Глобальную область действия.

Доступ к глобальным переменным можно получить из любого места в программе JavaScript.

Переменные, объявленные с помощью var , let и const очень похожи, когда объявлены вне блока.

Они все имеют Глобальную область действия:

JavaScript Переменные

В JavaScript объекты и функции также являются переменными.

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

Автоматически глобальная

Если вы присвоите значение переменной, которая не была объявлена, она автоматически станет ГЛОБАЛЬНОЙ переменной.

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

Пример

// код здесь может использовать carName

function myFunction() carName = "Volvo";
>

Строгий режим

Все современные браузеры поддерживают выполнение JavaScript в "Строгом режиме".

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

В "Строгом режиме" необъявленные переменные не становятся глобальными автоматически.

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

В JavaScript глобальной областью действия является среда JavaScript.

В HTML глобальной областью действия является объект окна.

Глобальные переменные, определенные с помощью ключевого слова var принадлежат объекту окна:

Пример

Глобальные переменные, определенные с помощью ключевого слова let не принадлежат объекту окна:

Пример

Предупреждение

НЕ создавайте глобальные переменные, если вы не собираетесь.

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

Время жизни переменных JavaScript

Время жизни переменной JavaScript начинается с момента её объявления.

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

В веб-браузере глобальные переменные удаляются при закрытии окна (или вкладки) браузера.

Аргументы функции

Аргументы функции (параметры) работают как локальные переменные внутри функций.

ПАЛИТРА ЦВЕТОВ

Связь с админом

Топ Учебники

Топ Справочники

Топ Примеры

Веб Сертификаты

Этот сайт оптимизирован для обучения и тестирования. Примеры могут быть упрощены для улучшения чтения и базового понимания. Учебные пособия, ссылки и примеры постоянно пересматриваются, чтобы избежать ошибок, но мы не можем гарантировать полную правильность и работоспособность всего контента. Используя этот сайт, вы соглашаетесь с тем, что прочитали и приняли условия использования, cookie и политику конфиденциальности.
Также вы можете абсолютно бесплатно скачать офлайн версию сайта W3Schools на русском архивом с GitHub и пользоваться локально на своём компьютере.
Также доступна версия сайта W3Schools на украинском языке.
Copyright 1999-2023 by Refsnes Data. All Rights Reserved.
Сайт работает на фреймворке W3.CSS.

Область действия определяет доступность (видимость) переменных.

JavaScript Область действия функции

В JavaScript есть два типа области видимости:

  • Локальная область действия
  • Глобальная область действия

JavaScript имеет область действия функции: каждая функция создает новую область действия.

Область действия определяет доступность (видимость) этих переменных.

Переменные, определенные внутри функции, недоступны (не видны) снаружи функции.

JavaScript Локальные переменные

Переменные, объявленные в функции JavaScript, становятся ЛОКАЛЬНЫМИ для функции.

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

Пример

// код здесь НЕ МОЖЕТ использовать carName

function myFunction() var carName = "Вольво";

// код здесь МОЖЕТ использовать carName

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

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

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

Переменная, объявленная вне функции, становится ГЛОБАЛЬНОЙ.

Глобальная переменная имеет глобальную область действия функции: все сценарии и функции на веб-странице могут получить к ней доступ.

Пример

var carName = "Вольво";

// код, в котором можно использовать carName

// код, в котором также можно использовать carName

JavaScript Переменные

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

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

Автоматически Глобальная

Если вы присвоите значение переменной, которая не была объявлена, она автоматически станет ГЛОБАЛЬНОЙ переменной.

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

Пример

// код, в котором можно использовать carName

function myFunction() carName = "Вольво";
>

Строгий режим

Все современные браузеры поддерживают выполнение JavaScript в "строгом режиме".

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

В "строгом режиме" необъявленные переменные не становятся автоматически глобальными.

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

В JavaScript глобальная область действия - это полная среда JavaScript.

В HTML глобальной областью видимости является объект окна. Все глобальные переменные принадлежат объекту окна.

Пример

var carName = "Вольво";

// код, в котором можно использовать window.carName

Предупреждение

НЕ создавайте глобальные переменные, если вы не собираетесь их использовать.

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

Время жизни переменных JavaScript

Время жизни переменной JavaScript начинается с момента ее объявления.

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

В веб браузере глобальные переменные удаляются при закрытии окна (или вкладки) браузера.

Аргументы функции

Аргументы (параметры) функции работают как локальные переменные внутри функций.


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

Область видимости

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

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

Пример

Представим, что наша программа состоит из двух переменных и одной функции, которую мы разбирали в Уроке 4:

В глобальную область видимости войдут переменные someVar и someOtherVar, а также функция sum.

В локальной видимости находится то, что указано внутри функции sum: два параметра a и b, а также переменная result.

Добавим ещё одну функцию:

Теперь в глобальную область видимости добавилась и функция someFn, а в функции someFn образовалась собственная локальная область видимости, которая состоит из параметров a, b, c, d и двух переменных var1 и var2.

Замыкания

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

Пример

Снова возьмём наш код, который состоит из двух переменных и одной функции, но попросим функцию выполнить сложение не только параметров a и b, но и значений из переменных someVar и someOtherVar. Это выглядит так:

Запишем результат функции sum с аргументами 2 и 3 в переменную result, чтобы затем вывести её значение в консоль:

Выведем результат в консоль:

Так как функция sum объявлена в глобальной области видимости после переменных someVar и someOtherVar, то она может ими пользоваться. В консоли увидим результат:

Если бы мы сначала создали функцию sum, а затем переменные someVar и someOtherVar, то функция бы не сработала.

Здесь замыкание – это способность функции sum обратиться к созданным ранее переменным someVar и someOtherVar.

Как интерпретатор пришёл к результату 55? Рассмотрим пошагово:

1. Мы попросили его выполнить заданную функцию с аргументами 2 и 3 и вывести результат:

2. Он проводит поиск, берёт заданные аргументы и подставляет в соответствующие параметры их значения.

3. Сначала поиск происходит в локальной области видимости – внутри функции. В этой области он видит параметры a и b, равные 2 и 3 соответственно. Подставляет:

Теперь ему нужно найти значения переменных someVar и someOtherVar. Как он это сделает? Закончив поиск внутри локальной области и не найдя там нужных значений, интерпретатор переходит в более широкую область. В данном случае – это глобальная. Здесь находится сама функция sum и значения переменных someVar и someOtherVar. Интерпретатор подставляет их в функцию вот так:

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

Усложним задачу и сделаем несколько локальных областей видимости.

Для этого создадим переменную a и функцию fn1, в которую вложена ещё одна функция fn2:

Теперь попросим компьютер выдать нам результат функции fn1 с аргументами 1 и 2, записав их в переменную result:

Как интерпретатор вычисляет результат в этом случае?

Рассмотрим подробнее выражение, записанное в функции fn2 – a + b + c + d + e:

Сначала ищем значение a. В первую очередь поиск происходит внутри локальной области видимости первого уровня – это область видимости функции fn2:

Здесь значения a нет.

Поиск переходит в локальную область видимости более высокого уровня, в которой создана функция fn2 – это функция fn1:

Но и здесь значения a нет.

Тогда поиск переходит на следующий уровень видимости, куда вложена функция fn1 – это глобальная область. И здесь находит переменную a со значением 10. Подставляет его в выражение: 10 + b + c + d + e.

Продолжает поиск параметров b и c сначала в своей области видимости. Не находит. Затем обнаруживает их в локальной области видимости функции fn1, которым мы передали значение 1 и 2. Подставляет: 10 + 1 + 2 + d + e.

Продолжает поиск параметров d и e и сразу находит их в своей локальной области видимости, подставляет переданные значения 3 и 4: 10 + 1 + 2 + 3 + 4.

Так мы видим в консоли итоговый результат:

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

Читайте также: