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

В чем разница между областью видимости Let и Var?

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

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Разница между областью видимости Let и Var

В JavaScript существуют три способа объявления переменных: var, let и const. Их ключевые различия заключаются в области видимости (scope), переподъёме (hoisting) и переприсваивании. Это одна из фундаментальных концепций, которую должен понимать каждый JavaScript разработчик.

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

var — функциональная область видимости (function scope)

function example() {
  if (true) {
    var x = 1;
  }
  console.log(x); // 1 - видима за пределами блока if
}

example();

let — блочная область видимости (block scope)

function example() {
  if (true) {
    let y = 2;
  }
  console.log(y); // ReferenceError: y is not defined
}

example();

Практические различия

1. Цикл for

// Проблема с var
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i); // выведет 3, 3, 3
  }, 100);
}

// Решение с let
for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i); // выведет 0, 1, 2 (как ожидается)
  }, 100);
}

Почему так происходит? При использовании var переменная i одна на весь цикл. К моменту выполнения setTimeout цикл закончился, и i = 3. С let для каждой итерации создается новая переменная.

2. Функциональные выражения

// var - функциональная область видимости
for (var i = 0; i < 3; i++) {
  (function(index) {
    setTimeout(() => {
      console.log(index); // 0, 1, 2
    }, 100);
  })(i);
}

// let - более чистое решение
for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i); // 0, 1, 2
  }, 100);
}

Подъем переменных (Hoisting)

var - подъимается и инициализируется значением undefined

console.log(x); // undefined (не ошибка!)
var x = 5;
console.log(x); // 5

// Интерпретируется как:
var x;
console.log(x); // undefined
x = 5;
console.log(x); // 5

let - подъимается, но не инициализируется (Temporal Dead Zone)

console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 5;

// let находится в "Temporal Dead Zone" от начала блока до объявления

Переприсваивание и переобъявление

var - можно переобъявлять и переприсваивать

var a = 1;
var a = 2; // ОК
a = 3;     // ОК
console.log(a); // 3

let - можно только переприсваивать, не переобъявлять

let b = 1;
let b = 2; // SyntaxError: Identifier 'b' has already been declared
b = 3;     // ОК
console.log(b); // 3

const - нельзя ни переобъявлять, ни переприсваивать

const c = 1;
const c = 2; // SyntaxError
c = 3;       // TypeError: Assignment to constant variable

Утечки в глобальную область

// var может случайно загрязнить глобальный scope
function test() {
  var globalVar = 'я в глобалке'; // попадает в window
}
test();
console.log(window.globalVar); // 'я в глобалке'

// let не загрязняет глобальный scope
function test2() {
  let localVar = 'я локальная';
}
test2();
console.log(window.localVar); // undefined

Замыкания (Closures)

Различия проявляются и в замыканиях:

// var - все замыкания ссылаются на одну переменную
const functions1 = [];
for (var i = 0; i < 3; i++) {
  functions1.push(() => i);
}
console.log(functions1.map(f => f())); // [3, 3, 3]

// let - каждое замыкание имеет свою переменную
const functions2 = [];
for (let i = 0; i < 3; i++) {
  functions2.push(() => i);
}
console.log(functions2.map(f => f())); // [0, 1, 2]

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

if (true) {
  var x = 1;
  let y = 2;
  const z = 3;
}

console.log(x); // 1
console.log(y); // ReferenceError
console.log(z); // ReferenceError

Вложенные блоки

{
  var a = 1;
  let b = 2;
}

{
  console.log(a); // 1 (видима)
  console.log(b); // ReferenceError (не видима)
  var a = 10; // переиспользуется одна переменная
  let b = 20; // новая переменная в новом блоке
}

Сравнительная таблица

Признакvarletconst
Область видимостиФункцияБлокБлок
HoistingundefinedReferenceErrorReferenceError
ПереприсваиваниеДаДаНет
ПереобъявлениеДаНетНет
Временная мертвая зонаНетДаДа
Загрязняет globalДаНетНет

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

  1. Не используй var в современном коде — он устаревший и опасный
  2. Используй let для переменных, которые будут переприсваиваться
  3. Используй const по умолчанию для всех переменных
  4. Переходи на const/let если работаешь в старом коде с var
// Хорошо
const config = { ... };
let counter = 0;

// Плохо
var config = { ... };
var counter = 0;

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

В чем разница между областью видимости Let и Var? | PrepBro