← Назад к вопросам

Какие знаешь области видимости в JS?

1.2 Junior🔥 241 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI20 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Области видимости (Scope) в JavaScript

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

Основные типы областей видимости

1. Глобальная область видимости (Global Scope)

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

// Глобальная переменная
var globalVar = 'I am global';
let globalLet = 'Also global';
const globalConst = 'Const global';

function testGlobal() {
  console.log(globalVar);   // 'I am global'
  console.log(globalLet);   // 'Also global'
  console.log(globalConst); // 'Const global'
}

console.log(globalVar);   // 'I am global'
testGlobal();

В браузерах глобальные переменные добавляются на объект window:

var x = 5;
console.log(window.x);  // 5

let y = 10;
console.log(window.y);  // undefined (let не добавляется на window)

2. Функциональная область видимости (Function Scope)

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

function outer() {
  var functionVar = 'I am inside function';
  
  console.log(functionVar);  // 'I am inside function'
  
  function inner() {
    console.log(functionVar);  // 'I am inside function' - доступна!
  }
  
  inner();
}

console.log(functionVar);  // ReferenceError: functionVar is not defined

3. Блочная область видимости (Block Scope)

Переменные, объявленные с помощью let и const внутри блока (if, for, while, {}) доступны только внутри этого блока.

// var - НЕ имеет блочной области видимости
if (true) {
  var varX = 'var';
}
console.log(varX);  // 'var' - ДОСТУПНА вне блока!

// let - ИМЕЕТ блочную область видимости
if (true) {
  let letX = 'let';
}
console.log(letX);  // ReferenceError: letX is not defined

// const - ИМЕЕТ блочную область видимости
if (true) {
  const constX = 'const';
}
console.log(constX);  // ReferenceError: constX is not defined

Пример с циклом:

// ❌ var - проблема с областью видимости
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log('var:', i), 100);
}
// Выведет: var: 3, var: 3, var: 3

// ✅ let - правильное поведение
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log('let:', i), 100);
}
// Выведет: let: 0, let: 1, let: 2

4. Лексическая область видимости (Lexical Scope)

Функция имеет доступ к переменным из области видимости, где она была определена, а не где она была вызвана.

const greeting = 'Hello';

function outer() {
  const greeting = 'Hi from outer';
  
  function inner() {
    console.log(greeting);  // Использует greeting из outer, не из глобального scope
  }
  
  return inner;
}

const innerFunc = outer();
innerFunc();  // 'Hi from outer'

// Переменная greeting из глобального scope не переопределит локальную
console.log(greeting);  // 'Hello'

5. Область видимости Замыкания (Closure Scope)

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

function createCounter() {
  let count = 0;  // Переменная в замыкании
  
  return {
    increment() {
      return ++count;
    },
    decrement() {
      return --count;
    },
    getCount() {
      return count;
    }
  };
}

const counter = createCounter();
console.log(counter.increment());  // 1
console.log(counter.increment());  // 2
console.log(counter.decrement());  // 1
console.log(counter.getCount());   // 1

// count остается приватной - недоступна напрямую
console.log(counter.count);  // undefined

Еще пример с замыканиями:

function createMultiplier(multiplier) {
  return function(number) {
    return number * multiplier;
  };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

console.log(double(5));   // 10
console.log(triple(5));   // 15

// Каждая функция имеет свое замыкание с своим multiplier

Цепочка областей видимости (Scope Chain)

JavaScript ищет переменные по цепочке от внутреннего scope до глобального:

const global = 'global';

function level1() {
  const local1 = 'level1';
  
  function level2() {
    const local2 = 'level2';
    
    function level3() {
      const local3 = 'level3';
      
      console.log(local3);  // 'level3' - найдена в level3
      console.log(local2);  // 'level2' - найдена в level2
      console.log(local1);  // 'level1' - найдена в level1
      console.log(global);  // 'global' - найдена в global
    }
    
    level3();
  }
  
  level2();
}

level1();

Затемнение областей видимости (Shadowing)

Когда переменная во внутреннем scope имеет то же имя, что и во внешнем scope, она "затемняет" внешнюю переменную.

const x = 'global';

function outer() {
  const x = 'outer';
  
  function inner() {
    const x = 'inner';
    console.log(x);  // 'inner' - затемняет outer и global
  }
  
  inner();
  console.log(x);  // 'outer' - затемняет global
}

outer();
console.log(x);  // 'global'

Отличия var, let, const

// var - функциональная область видимости, hoisting с инициализацией undefined
function testVar() {
  console.log(varX);  // undefined (hoisting)
  var varX = 5;
  console.log(varX);  // 5
}

// let - блочная область видимости, hoisting БЕЗ инициализации (Temporal Dead Zone)
function testLet() {
  console.log(letX);  // ReferenceError: Cannot access 'letX' before initialization
  let letX = 5;
}

// const - блочная область видимости, hoisting БЕЗ инициализации, не переназначается
function testConst() {
  const constX = 5;
  constX = 10;  // TypeError: Assignment to constant variable
}

Лучшие практики

  1. Используй let и const вместо var - они имеют правильную блочную область видимости
  2. Предпочитай const по умолчанию - это предотвращает случайные переназначения
  3. Используй let только когда нужно переназначение - это явно показывает намерение
  4. Избегай глобальных переменных - они загрязняют глобальный scope
  5. Используй замыкания для инкапсуляции - создавай приватные переменные
  6. Помни о цепочке областей видимости - ищи переменные от внутреннего scope к глобальному

Пример: Современный подход

// ✅ Хорошо - понятные области видимости
const API_URL = 'https://api.example.com';  // global const

function createUserService() {
  const timeout = 5000;  // замкнутая переменная
  
  return {
    async fetchUser(id: string) {
      const response = await fetch(\`\${API_URL}/users/\${id}\`);
      const data = await response.json();
      return data;
    },
    
    async updateUser(id: string, updates: any) {
      const url = \`\${API_URL}/users/\${id}\`;  // блочная область видимости
      return fetch(url, { method: 'PUT', body: JSON.stringify(updates) });
    }
  };
}

const userService = createUserService();

Понимание областей видимости критично для написания надежного и предсказуемого кода на JavaScript.

Какие знаешь области видимости в JS? | PrepBro