Переменные в JavaScript
Переменные в JavaScript
Переменные и константы
Для своей работы, функции используют какие-то данные. Эти данные являются по умолчанию чем-то неопределённым. Но, чтобы этот набор данных как-то «упаковать» в пригодной для работы оболочке, нужен «контейнер».
★ Переменная – это «контейнер» для хранения данных. Её значение можно менять. Переменная – это именно та самая «x» из математических примеров, где x=5+5.
★ Константа – тоже контейнер для данных, но её значение нельзя изменить после создания. Представим, что вам нужно объявить значение, и оно будет постоянным. Тогда и нужна константа.
В начальных примерах мы указывали именно константы, потому что подразумевали, что значение, указанное нами в коде, будет постоянным и неизменным.
Говоря о создании, поскольку фактически непосредственного «создания» не происходит, программирование использует термин «объявить». Переменную не создают, а объявляют.
let, var, const
Ключевые слова для объявления переменных
| Ключевое слово | Описание | Пример |
|---|---|---|
| let | Переменная (значение можно менять) | let age = 25 |
| const | Константа (значение нельзя менять) | const PI = 3.14 |
| var | Устаревший вариант переменной var | name = "Тимур" |
Переменную можно объявить, и она уже будет в памяти. Потом ей можно изменить значение, допустим, x была равна 10, а потом можно её сделать равной 5. Константу, если мы указали как равной 10, уже значение не поменять.
В коде это выглядит так:
// Переменная (можно менять)
let userName = "Оскар";
userName = "Хан"; // OK
// Константа (нельзя менять)
const birthYear = 1990;
birthYear = 2000; // Ошибка! TypeError: Assignment to constant variable.
Поэтому, если какое-то значение менять в процессе не потребуется, и оно всегда будет стабильным – лучше использовать константы, это займёт меньше ресурсов.
У вас может возникнуть вопрос - а почему var устаревшее ключевое слово для объявления переменной?
Мы помним, что такое область видимости переменной - как правило, она ограничивается блоком кода, где она была объявлена. Но область видимости переменных var не ограничивается блоком кода - она создаёт глобальную переменную. Допустим, если напишем if(true) { let name; } то name будет видна только внутри фигурных скобок блока if, при попытке доступа из других блоков name будет undefined. Но если мы аналогично сделаем var - if(true) { var name } то name станет видима!
Кроме этого, var допускает повторное объявление, в отличие от let - если вы напишете let name; let name; то на втором экземпляре «let name;» будет ошибка синтаксиса, потому что переменная name уже объявлена. В случае с var name; var name система ругаться не будет.
Ещё интересное отличие - var технически считается объявленным в самом начале работы функции. То есть, даже если вы поместите var в конец блока функции, системе будет «плевать», она начнёт исполнение с var, «переместив» в начало кода. И что самое сложное - такое объявление «перемещается» без своего значения.
Как использовать переменные?
Пример:
let name = "Тарзан";
let message = 'Привет, мир!';
let template = `Меня зовут ${name}`; // Шаблонная строка, для вызова надо указать ${имя переменной} и тогда будет работа с её значением
Здесь мы объявили три переменные:
- name – её значение равно «Анна»;
- message со значением «Привет мир!»;
- template – «
Меня зовут ${name}».
Шаблонная строка (template) будет выводить нам динамически изменяемое значение, которое будет подставлять значение переменной, указанной через символ $ в скобках – в нашем случае, будет «Меня зовут Анна», так как выше мы указали, что name=«Анна».
Пример объекта:
const person = {
name: "Рэй",
age: 30,
isStudent: false
};
Здесь мы видим более сложный объект person, который включает в себя свойства, name, age, isStudent. Все эти три свойства друг от друга независимы, к примеру, isStudent может быть true. Следовательно, обратившись к person.name, person.age, person.isStudent – мы получим соответственно значения «Рэй», 30 и false. Так и работает объект.
Объявление переменных
★ Создание (объявление) переменной:
<ключевое_слово> <имя_переменной>;
let age; // Объявили переменную (значение = undefined)
Объявить переменную можно через ключевое слово let или var. При объявлении значение можно не указывать. Логически это «пусть будет возраст».
Главное отличие между var и let в области видимости. Это главное отличие.
var: Обладает функцийной областью видимости. Переменная становится доступной во всей функции, где она объявлена, независимо от того, находится ли она внутри блоковif,forилиwhile.let: Обладает блочной областью видимости. Переменная видна только внутри блока{ ... }, в котором она объявлена (например, внутриif,forили просто фигурных скобок).
// --- Пример с var ---
function testVar() {
if (true) {
var x = 10; // Объявлена в области видимости функции testVar, а не блока if
}
console.log(x); // Выведет: 10 (доступна снаружи блока if)
}
testVar();
// --- Пример с let ---
function testLet() {
if (true) {
let y = 20; // Объявлена только внутри блока if
}
// console.log(y); // ОШИБКА: ReferenceError: y is not defined
// Переменная y недоступна за пределами блока if
}
testLet();
При использовании var в цикле for переменная цикла остается доступной после завершения цикла и имеет значение последнего элемента. При использовании let переменная создается заново для каждой итерации и недоступна после цикла.
// --- С var ---
for (var i = 0; i < 3; i++) {
console.log("Итерация:", i);
}
console.log("После цикла:", i); // Выведет: 3 (i доступна и равна 3)
// --- С let ---
for (let j = 0; j < 3; j++) {
console.log("Итерация:", j);
}
// console.log("После цикла:", j); // ОШИБКА: ReferenceError: j is not defined
// Переменная j уничтожается после окончания блока цикла
var: Позволяет переобъявлять одну и ту же переменную в одной и той же области видимости без ошибок. Последнее объявление побеждает.let: Запрещает повторное объявление переменной с тем же именем в той же области видимости. Это вызовет ошибкуSyntaxError.
// --- С var ---
var name = "Тимур";
var name = "Новое имя"; // Разрешено, но может запутать логику
console.log(name); // "Новое имя"
// --- С let ---
let age = 31;
// let age = 32; // ОШИБКА: SyntaxError: Identifier 'age' has already been declared
var: Подвержен хоистингу (вынесению вверх). Переменная объявляется и инициализируется значениемundefinedв начале функции/блока. К ней можно обратиться до строки объявления, но она будет иметь значениеundefined.let: Также подвержен хоистингу, но не инициализируется. Между началом блока и строкой объявления переменная существует в зоне временной мертвой области (TDZ). Попытка обратиться к ней до объявления вызовет ошибкуReferenceError.
// --- С var ---
console.log(a); // Вывод: undefined (без ошибки)
var a = 5;
// --- С let ---
console.log(b); // ОШИБКА: ReferenceError: Cannot access 'b' before initialization
let b = 5;
Если объявить переменную с var вне любой функции, она становится свойством глобального объекта (window в браузере). С let это невозможно — глобальная переменная с let не добавляется в объект window.
var globalVar = "Я в window";
let globalLet = "Я не в window";
console.log(window.globalVar); // "Я в window"
console.log(window.globalLet); // undefined
Сводная таблица различий
| Характеристика | var | let |
|---|---|---|
| Область видимости | Функция (Function scope) | Блок (Block scope) |
| Переопределение | Разрешено | Запрещено (SyntaxError) |
| Доступ до объявления | Возвращает undefined | Вызывает ReferenceError |
| Глобальный объект | Добавляется в window | Не добавляется в window |
| Рекомендация | Избегать в новом коде | Использовать по умолчанию |
Всегда используйте let (или const, если переменная не меняется). Используйте var только при поддержке очень старого кода, который нельзя изменить.
Присваивание значений
★ Присваивание значения:
<имя_переменной> = <значение>;
age = 25; // Теперь age = 25
Присваивание значение выполняется через символ равенства «=». Присваивание можно выполнить и при объявлении, но в нашем случае, это будет «Возраст равен 25».
Инициализация при объявлении:
<ключевое_слово> <имя_переменной> = <значение>;
Использование переменных
★ Использование:
<имя_переменной>
console.log(age); // 25
Поскольку ранее переменная age уже была объявлена – в памяти для неё выделено место, а после присвоения получено было и конкретное значение типа Number. Теперь можно просто указать имя переменной, чтобы использовать.
Обновление значения:
<имя_переменной> = <новое_значение>;
Деструктуризирующее присваивание:
{ <свойство>: <имя_переменной> } = <объект>;
[ <имя_переменной> ] = <массив>;
Эти шаблоны позволяют извлекать значения из объектов или массивов и одновременно объявлять новые переменные.
Объявление нескольких переменных:
<ключевое_слово> <имя1> = <значение1>, <имя2> = <значение2>, …;
Правила работы с переменными
★ Правила именования переменных:
- имена чувствительны к регистру (user, USER, User – разные переменные);
- можно использовать буквы, цифры, _ и $;
- нельзя начинать с цифры: 1user – ошибка;
- нельзя использовать зарезервированные ключевые слова (let, function).
И разумеется, есть продвинутые операции с переменными. Как можно понять, это просто участок памяти, в который можно записать что угодно - к примеру, число, строку, объект или результат выполнения нескольких функций, всё зависит от сложности.
JS - динамически типизированный, что позволяет писать просто «пусть будет переменная», а система сама решит, что за тип, на основе значения — это значительно упрощает код. И допустим можно сделать так:
let array = [1,2]
Это массив, мы буквально сказали - пусть будет переменная по имени array, значением которой будет массив чисел из 1 и 2. И порой возникает задача, когда нужно распаковать такие массивы или объекты, раскидав их в несколько переменных. Это называется деструктирующее присваивание.
Мы просто объявляем, буквально в инверсии:
let [a, b] = array;
Так мы указываем, что a и b это соответствующие значения массива array, что позволит нам использовать соответствующие значения - a будет 1, b будет 2 (a - первый элемент массива, b второй):
console.log(a); // 1
console.log(b); // 2
Элементы массива можно пропускать, добавив «, ,»:
let [x, , z] = [10, 20, 30];
Можно указать …rest, чтобы выбрать массив оставшихся:
let [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [2, 3, 4, 5] → массив оставшихся
И можно устанавливать значения по умолчанию:
let [name = "Аноним", age = 18] = ["Алиса"];
console.log(name); // "Алиса"
console.log(age); // 18 → значение по умолчанию
Деструктуризация может быть применена и к объектам, но мы ещё их не изучили, поэтому вернёмся позже.
Hoisting
Hoisting – это поведение JavaScript, при котором объявления переменных и функций перемещаются в начало своей области видимости во время компиляции кода. Это происходит до выполнения кода.
Переменные, объявленные с var, поднимаются в начало функции:
console.log(x); // undefined
var x = 5;
console.log(x); // 5
В этом примере переменная x объявлена в начале функции, но её значение undefined до присвоения.
Функции, объявленные через Function Declaration, полностью поднимаются:
sayHello(); // "Привет!"
function sayHello() {
console.log("Привет!");
}
Функция sayHello доступна до её объявления в коде.
Переменные let и const также поднимаются, но остаются в "временной мёртвой зоне":
console.log(y); // ReferenceError
let y = 10;
Переменная y существует в памяти, но недоступна до её объявления.
Пример с несколькими объявлениями:
function example() {
console.log(a); // undefined
var a = 1;
console.log(b); // ReferenceError
let b = 2;
console.log(c()); // 3
function c() {
return 3;
}
}
example();
Область действия
Область действия определяет, где в коде доступна переменная. JavaScript поддерживает функциональную и блочную области видимости.
Функциональная область видимости
Переменные, объявленные внутри функции, доступны только внутри этой функции:
function outerFunction() {
let outerVar = "внешняя";
function innerFunction() {
let innerVar = "внутренняя";
console.log(outerVar); // "внешняя"
console.log(innerVar); // "внутренняя"
}
innerFunction();
console.log(outerVar); // "внешняя"
// console.log(innerVar); // ReferenceError
}
outerFunction();
Переменные var имеют функциональную область видимости:
function testVar() {
if (true) {
var x = "var";
}
console.log(x); // "var" - доступна вне блока if
}
testVar();
Блочная область видимости
Переменные let и const имеют блочную область видимости:
function testLet() {
if (true) {
let y = "let";
const z = "const";
console.log(y); // "let"
console.log(z); // "const"
}
// console.log(y); // ReferenceError
// console.log(z); // ReferenceError
}
testLet();
Вложенные блоки создают вложенные области видимости:
function nestedScopes() {
let level1 = "уровень 1";
{
let level2 = "уровень 2";
console.log(level1); // "уровень 1"
console.log(level2); // "уровень 2"
{
let level3 = "уровень 3";
console.log(level1); // "уровень 1"
console.log(level2); // "уровень 2"
console.log(level3); // "уровень 3"
}
// console.log(level3); // ReferenceError
}
// console.log(level2); // ReferenceError
}
nestedScopes();
Циклы создают свою область видимости для let:
for (let i = 0; i < 3; i++) {
console.log(i); // 0, 1, 2
}
// console.log(i); // ReferenceError
for (var j = 0; j < 3; j++) {
console.log(j); // 0, 1, 2
}
console.log(j); // 3 - var доступен вне цикла
Глобальное пространство имён
Глобальное пространство имён – это область, доступная во всём коде приложения. Переменные, объявленные вне функций и блоков, становятся глобальными.
В браузере глобальный объект – это window:
let globalVar = "глобальная";
function checkGlobal() {
console.log(globalVar); // "глобальная"
console.log(window.globalVar); // "глобальная"
}
checkGlobal();
Переменные без ключевого слова становятся глобальными:
function createGlobal() {
accidentalGlobal = "случайная глобальная";
}
createGlobal();
console.log(accidentalGlobal); // "случайная глобальная"
console.log(window.accidentalGlobal); // "случайная глобальная"
Глобальные константы полезны для общих значений:
const API_URL = "https://api.example.com";
const MAX_RETRIES = 3;
const TIMEOUT_MS = 5000;
function fetchData() {
console.log(`Запрос к ${API_URL}`);
// Логика запроса
}
Избегайте загрязнения глобального пространства имён:
// Плохо - много глобальных переменных
var userName = "Джон";
var userAge = 30;
var userEmail = "john@example.com";
// Хорошо - одна глобальная переменная
const user = {
name: "Джон",
age: 30,
email: "john@example.com"
};
Модульный подход изолирует глобальные переменные:
// app.js
const App = (function() {
let privateVar = "приватная";
return {
publicVar: "публичная",
getPrivate: function() {
return privateVar;
}
};
})();
console.log(App.publicVar); // "публичная"
console.log(App.getPrivate()); // "приватная"
// console.log(App.privateVar); // undefined
using, await using
Конструкции using и await using предоставляют механизм автоматического управления ресурсами. Эти конструкции гарантируют освобождение ресурсов после завершения блока кода.
using для синхронного управления
Конструкция using автоматически вызывает метод dispose при выходе из блока:
// using для файловых операций
using (const file = new File("Данные.txt")) {
const content = file.read();
console.log(content);
}
// Файл автоматически закрыт здесь
Пример с базой данных:
using (const connection = new DatabaseConnection()) {
const results = connection.query("SELECT * FROM users");
processResults(results);
}
// Соединение автоматически закрыто
await using для асинхронного управления
Конструкция await using работает с асинхронными ресурсами:
async function processFile() {
await using (const file = await File.openAsync("Данные.txt")) {
const content = await file.readAsync();
console.log(content);
}
// Файл автоматически закрыт здесь
}
Пример с сетевыми ресурсами:
async function fetchData() {
await using (const client = new HttpClient()) {
const response = await client.getAsync("https://api.example.com");
const Данные = await response.json();
return Данные;
}
// Клиент автоматически освобождён
}
Создание собственных disposable объектов
Объекты могут реализовать интерфейс IDisposable:
class CustomResource {
constructor() {
this.resource = allocateResource();
}
use() {
// Работа с ресурсом
console.log("Использую ресурс");
}
dispose() {
// Освобождение ресурса
console.log("Освобождаю ресурс");
freeResource(this.resource);
}
}
// Использование
using (const resource = new CustomResource()) {
resource.use();
}
// dispose вызван автоматически
Асинхронная версия:
class AsyncResource {
async open() {
this.resource = await allocateResourceAsync();
}
async use() {
console.log("Использую асинхронный ресурс");
}
async disposeAsync() {
console.log("Освобождаю асинхронный ресурс");
await freeResourceAsync(this.resource);
}
}
// Использование
await using (const resource = new AsyncResource()) {
await resource.open();
await resource.use();
}
// disposeAsync вызван автоматически
Преимущества конструкций using
Конструкции using и await using обеспечивают:
- Автоматическое освобождение ресурсов
- Защиту от утечек памяти
- Чистый и понятный код
- Гарантированное выполнение
disposeдаже при ошибках
Пример с обработкой ошибок:
try {
using (const resource = new CriticalResource()) {
resource.performOperation();
// Если здесь возникнет ошибка, dispose всё равно вызовется
}
} catch (error) {
console.error("Ошибка:", error);
}
// Ресурс освобождён независимо от результата
Асинхронный пример:
async function safeOperation() {
try {
await using (const resource = await CriticalResource.createAsync()) {
await resource.performAsyncOperation();
}
} catch (error) {
console.error("Асинхронная ошибка:", error);
}
// Ресурс освобождён даже при ошибке
}
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). ECMAScript — это официальный стандарт языка JavaScript, определяющий его синтаксис, семантику и встроенные объекты. Он описывает поведение языка независимо от среды выполнения (браузер, Node.js и… Фундамент для начинающего программиста - что повторить, как работать, чего ожидать. Для создания массивов используется литеральная нотация. Конструктор Array не применяется. Как работать с HTML-элементами, как их создавать, менять. JavaScript — это язык программирования, который изначально создавался для работы в веб-браузерах. Сегодня он является универсальным инструментом, позволяющим создавать серверные приложения, утилиты… Потребность в интерактивности возникла по мере роста сложности веб-сервисов. В частности, уже в первой половине 1990-х года в компании Netscape Communications, разрабатывавшей браузер Netscape… Такое именование представляет собой соглашение между разработчиками. Классический JavaScript не обеспечивает реальной приватности через подчеркивания. JavaScript содержит набор зарезервированных слов, которые имеют специальное значение в языке. Эти слова нельзя использовать в качестве идентификаторов для переменных, функций или классов. Функция Значение Пример --------------------------- Array.isArray() Проверяет, является ли значение массивом Array.isArray(1, 2) concat() Объединяет массивы 1, 2.concat(3, 4) push() Добавляет элемент… Этот шаблон описывает подключение внешних функций, классов или значений из других файлов. Он используется в начале файла и определяет зависимости текущего модуля. JavaScript используется для создания кроссплатформенных мобильных приложений, которые работают на iOS и Android с использованием единой кодовой базы. Что такое функция, параметры, аргументы, возврат значения.Основы JavaScript
Что требуется знать перед началом изучения языка программирования
Рекомендации по разработке на JavaScript
Работа с HTML в JavaScript
Простые приложения на JavaScript
История языка JavaScript
Синтаксис и пунктуация в JavaScript
Ключевые слова языка JavaScript
Встроенные функции JavaScript
Структура и подключение JavaScript-кода
Применение JavaScript в вебе и за его пределами
Функции в JavaScript