const, let, var в TypeScript
Разбираемся, чем отличаются три способа объявления переменных, почему var ушёл в прошлое и как правильно выбирать между const и let в повседневной работе.
Что такое переменные — аналогия с коробками
Представьте, что вы храните вещи в коробках. Каждая коробка имеет:
- Надпись на коробке (имя переменной) — чтобы вы знали, что внутри
- Содержимое (значение переменной) — то, что лежит внутри коробки
- Скрепку или замок (const/let/var) — определяет, можно ли менять содержимое и где эта коробка доступна
В программировании переменная — это именованный контейнер для хранения данных. Вы кладёте туда значение и потом можете его использовать, изменять или передавать дальше.
Простая аналогия: Вы приходите в отель и просите номер. На ресепшневам ключ от номера 101. Этот ключ — имя переменной. Номер 101 — это адрес в памяти компьютера. А вещи, которые вы кладёте в шкаф — это значение переменной.
В JavaScript и TypeScript есть три способа создать такую «коробку»:
var
Старый способ. Работает, но лучше не использовать.
let
Современный. Коробку можно перекладывать.
const
Самый популярный. Коробку нельзя перекладывать.
Давайте разберём каждый из них подробно, с примерами кода.
// Пример: три способа объявить переменную
var имяКоробки1 = "яблоко"; // старый способ
let имяКоробки2 = "банан"; // современный, можно менять
const имяКоробки3 = "апельсин"; // современный, нельзя менять
console.log(имяКоробки1); // яблоко
console.log(имяКоробки2); // банан
console.log(имяКоробки3); // апельсин
var — старый способ объявления переменных
var — это первый способ объявления переменных, который появился в JavaScript. Он существовал ещё в 1995 году, когда Брендан Эйх создал язык за 10 дней. До появления let и const в 2015 году, var был единственным вариантом.
⚠️ Важно: В современном TypeScript и JavaScript использование var считается плохой практикой. Однако вы обязательно встретите его в старых проектах, и важно понимать, как он работает.
Область видимости (scope) у var
Главная проблема var — это функциональная область видимости (function scope). Это значит, что переменная, объявленная внутри функции, видна везде внутри этой функции, независимо от того, в каком блоке (if, for, while) она была создана.
// Пример: var игнорирует блоки {}
function покажиОбласть() {
if (true) {
var сообщение = "Привет!";
}
// Здесь переменная всё ещё видна!
// Это неожиданно и опасно
console.log(сообщение); // "Привет!" — работает!
}
покажиОбласть();
Заметье: переменная сообщение была объявлена внутри блока if, но доступна за его пределами. Это работает потому, что var не знает про блоки — он знает только про функции.
💡 Аналогия: Представьте, что у вас есть огромный склад (функция). Вы поставили коробку (переменную) в одном углу склада, за ширмой. Но на складе нет стен — ширма ничего не разделяет. Коробка доступна отовсюду на этом складе.
Поднятие (Hoisting) — «магия» var
У var есть ещё одна странная особенность — поднятие (hoisting). JavaScript «поднимает» все объявления переменных с var в самое начало функции. Это значит, что вы можете использовать переменную до того, как её объявили!
// Пример: Hoisting — переменная "поднимается"
function загадка() {
// Используем переменную ДО объявления!
console.log(загадочная); // undefined (не ошибка!)
var загадочная = "Найди меня";
console.log(загадочная); // "Найди меня"
}
загадка();
Что здесь произошло? JavaScript видит var загадочная и «поднимает» объявление в начало функции. Но присваивание остаётся на месте. Поэтому первая строка выводит undefined — переменная существует, но в неё ещё ничего не положили.
// Что видит JavaScript (упрощённо):
function загадка() {
var загадочная; // ← поднялось сюда (объявление)
console.log(загадочная); // undefined
загадочная = "Найди меня"; // ← присваивание осталось тут
console.log(загадочная); // "Найди меня"
}
var в циклах — классическая ловушка
Самая famous проблема var — это поведение в циклах. Посмотрите на этот пример:
// Проблема: все кнопки выведут "Кнопка 3"
for (var i = 1; i <= 3; i++) {
console.log("Создаю кнопку" + i);
// Представим, что мы создаём обработчик клика
// setTimeout запустится ПОЗЖЕ, когда цикл уже закончится
setTimeout(function() {
console.log("Нажата кнопка" + i);
}, 100);
}
// Результат:
// "Нажата кнопка4"
// "Нажата кнопка4"
// "Нажата кнопка4"
Все три обработчика выводят "Нажата кнопка4", потому что var i — это одна-единственная переменная, и к моменту, когда срабатывают таймеры, цикл уже завершился и i равно 4.
Переобъявление var
var позволяет объявлять одну и ту же переменную несколько раз без ошибки. Это может приводить к трудноуловимым багам:
// var позволяет повторное объявление
var число = 10;
var число = 20; // Нет ошибки!
var число = 30; // Тоже нет ошибки!
console.log(число); // 30
// Если забыли, что уже объявляли — получите баг
Глобальная область var
Если объявить var вне любой функции, переменная становится глобальной — она доступна везде в вашей программе и даже попадает в объект window в браузере:
// Глобальная var — опасная территория
var глобальнаяПеременная = "Я доступна везде";
function мояФункция() {
console.log(глобальнаяПеременная); // "Я доступна везде"
}
// В браузере это даже попадёт в window:
// window.глобальнаяПеременная === "Я доступна везде"
⚠️ Зачем тогда вообще знать var? Вы встретите его в: (1) старых кодовых базах, написанных до 2015 года; (2) автоматически сгенерированном коде; (3) учебных материалах, которые не обновлялись. Умение читать var — обязательный навык.
Полный пример с var
// Демонстрация всех проблем var
function демонстрация() {
console.log( значение); // undefined (hoisting)
var значение = "Привет";
if (true) {
var внутренняя = "Я внутри if";
}
// Доступна вне if!
console.log(внутренняя); // "Я внутри if"
for (var счётчик = 0; счётчик < 3; счётчик++) {
// пусто
}
// счётчик доступен вне цикла!
console.log(счётчик); // 3
// Переобъявление без ошибки
var значение = "Новое значение";
console.log(значение); // "Новое значение"
}
демонстрация();
let — современный способ объявления переменных
Ключевое слово let появилось в стандарте ES2015 (ES6) и решает все проблемы var. Главное отличие — блочная область видимости (block scope).
Блочная область видимости
Переменная, объявленная через let, видна только внутри того блока { }, где она была объявлена:
// let уважает блоки {}
function покажиОбласть() {
if (true) {
let сообщение = "Привет!";
}
// ОШИБКА! переменная не видна за пределами блока
console.log(сообщение); // ReferenceError!
}
Это предсказуемое и безопасное поведение. Вы точно знаете, где доступна ваша переменная.
✅ Аналогия: Если var — это склад без стен, то let — это комната с дверью. Вы кладёте коробку в комнату — она доступна только внутри этой комнаты. Выйдите за дверь — коробку не видно.
let в циклах — правильное поведение
Исправим знаменитую проблему с кнопками, заменив var на let:
// Исправлено: каждая итерация — своя переменная
for (let i = 1; i <= 3; i++) {
setTimeout(function() {
console.log("Нажата кнопка" + i);
}, 100);
}
// Результат:
// "Нажата кнопка1"
// "Нажата кнопка2"
// "Нажата кнопка3"
С let каждая итерация цикла создаёт новую переменную i со своим значением. Поэтому каждый обработчик запоминает «своё» значение.
Нет поднятия (Hoisting) для значений
В отличие от var, переменная let находится в так называемой «временной мертвой зоне» (temporal dead zone, TDZ) от момента начала блока до момента объявления. Попытка использовать её до объявления вызывает ошибку:
// let: ошибка при использовании до объявления
function тест() {
console.log(значение); // ReferenceError!
// Cannot access 'значение' before initialization
let значение = 42;
}
// Это ХОРОШАЯ ошибка! Она говорит вам:
// "Вы пытаетесь использовать переменную до того, как она создана"
💡 Почему TDZ — это хорошо? Ошибка сразу говорит вам о проблеме. С var вы бы получили undefined — тихий баг, который может проявиться только при определённых условиях.
Нет переобъявления
let не позволяет объявлять переменную дважды в одной области видимости:
// let: ошибка при повторном объявлении
let число = 10;
let число = 20; // SyntaxError!
// Identifier 'число' has already been declared
// Но можно переиспользовать в разных блоках:
let число = 10;
if (true) {
let число = 20; // OK — это другой блок!
console.log(число); // 20
}
console.log(число); // 10 —.outer block value
let не создаёт глобальных переменных
В отличие от var, let за пределами функции не создаёт свойство на window:
var глобальнаяVar = "Я в window";
let глобальнаяLet = "Меня нет в window";
// В браузере:
console.log(window.глобальнаяVar); // "Я в window"
console.log(window.глобальнаяLet); // undefined
Примеры использования let
// Пример 1: Счётчик
let счётчик = 0;
счётчик = счётчик + 1; // 1
счётчик = счётчик + 1; // 2
счётчик += 1; // 3
// Пример 2: Временное значение
let временныйРезультат;
if (счётчик > 2) {
временныйРезультат = счётчик * 10;
}
console.log(временныйРезультат); // 30
// Пример 3: Изменение строки
let приветствие = "Привет";
приветствие = приветствие + ", Мир!";
console.log(приветствие); // "Привет, Мир!"
// Пример 4: Переключатель
let включен = true;
включен = !включен; // false
включен = !включен; // true
const — неизменяемая константа
Ключевое слово const (от англ. constant — константа) создаёт переменную, которую нельзя переназначить. Это значит, что после присваивания вы не можете положить туда другое значение.
✅ Рекомендация: Используйте const по умолчанию. Меняйте на let только когда точно знаете, что значение будет меняться. Это правило называют «const by default».
Базовые примеры const
// const: значение нельзя переназначить
const имя = "Алексей";
const возраст = 25;
const активен = true;
console.log(имя); // "Алексей"
console.log(возраст); // 25
console.log(активен); // true
// Попытка переназначить — ОШИБКА:
имя = "Мария"; // TypeError!
// Assignment to constant variable.
возраст = 26; // TypeError!
активен = false; // TypeError!
Что можно менять в const?
Вот момент, который путает многих новичков: const запрещает переназначение переменной, но не запрещает менять содержимое объектов и массивов!
// const с массивом
const фрукты = ["яблоко", "банан", "апельсин"];
// Можно менять элементы:
фрукты[0] = "груша"; // OK!
фрукты.push("манго"); // OK!
фрукты.pop(); // OK!
фрукты.splice(1, 1); // OK!
console.log(фрукты); // ["груша", "апельсин", "манго"]
// Но заменить весь массив НЕЛЬЗЯ:
фрукты = ["дыня"]; // TypeError!
// const с объектом
const пользователь = {
имя: "Алексей",
возраст: 25
};
// Можно менять свойства:
пользователь.имя = "Мария"; // OK!
пользователь.возраст = 30; // OK!
пользователь.email = "a@b.com"; // OK — добавили новое свойство
delete пользователь.возраст; // OK — удалили свойство
console.log(пользователь);
// Но заменить весь объект НЕЛЬЗЯ:
пользователь = { имя: "Другой" }; // TypeError!
⚠️ Важно понимать: const защищает ссылку, а не данные. Представьте коробку с замком: замок не даёт подставить другую коробку, но вы можете свободно перекладывать вещи внутри коробки.
Blrozen (замороженные) объекты
Если вы хотите сделать объект действительно неизменяемым (нельзя ни переназначить, ни менять свойства), используйте Object.freeze():
// Object.freeze() — полная неизменяемость
const конфиг = Object.freeze({
хост: "localhost",
порт: 3000,
debug: false
});
// Попытки изменить — молча игнорируются:
конфиг.порт = 8080; // Не ошибка, но не работает!
конфиг.новое = "значение"; // Тоже не работает!
console.log(конфиг.порт); // 3000 (не изменилось)
console.log(конфиг.новое); // undefined (не добавилось)
const и блочная область видимости
Как и let, const имеет блочную область видимости:
// const тоже работает с блоками
if (true) {
const секрет = "Тайное слово";
console.log(секрет); // "Тайное слово"
}
//console.log(секрет); // ReferenceError!
// const не виден за пределами блока
// Итого: const = let, но без переназначения
const в циклах
Нельзя использовать const для переменной счётчика, потому что она переназначается:
// const в for-цикле — ОШИБКА
for (const i = 0; i < 5; i++) {
console.log(i);
}
// TypeError: Assignment to constant variable.
// Потому что i++ пытается переназначить i
// Правильно — используйте let:
for (let i = 0; i < 5; i++) {
console.log(i); // 0, 1, 2, 3, 4
}
// Или for...of с const:
const числа = [10, 20, 30];
for (const число of числа) {
console.log(число); // 10, 20, 30
}
Правила именования переменных в TypeScript
TypeScript (и JavaScript) имеют несколько правил для имён переменных. Некоторые из них — строгие ограничения языка, другие — общепринятые соглашения.
Строгие правила (язык не разрешит нарушить)
// ✅ ИМЕНА МОГУТ СОДЕРЖАТЬ:
let переменная = 1; // буквы
let _приватная = 2; // подчёркивание
let $ dollars = 3; // знак доллара
let var1 = 4; // цифры (не первым символом!)
let имяФайла = "test.ts"; // смешанный регистр
let ALL_CAPS = 100; // верхний регистр
// ❌ ИМЕНА НЕ МОГУТ НАЧИНАТЬСЯ С ЦИФРЫ:
// let 1переменная = 10; // SyntaxError!
// ❌ ИМЕНА НЕ МОГУТ СОДЕРЖАТЬ ПРОБЕЛЫ ИДЕФИСЫ:
// let имя файла = "test"; // SyntaxError!
// let my-var = 10; // SyntaxError!
// ❌ ИМЕНА НЕ МОГУТ БЫТЬ ЗАРЕЗЕРВИРОВАННЫМИ СЛОВАМИ:
// let let = 10; // SyntaxError!
// let const = 10; // SyntaxError!
// let function = 10; // SyntaxError!
// let if = 10; // SyntaxError!
Соглашения об именовании (рекомендации)
✅ Рекомендуется
camelCaseдля переменных и функций- Осмысленные имена:
имяПользователя - Булевы:
естьАктивность,загружен - Глаголы для функций:
получитьДанные()
❌ Избегайте
- Однобуквенные имена:
x,a,tmp - Сокращения:
usr,cnt - Противоречивые имена:
числодля строки - Слишком длинные:
результатВычисленияНДССУчётомСкидки
Примеры хороших и плохих имён
// ❌ Плохие имена:
let a = 25;
let data = "Привет";
let x = true;
let tmp = [1, 2, 3];
// ✅ Хорошие имена:
const возрастПользователя = 25;
const приветствие = "Привет";
const активен = true;
const числаФибоначчи = [1, 2, 3];
// ✅ Булевы переменные — с префиксом:
const естьОшибки = false;
const загружен = true;
const можноОтправить = true;
const видитПароль = false;
// ✅ Функции — с глаголом:
// function получитьПользователя() { ... }
// function отправитьФорму() { ... }
// function проверитьВалидность() { ... }
Рекомендации: когда использовать const, let, var
Существует чёткий алгоритм выбора между тремя способами объявления. Следуйте этому правилу, и ваши код будет безопасным и читаемым.
Алгоритм выбора:
Начните с const — если значение не будет меняться
Переключитесь на let — если значение будет меняться
Забудьте о var — используйте только если поддерживаете старый код
Примеры правильного выбора
// ✅ const — для данных, которые не меняются
const API_URL = "https://api.example.com";
const MAX_ПОПЫТОК = 3;
const ПОЛ = "мужской";
const датаРегистрации = new Date();
const имяФайла = "report.pdf";
const ПУСТОЙ_МАССИВ = [];
const настройки = { язык: "ru", тема: "тёмная" };
// ✅ let — для данных, которые будут меняться
let счётчик = 0;
let текущийЭтап = "загрузка";
let сумма = 0;
let результат;
let текст = "";
let массивЧисел = [1, 2, 3];
// ❌ var — НЕ используйте в новом коде
// var стараяПеременная = "устарело";
Типичные паттерны
// Паттерн 1: Конфигурация — всегда const
const конфиг = {
базовыйURL: "https://api.example.com",
таймаут: 5000,
повторы: 3
};
// Паттерн 2: Счётчики и аккумуляторы — let
let общаяСумма = 0;
let количествоОшибок = 0;
for (let цена of [100, 200, 150]) {
общаяСумма += цена;
}
console.log(общаяСумма); // 450
// Паттерн 3: Результат вычислений — let или const
const результат = посчитать(10, 20); // const если одна операция
let итог;
if (условие1) {
итог = значение1;
} else {
итог = значение2;
}
// Паттерн 4: Переменные цикла — let
for (let индекс = 0; индекс < массив.length; индекс++) {
// обработка
}
for (const элемент of массив) {
// обработка — const тут ок, т.к. не переназначаем
}
Ошибки новичков с переменными
Давайте разберём самые частые ошибки, которые допускают начинающие программисты при работе с переменными. Зная их заранее, вы сможете избежать многих часов отладки.
Ошибка 1: Использование переменной до объявления
// ❌ Ошибка новичка
console.log(имя); // ReferenceError!
let имя = "Мария";
// ✅ Правильно: сначала объявление, потом использование
let имя = "Мария";
console.log(имя); // "Мария"
Ошибка 2: Путаница = и ===
// = — присваивание
let число = 10; // кладём 10 в переменную
// === — сравнение
if (число === 10) {
console.log("Равно!");
}
// ❌ Частая ошибка:
if (число = 10) { // Это ПРИСВАИВАНИЕ, не сравнение!
console.log("Всегда true!"); // 10 — truthy
}
Ошибка 3: Попытка менять const
// ❌ Ошибка новичка
const число = 10;
число = 20; // TypeError!
// ✅ Решение: используйте let если значение будет меняться
let число = 10;
число = 20; // OK
Ошибка 4: Забыли объявить переменную
// ❌ Ошибка новичка: случайно создали глобальную переменную
function подсчитать() {
for (i = 0; i < 10; i++) {
// забыли let/const/var!
}
console.log(i); // 10 — глобальная переменная!
}
// ✅ Правильно:
function подсчитать() {
for (let i = 0; i < 10; i++) {
// ok
}
// console.log(i); // ReferenceError — переменная не видна
}
Ошибка 5: const не значит «неизменяемый объект»
// Многие новички думают, что const делает объект "только для чтения"
const юзер = { имя: "Аня" };
// Это РАБОТАЕТ (и это неожиданно для новичков):
юзер.имя = "Маша"; // OK — меняем свойство
юзер.возраст = 20; // OK — добавляем свойство
console.log(юзер); // {имя: "Маша", возраст: 20}
// Только переназначение запрещено:
юзер = {}; // TypeError!
Ошибка 6: Неправильная работа с временными блоками
// Ошибка: ожидаем, что let из одного блока виден в другом
let результат = "по умолчанию";
if (true) {
let результат = "из блока"; // Это ДРУГАЯ переменная!
console.log(результат); // "из блока"
}
console.log(результат); // "по умолчанию" — внешняя не изменилась!
// ✅ Если хотите менять внешнюю переменную:
let результат = "по умолчанию";
if (true) {
результат = "из блока"; // Без let — меняем внешнюю
console.log(результат); // "из блока"
}
console.log(результат); // "из блока" — внешняя изменилась
Множественное объявление переменных
TypeScript позволяет объявлять несколько переменных в одной строке, разделяя их запятой. Однако это часто снижает читаемость кода.
// Множественное объявление
let a, b, c; // три переменные без значений
let x = 1, y = 2, z = 3; // три переменные с начальными значениями
// ❌ НЕЛЬЗЯ делать так с const:
// const a = 1, b = 2, c = 3;
// const a, b, c; // SyntaxError!
// ✅ const — только с начальными значениями:
const ширина = 100, высота = 200; // OK
// ❌ const без значения — ошибка:
// const x, y; // SyntaxError: Missing initializer
console.log(x, y, z); // 1 2 3
💡 Рекомендация: Объявляйте одну переменную на строку. Это упрощает чтение кода, упрощает diff в git (каждое изменение — на отдельной строке) и позволяет TypeScript лучше выводить типы.
Деструктуризация — элегантный способ
Вместо множественного объявления используйте деструктуризацию — она позволяет разложить массив или объект на отдельные переменные:
// Деструктуризация массива
const координаты = [10, 20, 30];
const [x, y, z] = координаты;
console.log(x, y, z); // 10 20 30
// Деструктуризация объекта
const пользователь = { имя: "Катя", возраст: 22, город: "Москва" };
const { имя, возраст } = пользователь;
console.log(имя, возраст); // "Катя" 22
// С переименованием:
const { имя: имяЮзера, город: местоЖительства } = пользователь;
console.log(имяЮзера, местоЖительства); // "Катя" "Москва"
// С значением по умолчанию:
const { имя, email = "не указан" } = пользователь;
console.log(email); // "не указан"
Неинициализированные переменные
Бывают ситуации, когда переменная объявлена, но значение ещё не присвоено. Поведение зависит от способа объявления.
// let и var без начального значения
let имя;
var адрес;
console.log(имя); // undefined
console.log(адрес); // undefined
// ✅ const требует обязательного начального значения!
// const секрет; // SyntaxError!
const секрет = undefined; // OK, если нужно
undefined vs null
// undefined — "значение ещё нет"
let результат;
console.log(результат); // undefined
// null — "значение пустое, намеренно"
let результат2 = null;
console.log(результат2); // null
// Разница на практике:
let найден; // undefined — ещё не искали
let найден2 = null; // null — искали, но не нашли
// TypeScript предупредит вас о возможном undefined:
let число: number;
// console.log(число + 1); // Ошибка TypeScript!
// Object is possibly 'undefined'
✅ TypeScript спасает: Если вы попытаетесь использовать неинициализированную переменную, TypeScript выдаст предупреждение. Это одна из сильных сторон TypeScript — он ловит такие ошибки на этапе написания кода.
Типичные сценарии с неинициализированными переменными
// Сценарий 1: Промежуточный результат
let итог;
if (условие) {
итог = значение1;
} else {
итог = значение2;
}
// Сценарий 2: Поиск значения
let найденныйЭлемент;
for (const элемент of массив) {
if (элемент.ид === целевойИд) {
найденныйЭлемент = элемент;
break;
}
}
// Теперь проверяем:
if (найденныйЭлемент) {
console.log(найденныйЭлемент);
} else {
console.log("Не найдено");
}
Сравнительная таблица var vs let vs const
Ниже — полная сравнительная таблица трёх способов объявления переменных.
| Характеристика | var | let | const |
|---|---|---|---|
| Год появления | 1995 | 2015 | 2015 |
| Область видимости | Функция | Блок { } | Блок { } |
| Hoisting (поднятие) | Да (→ undefined) | TDZ (ошибка) | TDZ (ошибка) |
| Переобъявление | ✅ Разрешено | ❌ Ошибка | ❌ Ошибка |
| Переназначение | ✅ Разрешено | ✅ Разрешено | ❌ Запрещено |
| Глобальное свойство (window) | Да | Нет | Нет |
| Начальное значение | Не обязательно | Не обязательно | Обязательно |
| В цикле for | ❌ Проблемы | ✅ Идеально | ⚠️ Только for...of |
| Рекомендация | 🚫 Избегать | ✅ Когда меняется | ✅ По умолчанию |
| Приоритет использования | 3 (последний) | 2 (второй) | 1 (первый) |
💡 Краткое правило: 95% времени используйте const. Когда значение точно будет меняться — берите let. var — только если поддерживаете legacy-код.
Практические примеры и упражнения
Давайте закрепим знания на реальных примерах. Для каждого случая подберите правильное ключевое слово.
Пример 1: Калькулятор
// Простой калькулятор — какие ключевые слова выбрать?
const ПРОЦЕНТ_НАЛОГА = 0.13; // const — константа
const СТАВКА_СКИДКИ = 0.05; // const — константа
function рассчитатьИтог(цена, количество, применитьСкидку) {
const подытог = цена * количество; // const — вычисляется один раз
let скидка = 0; // let — может измениться
if (применитьСкидку) {
скидка = подытог * СТАВКА_СКИДКИ;
}
const суммаБезНДС = подытог - скидка;
const налог = суммаБезНДС * ПРОЦЕНТ_НАЛОГА;
const итог = суммаБезНДС + налог;
return итог;
}
const цена = рассчитатьИтог(1000, 3, true);
console.log(цена); // 3045.5
Пример 2: Форма входа
// Форма входа — какие ключевые слова?
const МАКС_ДЛИНА_ПАРОЛЯ = 128;
const МИН_ДЛИНА_ПАРОЛЯ = 8;
function проверитьВход(логин, пароль) {
const ошибки = []; // const — массив, но будем пушить
if (!логин) {
ошибки.push("Введите логин");
}
if (!пароль) {
ошибки.push("Введите пароль");
} else if (пароль.length < МИН_ДЛИНА_ПАРОЛЯ) {
ошибки.push("Пароль слишком короткий");
} else if (пароль.length > МАКС_ДЛИНА_ПАРОЛЯ) {
ошибки.push("Пароль слишком длинный");
}
const валидно = ошибки.length === 0;
return { валидно, ошибки };
}
const результат = проверитьВход("admin", "123");
console.log(результат);
// { валидно: false, ошибки: ["Пароль слишком короткий"] }
Пример 3: Список задач
// Список задач — все переменные на своих местах
const задачи = []; // const — массив будет пополняться
let счётчикИд = 1; // let — будет увеличиваться
function добавитьЗадачу(текст) {
const задача = {
ид: счётчикИд++,
текст,
выполнена: false
};
задачи.push(задача);
return задача;
}
function выполнитьЗадачу(ид) {
const задача = задачи.find(т => т.ид === ид);
if (задача) {
задача.выполнена = true;
}
}
function показатьНевыполненные() {
const невыполненные = задачи.filter(т => !т.выполнена);
return невыполненные;
}
добавитьЗадачу("Написать код");
добавитьЗадачу("Написать тесты");
выполнитьЗадачу(1);
console.log(показатьНевыполненные());
// [{ид: 2, текст: "Написать тесты", выполнена: false}]
Визуальная шпаргалка: как выбрать ключевое слово
Алгоритм выбора: const vs let vs var
Нужно объявить переменную?
Это старый код (до 2015)?
Да → var
Нет → ↓
Значение будет меняться?
Нет → const
Да → let
Советы для повседневной работы
1. Начинайте с const
По умолчанию объявляйте все переменные через const. Если позже выяснится, что значение нужно менять — переключитесь на let. Так вы защитите себя от случайных переназначений.
2. Одна переменная на строку
Не объявляйте несколько переменных через запятую в одной строке. Каждая переменная — отдельная строка. Это улучшает читаемость и упрощает работу с git.
3. Забудьте о var
В новом коде никогда не используйте var. Его поведение непредсказуемо и приводит к багам. Если встретите var в старом коде — при рефакторинге заменяйте на let или const.
4. Используйте осмысленные имена
Имя переменной должно объяснять, что в ней хранится. имяПользователя лучше, чем data или x.
5. Доверяйте TypeScript
TypeScript предупредит вас о проблемах: использование до объявления, возможный undefined, несовпадение типов. Прислушивайтесь к его подсказкам.
6. const не значит «неизменяемый»
Помните: const запрещает переназначение, но не изменение содержимого массивов и объектов. Если нужна полная неизменяемость — используйте Object.freeze().
Краткое резюме: три ключевых отличия
var
- Функциональная область видимости
- Поднимает значение (undefined)
- Можно переобъявлять
- Не использовать!
let
- Блочная область видимости
- Временная мёртвая зона
- Нельзя переобъявлять
- Можно переназначать
const
- Блочная область видимости
- Временная мёртвая зона
- Нельзя переобъявлять
- Нельзя переназначать
Итоги урока
- var — старый способ с функциональной областью видимости, hoisting и переобъявлением. Не используйте в новом коде.
- let — современный способ с блочной областью видимости. Используйте, когда значение будет меняться.
- const — modernенный способ с блочной областью и запретом переназначения. Используйте по умолчанию.
- Правило: 95% времени —
const, когда значение меняется —let,var— только в legacy-коде. - const защищает ссылку, но не данные — содержимое массивов и объектов можно менять.
- Именование: используйте camelCase, осмысленные имена, одну переменную на строку.
Следующий урок
Неявное определение типа (type inference)
Как TypeScript сам догадывается о типах ваших переменных
Проверяем понимание
8 вопросов