[Перевод] JavaScript: область видимости простыми словами

qzlgcssylf0he28diw7hcpmiyeg.png

Доброго времени суток, друзья!

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

В этой статье я постараюсь простыми словами объяснить, что такое область видимости в JavaScript.

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


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

Допустим, мы определили переменную:

const message = 'Hello'
console.log(message) // 'Hello'


Мы легко можем вывести ее значение в консоль. Это понятно.

Теперь поместим объявление переменной message в блок if:

if (true) {
    const message = 'Hello'
}
console.log(message) // ReferenceError: message is not defined


На этот раз при попытке доступа к переменной выбрасывается исключение ReferenceError: message is not defined.

Почему это произошло?

Потому что блок if создал область видимости для переменной message. И message доступна только внутри этой области.

2rrzqmyaxuooebz1ewhr5opobq4.jpeg

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

Итак, область видимости — это зона доступности переменных.

2. Блочная область видимости


Блок кода в JavaScript определяет область видимости переменных, объявленных с помощью ключевых слов const и let:

if (true) {
    // область видимости блока if
    const message = 'Hello'
    console.log(message) // 'Hello'
}
console.log(message) // ReferenceError


Первый console.log () благополучно выводит значение переменной message в консоль, поскольку доступ к этой переменной осуществляется в той области видимости, в которой она определена.

Однако вызов второго console.log () приводит к возникновению ошибки, поскольку переменная message недоступна во внешней по отношению к ней области видимости: в текущем контексте message не существует.

В инструкциях if, for, while также создается блочная область видимости.

Например:

for (const color of ['green', 'red', 'blue']) {
    // область видимости блока for
    const message = 'Hi'
    console.log(color) // 'green', 'red', 'blue'
    console.log(message) // 'Hi', 'Hi', 'Hi'
}
console.log(color) // ReferenceError
console.log(message) // ReferenceError


Переменные color и message существуют только внутри блока for.

Тоже самое справедливо для инструкции while:

while (/* условие */) {
    // область видимости блока while
    const message = 'Hi'
    console.log(message) // 'Hi'
}
console.log(message) // ReferenceError


message, определенная в while, доступна только внутри данного цикла.

В JavaScript вы можете создавать самостоятельные блоки кода. Они также определяют собственную область видимости:

{
    const message = 'Hi'
    console.log(message) // 'Hi'
}
console.log(message) // ReferenceError


2.1. var не имеет блочной области видимости


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

Рассмотрим пример:

if (true) {
    // область видимости блока if
    var count = 0
    console.log(count) // 0
}
console.log(count) // 0


Переменная count, как и ожидалось, доступна внутри блока if. Однако, она доступна и за пределами данного блока!

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

3. Область видимости функции


Функции в JavaScript создают область видимости для всех переменных, независимо от того, с помощью какого ключевого слова они объявлены (var, const или let).

Например:

function run() {
    // область видимости функции run()
    var message = 'Беги, Форрест, беги!'
    console.log(message)
}
run() // 'Беги, Форрест, беги!'
console.log(message) // ReferenceError


Функция run () создает область видимости. Переменная message доступна внутри функции, но недоступна снаружи.

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

function run() {
    // область видимости функции run()
    const two = 2
    let one = 1
    function run2() {}
    var run3 = () => {}

    console.log(two)
    console.log(one)
    console.log(run2)
    console.log(run3)
}
run() // 2 1 ƒ run2() {} () => {}
console.log(two) // ReferenceError
console.log(one) // ReferenceError
console.log(run2) // ReferenceError
console.log(run3) // ReferenceError


4. Область видимости модуля


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

Модуль circle создает константу pi (для внутреннего использования):

// область видимости модуля circle
const pi = 3.14

console.log(pi) // 3.14

// использование pi


Переменная pi объявляется внутри модуля circle и не экспортируется из него.

Затем модуль circle импортируется:

import './circle'

console.log(pi) // ReferenceError


Переменная pi недоступна за пределами модуля circle (до тех пор, пока она не будет экспортирована с помощью export).

Модульная область видимости инкапсулирует модули. Это означает, что частные переменные (которые не экспортируются) используются для собственных нужд модуля и защищены от доступа извне.

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

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


Интересной особенностью областей видимости является то, что они могут быть вложены одна в другую.

В следующем примере функция run () создает область видимости, а внутри нее блок if создает еще одну область:

function run() {
    // область видимости функции run()
    const message = 'Беги, Форрест, беги!'

    if (true) {
        // область видимости блока if
        const friend = 'Бубба'
        console.log(message) // 'Беги, Форрест, беги!'
    }

    console.log(friend) // ReferenceError
}
run()


Область видимости блока if вложена в область видимости функции run ().

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

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

pix8xo2liy7a5mpnyaiayj7ybx4.jpeg

Что насчет доступности переменных? Нужно запомнить простое правило:

Переменные из внешней области видимости доступны во внутренней области.

Поэтому переменная message доступна внутри блока if.

6. Глобальная область видимости


Глобальная область видимости является самой внешней областью. Она доступна для любой внутренней или локальной области видимости. В браузере глобальной является область видимости, создаваемая при загрузке JavaScript-файла, указанного в атрибуте src тега script: