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

В чем разница между var и let?

1.3 Junior🔥 221 комментариев
#Node.js и JavaScript

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

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

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

Разница между var и let в JavaScript

Это ключевой вопрос, который показывает понимание JavaScript. Разница критична для написания правильного кода.

Основная разница: Scope (область видимости)

var — Function Scope

function example() {
  if (true) {
    var x = 1;
  }
  console.log(x); // 1 (видна!)
}

example();
var видна во всей функции, независимо от блока.

let — Block Scope

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

example();
let видна только в блоке {}, где определена.

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

var: Function-scoped

function test() {
  if (true) {
    var x = 1;
  }
  
  for (var i = 0; i < 3; i++) {
    // i видна здесь
  }
  
  console.log(x); // 1 (хорошо видна)
  console.log(i); // 3 (последнее значение!)
}

Это приводит к ошибкам:

for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i); // 3, 3, 3 (все одно значение!)
  }, 100);
}

let: Block-scoped

for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i); // 0, 1, 2 (каждая своя!)
  }, 100);
}
let создаёт новую переменную в каждой итерации.

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

var: Поднимается и инициализируется как undefined

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

// JavaScript внутренне делает так:
// var x;
// console.log(x); // undefined
// x = 5;
// console.log(x);

Это очень запутанное поведение!

let: Поднимается но НЕ инициализируется (Temporal Dead Zone)

console.log(y); // ReferenceError: y is not defined
let y = 5;

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

Это безопаснее, потому что ошибка явная.

3. Re-declaration (Переобъявление)

var: Можно переобъявить

var x = 1;
var x = 2; // OK
console.log(x); // 2

// Это ведёт к багам
function setupUser(userId) {
  var data = fetchUser(userId);
  // ... 100 строк кода ...
  var data = calculateStats(userId); // Упс, перезаписали!
  return data;
}

let: Нельзя переобъявить в одном scope

let y = 1;
let y = 2; // SyntaxError: Identifier 'y' has already been declared

// Но можно в разных scopes
let y = 1;
if (true) {
  let y = 2; // OK, другой scope
}

Это защищает от ошибок.

4. Global Object property (Глобальный объект)

var: Создаёт свойство window/global

// В браузере
var x = 5;
console.log(window.x); // 5

// В Node.js
var y = 10;
console.log(global.y); // 10

Это может конфликтовать с другими скриптами.

let: Не создаёт свойство

let x = 5;
console.log(window.x); // undefined

let y = 10;
console.log(global.y); // undefined

Безопаснее в глобальном масштабе.

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

Аспектvarlet
ScopeFunctionBlock
HoistingundefinedReferenceError (TDZ)
Re-declareМожноНельзя
Global propwindow.xundefined
ПереопределениеОпасноБезопасно
Когда использоватьРедкоВсегда

Практические примеры ошибок с var

Ошибка 1: Closure в цикле

// Плохо (var)
const callbacks = [];
for (var i = 0; i < 3; i++) {
  callbacks.push(() => console.log(i));
}
callbacks.forEach(cb => cb()); // 3, 3, 3

// Хорошо (let)
const callbacks = [];
for (let i = 0; i < 3; i++) {
  callbacks.push(() => console.log(i));
}
callbacks.forEach(cb => cb()); // 0, 1, 2

Ошибка 2: Случайное переобъявление

function processData() {
  var result = "first";
  
  if (someCondition) {
    var result = "second"; // Упс, перезаписали!
  }
  
  console.log(result); // Какое значение?
}

// С let:
function processData() {
  let result = "first";
  
  if (someCondition) {
    let result = "second"; // Другой scope, ошибки нет
  }
  
  console.log(result); // Гарантированно "first"
}

Ошибка 3: Hoisting

// Плохо (var)
console.log(typeof name); // string (из-за hoisting)
var name = "John";

// Хорошо (let)
console.log(typeof name); // ReferenceError (явная ошибка)
let name = "John";

Есть ли причины использовать var?

НЕТ практических причин использовать var в современном коде.

var — наследие из старого JavaScript (ES5 и раньше). С ES6 (2015) появился let и const, и они лучше.

const — третий вариант

Особый случай: const (тоже block-scoped)

const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable

// const != неизменяемое значение
// const = неизменяемая ссылка
const arr = [1, 2, 3];
arr.push(4); // OK, меняем содержимое
arr = []; // TypeError, меняем ссылку

Best Practice

// 1. Используй const по умолчанию
const name = "John";

// 2. Если нужно переприсваивать — используй let
let count = 0;
count++;

// 3. НИКОГДА не используй var
// var x = 5; // ❌

// TypeScript помогает
// tsconfig.json: "noImplicitAny": true

В Node.js и TypeScript

Модерный стек (TypeScript + Node.js 14+) использует только let/const:

// Modern code
const config = { port: 3000 };
let counter = 0;

function increment() {
  counter++; // Only if truly necessary
}

// Никогда не видишь var

Заключение

var — это ошибка дизайна JavaScript, которую нельзя полностью удалить для обратной совместимости.

let и const исправляют проблемы var:

  • Block scope вместо function scope
  • Нет странного hoisting
  • Нельзя переобъявлять
  • Не загрязняют глобальный объект

В 2025 году разработчик, использующий var, показывает либо незнание JavaScript, либо поддержку очень старого кода. Используй let и const всегда.

В чем разница между var и let? | PrepBro