Книга: JavaScript. Подробное руководство, 6-е издание

3.10.1. Область видимости функции и подъем

3.10.1. Область видимости функции и подъем

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

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

function test(o) {
  var і = 0; // і определена в теле всей функции
  if (typeof о == "object") {
    var j = 0; // j определена везде, не только в блоке
    for(var k=0; k < 10; k++) { // к определена везде, не только в цикле
      console.log(k); // выведет числа от 0 до 9
    }
    console.log(k); // к по-прежнему определена: выведет 10
  }
  console.log(j); // j определена, но может быть неинициализирована
}

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

var scope = "global";
function f() {
  console.log(scope); // Выведет "undefined", а не "global"
  var scope = "local"; // Инициализируется здесь, а определена везде
  console.log(scope); // Выведет "local"
}

Можно было бы подумать, что первая инструкция внутри функции должна вывести слово «global», потому что инструкция var с объявлением локальной переменной еще не была выполнена. Однако вследствие действия правил области видимости функции выводится совсем другое значение. Локальная переменная определена во всем теле функции, а это означает, что глобальная переменная с тем же именем оказывается скрытой для всей функции. Хотя локальная переменная определена во всем теле функции, она остается неинициализированной до выполнения инструкции var. То есть функция выше эквивалентна реализации, приведенной ниже, в которой объявление переменной «поднято» в начало функции, а инициализация переменной выполняется там же, где и раньше:

function f() {
  var scope; // Объявление локальной переменной в начале функции
  console.log(scope); // Здесь она доступна, но имеет значение "undefined"
  scope = "local";  // Здесь она инициализируется и получает свое значение
  console.log(scope); // А здесь она имеет ожидаемое значение
}

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

Оглавление книги


Генерация: 2.147. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз