В этом руководстве вы узнаете об области видимости переменных JavaScript, которая определяет доступность переменных.
JavaScript имеет три области видимости:
- Глобальная область
- Локальная область
- Область действия блока (начиная с ES6)
Глобальная область
Когда механизм JavaScript выполняет сценарий, он создает глобальный контекст выполнения.
Кроме того, он также назначает переменные, которые вы объявляете вне функций, глобальному контексту выполнения. Эти переменные находятся в глобальной области видимости. Они также известны как глобальные переменные.
Пример:
var message = 'Hi';
message
переменной имеет глобальную область действия. Он может быть доступен везде в сценарии.
Локальная область
Переменные, которые вы объявляете внутри функции, являются локальными для этой функции. Они называются локальными переменными. Например:
var message = 'Hi'; function say() { var message = 'Hello'; console.log('message'); } say(); console.log(message);
Выход:
Hello Hi
Когда движок JavaScript выполняет функцию say()
, он создает контекст выполнения функции. Переменное message
объявленное внутри функции say()
, привязано к контексту выполнения функции, а не к глобальному контексту выполнения.
Цепочка областей
Рассмотрим следующий пример:
var message = 'Hi'; function say() { console.log(message); } say();
Выход:
Hi
В этом примере мы ссылаемся на переменную message
внутри функции say()
. JavaScript выполняет следующие действия:
- Находит
message
переменной в текущем контексте (контексте выполнения функции) функцииsay()
. Он не может найти ни одного. - Находит переменную
message
во внешнем контексте выполнения, который является глобальным контекстом выполнения. Он находит переменнуюmessage
.
Способ, которым JavaScript разрешает переменную, заключается в просмотре ее в ее текущей области видимости. Если он не может найти переменную, он переходит к внешней области видимости, которая называется цепочкой областей видимости.
Дополнительный пример
Рассмотрим следующий пример:
var y = 20; function bar() { var y = 200; function baz() { console.log(y); } baz(); } bar();
Выход:
200
В этом примере:
- Сначала движок JavaScript находит переменную y в области видимости функции
baz()
. Он не может найти ни одного. Так что это выходит за рамки этого. - Затем движок JavaScript находит переменную y в функции
bar()
. Он может найти переменную y в области действия функцииbar()
и прекратить поиск.
Утечки глобальных переменных
Пример:
function getCounter() { counter = 10; return counter; } console.log(getCounter());
Выход:
10
В этом примере мы присвоили переменной counter
значение 10 без ключевых слов var
, let
или const
, а затем вернули его.
Вне функции мы вызвали функцию getCounter()
и показали результат в консоли.
Эта проблема известна как утечка глобальных переменных.
Под капотом движок JavaScript сначала ищет переменную counter
в локальной области видимости функции getCounter()
. Поскольку ключевое слово var
, let
или const
отсутствует, переменная counter
недоступна в локальной области. Он не создан.
Затем движок JavaScript следует по цепочке областей видимости и ищет переменную counter
в глобальной области видимости. Глобальная область также не имеет переменной counter
, поэтому механизм JavaScript создает переменную counter
в глобальной области.
Чтобы исправить это «странное» поведение, вы используете 'use strict'
в верхней части скрипта или в верхней части функции:
'use strict' function getCounter() { counter = 10; return counter; } console.log(getCounter());
Теперь код выдает ошибку:
ReferenceError: counter is not defined
Ниже показано, как использовать 'use strict'
в функции:
function getCounter() { 'use strict' counter = 10; return counter; } console.log(getCounter());
Область блока
ES6 предоставляет ключевые слова let
и const
, которые позволяют объявлять переменные в области блока.
Как правило, всякий раз, когда вы видите фигурные скобки {}
, это блок. Это может быть область внутри циклов if
, else
, switch
или for
, do while
и while
.
См. следующий пример:
function say(message) { if(!message) { let greeting = 'Hello'; // block scope console.log(greeting); } // say it again ? console.log(greeting); // ReferenceError } say();
В этом примере мы ссылаемся на переменную greeting
вне блока if
, что приводит к ошибке.