Переменные и типы данных в JavaScript: полное руководство + примеры
#Основы JavaScript #Синтаксис и типы данных #Переменные и области видимостиДля кого эта статья:
- начинающие разработчики в JavaScript
- студенты и курсанты по программированию
- профессионалы, желающие освежить знания о переменных и типах данных в JavaScript
Переменные и типы данных – фундамент, на котором строится каждая JavaScript-программа. Освоение этих концепций равносильно получению ключей от машины: теперь вы не просто можете смотреть на красивый автомобиль, но и управлять им. А управлять данными в JavaScript – это настоящее искусство! Знаете ли вы, что более 70% ошибок начинающих разработчиков связаны с неправильным использованием переменных и непониманием типов данных? Разберем всё от А до Я: от объявления простейшей переменной до сложных преобразований типов – с примерами кода, которые вы сможете запустить прямо сейчас. 🚀
Основы объявления переменных в JavaScript: var, let, const
В JavaScript существует три способа объявления переменных: var, let и const. Каждый из них имеет свои особенности и области применения. Понимание разницы между ними критически важно для написания качественного кода. 🧩
Начнем с классического var:
var userName = "Alex";
var userAge = 25;
var isLoggedIn = true;
Переменные, объявленные через var, имеют функциональную область видимости и "всплывают" (hoisting) в начало функции. Это значит, что вы можете использовать переменную до её объявления, хотя значение будет undefined:
console.log(x); // undefined
var x = 5;
С появлением ES6 (ECMAScript 2015) появились let и const, которые решили многие проблемы var:
let counter = 0;
const API_KEY = "abc123xyz";
Переменные let имеют блочную область видимости и не подвергаются всплытию в том же смысле, что и var:
console.log(counter); // Error: Cannot access 'counter' before initialization
let counter = 0;
const работает аналогично let, но с одним важным отличием: значение константы нельзя изменить после инициализации:
const PI = 3.14159;
PI = 3; // Error: Assignment to constant variable
Алексей Петров, старший JavaScript-разработчик
Я работал с командой джуниоров над проектом среднего размера, и код становился настоящим хаосом из-за использования var везде. Переменные переопределялись в неожиданных местах, создавались неявные глобальные переменные, а поиск багов превращался в настоящий квест.
Мы провели рефакторинг, заменив все var на let и const по следующему принципу: по умолчанию используем const, если значение переменной должно меняться – используем let. После этой, казалось бы, простой замены количество неожиданных багов сократилось на 40%!
Особенно показательный случай: у нас была функция обработки данных пользователя, где var userId переопределялся внутри вложенного цикла, но это изменение влияло на внешний цикл. Замена на let с правильной блочной областью видимости мгновенно решила проблему.
Сравним все три способа объявления переменных:
| Характеристика | var | let | const |
|---|---|---|---|
| Область видимости | Функциональная | Блочная | Блочная |
| Повторное объявление | Разрешено | Запрещено | Запрещено |
| Изменение значения | Разрешено | Разрешено | Запрещено |
| Hoisting | Да, со значением undefined | Да, но в "временной мертвой зоне" | Да, но в "временной мертвой зоне" |
| Использование в 2023 | Не рекомендуется | Для изменяемых значений | По умолчанию |
Современные рекомендации по использованию переменных в JavaScript:
- Используйте
constпо умолчанию для всех переменных - Используйте
letтолько когда значение переменной должно меняться - Избегайте использования
varв новом коде - Всегда инициализируйте переменные при объявлении
- Используйте осмысленные имена переменных в camelCase

Примитивные типы данных JS: number, string, boolean
В JavaScript существует семь примитивных типов данных, но три из них являются основными и используются повсеместно: number, string и boolean. Рассмотрим каждый из них подробно. 🔢 📝 ✓
Number – тип для всех числовых значений:
let age = 25; // целое число
let price = 19.99; // число с плавающей точкой
let infinityValue = Infinity; // бесконечность
let notANumber = NaN; // специальное значение "не число"
Переменные типа число в JavaScript могут содержать значения от ±(2<sup>-1074</sup>) до ±(2<sup>1024</sup>), что соответствует диапазону примерно ±5×10<sup>-324</sup> до ±1.8×10<sup>308</sup>.
JavaScript использует стандарт IEEE 754 для представления чисел, что иногда приводит к неожиданным результатам:
console.log(0.1 + 0.2); // 0.30000000000000004, а не 0.3
Для работы с числами в JavaScript доступны различные операции и методы:
let x = 10;
let y = 3;
console.log(x + y); // 13 (сложение)
console.log(x – y); // 7 (вычитание)
console.log(x * y); // 30 (умножение)
console.log(x / y); // 3.3333... (деление)
console.log(x % y); // 1 (остаток от деления)
console.log(x ** y); // 1000 (возведение в степень)
// Методы объекта Math
console.log(Math.round(3.7)); // 4
console.log(Math.floor(3.7)); // 3
console.log(Math.ceil(3.1)); // 4
console.log(Math.max(5, 10)); // 10
String – тип для текстовых данных:
let firstName = "John";
let lastName = 'Doe';
let greeting = `Hello, ${firstName}!`; // шаблонная строка с интерполяцией
Строки в JavaScript могут быть заключены в одинарные ('), двойные (") или обратные (`) кавычки. Последний вариант позволяет создавать шаблонные строки с интерполяцией переменных и многострочным содержимым.
JavaScript предоставляет богатый набор методов для работы со строками:
let message = "JavaScript is amazing";
console.log(message.length); // 22 (длина строки)
console.log(message.toUpperCase()); // "JAVASCRIPT IS AMAZING"
console.log(message.toLowerCase()); // "javascript is amazing"
console.log(message.indexOf("is")); // 11 (позиция подстроки)
console.log(message.replace("amazing", "awesome")); // "JavaScript is awesome"
console.log(message.split(" ")); // ["JavaScript", "is", "amazing"]
console.log(message.slice(0, 10)); // "JavaScript"
Boolean – тип с двумя возможными значениями: true и false:
let isActive = true;
let isLoggedIn = false;
// Логические операторы
console.log(!isActive); // false (отрицание)
console.log(isActive && isLoggedIn); // false (логическое И)
console.log(isActive || isLoggedIn); // true (логическое ИЛИ)
Булевы значения часто являются результатом сравнений:
console.log(5 > 3); // true
console.log(5 === 3); // false (строгое равенство)
console.log(5 !== 3); // true (строгое неравенство)
console.log(5 >= 5); // true
Важно понимать разницу между строгим (=, !) и нестрогим (==, !=) сравнением в JavaScript:
| Выражение | Результат | Пояснение |
|---|---|---|
| 5 == "5" | true | Нестрогое равенство с приведением типов |
| 5 === "5" | false | Строгое равенство без приведения типов |
| 0 == false | true | Нестрогое равенство с приведением типов |
| 0 === false | false | Строгое равенство без приведения типов |
| "" == false | true | Нестрогое равенство с приведением типов |
| null == undefined | true | Особый случай в спецификации |
| null === undefined | false | Разные типы данных |
Специальные значения: null, undefined, symbol, bigint
Кроме основных типов данных, JavaScript имеет несколько специальных типов значений, которые служат для особых случаев: null, undefined, Symbol и BigInt. Понимание этих типов отличает опытного JavaScript-разработчика от новичка. 🧠
undefined – значение, которое получают переменные, объявленные, но не инициализированные. Также это значение возвращается при обращении к несуществующему свойству объекта:
let unassignedVar;
console.log(unassignedVar); // undefined
let obj = {};
console.log(obj.nonExistentProperty); // undefined
function noReturn() {
// функция без return
}
console.log(noReturn()); // undefined
null – специальное значение, представляющее "ничего", "пусто" или "неизвестное значение". В отличие от undefined, null нужно явно присвоить переменной:
let user = null; // пользователь пока неизвестен/не существует
let selectedItem = null; // ничего не выбрано
Хотя null и undefined часто используются взаимозаменяемо, между ними есть важные различия:
null– явное отсутствие значения (присваивается программистом)undefined– неявное отсутствие значения (генерируется JavaScript)typeof nullвозвращает "object" (это исторический баг JavaScript)typeof undefinedвозвращает "undefined"
Symbol – уникальный и неизменяемый примитивный тип данных, который может использоваться как ключ для свойств объекта. Символы были добавлены в ECMAScript 2015 (ES6):
const id = Symbol('id');
const user = {
name: 'John',
[id]: 12345 // использование символа как ключа
};
console.log(user[id]); // 12345
console.log(user.id); // undefined (нельзя обратиться через точечную нотацию)
// Каждый символ уникален
const sym1 = Symbol('description');
const sym2 = Symbol('description');
console.log(sym1 === sym2); // false
Символы часто используются для создания "приватных" свойств объектов или для предотвращения случайных коллизий имён свойств:
// Использование символов для предотвращения конфликтов в расширениях
const library1Property = Symbol('property');
const library2Property = Symbol('property');
const obj = {};
obj[library1Property] = 'Value from library 1';
obj[library2Property] = 'Value from library 2';
// Обе библиотеки могут работать с одним объектом без конфликтов
BigInt – относительно новый тип данных (ES2020), предназначенный для работы с целыми числами произвольной длины, за пределами ограничений типа Number:
const bigNumber = 9007199254740991n; // 'n' в конце делает число BigInt
const anotherBigNumber = BigInt("9007199254740991");
console.log(bigNumber + 1n); // 9007199254740992n
console.log(typeof bigNumber); // "bigint"
BigInt особенно полезен в ситуациях, где требуется точная целочисленная арифметика с большими числами, например, при работе с ID из баз данных, в криптографических алгоритмах или при необходимости представить очень большие временные метки.
Важные особенности BigInt:
- Нельзя смешивать операции между BigInt и Number без явного преобразования
- BigInt нельзя использовать с методами Math
- При делении BigInt результат округляется до ближайшего целого
- BigInt не строго равен (=) соответствующему Number, но нестрого равен ()
console.log(1n === 1); // false
console.log(1n == 1); // true
console.log(5n / 2n); // 2n (результат округляется вниз)
Михаил Сидоров, архитектор веб-приложений
В 2021 году мы работали над финтех-платформой, где требовалось обрабатывать очень большие числа — суммы транзакций в микроединицах валют. Мы столкнулись с серьезной проблемой: JavaScript терял точность при работе с большими числами типа Number.
Например, ID транзакций из базы данных (64-битные числа) некорректно отображались в интерфейсе. Мы пробовали разные обходные пути: хранение чисел в строках, использование специальных библиотек. Но настоящим спасением стал тип BigInt.
После внедрения BigInt для ID транзакций и микросумм мы полностью избавились от ошибок округления. Особенно заметна была разница при расчете процентов и комиссий, где ранее накапливалась погрешность. Теперь система работает с точностью до последней "копейки" даже при миллиардных суммах.
Мой совет: всегда используйте BigInt при работе с финансовыми данными или идентификаторами, которые могут превышать безопасный диапазон чисел JavaScript (Number.MAXSAFEINTEGER).
Составные типы данных: объекты и массивы в JavaScript
В JavaScript, помимо примитивных типов, существуют составные (ссылочные) типы данных. Главные представители этой категории — объекты и массивы. Это мощные инструменты для структурирования и организации данных, без которых невозможно представить современную веб-разработку. 📊 🗃️
Объекты – это коллекции пар "ключ-значение". Они позволяют группировать связанные данные и функциональность в одну структуру:
const person = {
firstName: "John",
lastName: "Doe",
age: 30,
hobbies: ["reading", "music", "hiking"],
address: {
street: "123 Main St",
city: "Boston",
state: "MA"
},
greet: function() {
return `Hello, my name is ${this.firstName} ${this.lastName}`;
}
};
// Доступ к свойствам
console.log(person.firstName); // "John"
console.log(person["lastName"]); // "Doe"
console.log(person.address.city); // "Boston"
console.log(person.greet()); // "Hello, my name is John Doe"
Свойства объекта могут быть добавлены, изменены или удалены в любой момент:
person.email = "john.doe@example.com"; // добавление нового свойства
person.age = 31; // изменение существующего свойства
delete person.hobbies; // удаление свойства
JavaScript предлагает несколько мощных методов для работы с объектами:
Object.keys(obj)– возвращает массив ключей объектаObject.values(obj)– возвращает массив значений свойствObject.entries(obj)– возвращает массив пар [ключ, значение]Object.assign(target, ...sources)– копирует свойства из исходных объектов в целевойObject.freeze(obj)– делает объект неизменяемымObject.seal(obj)– запрещает добавление/удаление свойств, но разрешает изменение значений
Массивы – это специальный тип объектов, оптимизированный для хранения упорядоченных коллекций данных:
const colors = ["red", "green", "blue"];
const mixed = [42, "hello", true, null, { name: "object" }];
// Доступ к элементам по индексу (нумерация с 0)
console.log(colors[0]); // "red"
console.log(colors[2]); // "blue"
console.log(colors.length); // 3
JavaScript предоставляет богатый набор методов для работы с массивами:
// Методы, изменяющие исходный массив
colors.push("yellow"); // добавляет элемент в конец
colors.pop(); // удаляет и возвращает последний элемент
colors.unshift("black"); // добавляет элемент в начало
colors.shift(); // удаляет и возвращает первый элемент
colors.splice(1, 1, "purple"); // удаляет 1 элемент с индекса 1 и вставляет "purple"
colors.sort(); // сортирует массив
// Методы, возвращающие новый массив
const sliced = colors.slice(1, 3); // подмассив от индекса 1 до 3 (не включая 3)
const doubled = colors.map(color => color + color); // применяет функцию к каждому элементу
const longColors = colors.filter(color => color.length > 3); // фильтрует элементы
Обход массивов и объектов — частая операция в JavaScript:
// Обход массива
for (let i = 0; i < colors.length; i++) {
console.log(colors[i]);
}
// Более современный способ
for (const color of colors) {
console.log(color);
}
// Функциональный подход
colors.forEach((color, index) => {
console.log(`${index}: ${color}`);
});
// Обход объекта
for (const key in person) {
if (person.hasOwnProperty(key)) {
console.log(`${key}: ${person[key]}`);
}
}
// С использованием Object.entries
Object.entries(person).forEach(([key, value]) => {
console.log(`${key}: ${value}`);
});
Важно понимать, что объекты и массивы в JavaScript передаются по ссылке, а не по значению:
const original = [1, 2, 3];
const copy = original; // copy и original указывают на один и тот же массив
copy.push(4);
console.log(original); // [1, 2, 3, 4] – исходный массив тоже изменился!
// Правильное копирование (поверхностное)
const properCopy = [...original]; // с использованием spread оператора
const anotherCopy = Array.from(original);
const yetAnotherCopy = original.slice();
Для глубокого копирования вложенных структур можно использовать:
const deepObject = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(deepObject)); // с ограничениями
// или использовать структуры данных JS вроде structuredClone() в новых версиях
Преобразование типов данных и практические задачи
Динамическая типизация JavaScript означает, что типы данных могут автоматически преобразовываться при необходимости. Однако понимание и контроль этих преобразований критически важны для предотвращения ошибок. Рассмотрим основные принципы и практические примеры работы с типами данных. 🔄
Явное преобразование типов
JavaScript предоставляет встроенные функции для явного преобразования данных из одного типа в другой:
// Строковое преобразование
let num = 42;
let str1 = String(num); // "42"
let str2 = num.toString(); // "42"
let str3 = num + ""; // "42" (неявное преобразование)
// Числовое преобразование
let str = "42";
let num1 = Number(str); // 42
let num2 = parseInt(str, 10); // 42 (второй аргумент – система счисления)
let num3 = parseFloat("42.5"); // 42.5
let num4 = +"42"; // 42 (неявное преобразование)
// К логическому типу
let bool1 = Boolean(1); // true
let bool2 = Boolean(""); // false
let bool3 = !!0; // false (неявное преобразование через двойное отрицание)
Неявное преобразование типов
JavaScript автоматически преобразует типы в определенных контекстах. Понимание этих правил поможет избежать неожиданного поведения:
// При использовании операторов сравнения
console.log("5" == 5); // true (строка преобразуется в число)
console.log("5" === 5); // false (строгое сравнение, типы разные)
// При использовании математических операторов
console.log("5" + 2); // "52" (число преобразуется в строку)
console.log("5" – 2); // 3 (строка преобразуется в число)
console.log("5" * "2"); // 10 (обе строки преобразуются в числа)
// В логических операциях
console.log(0 || "default"); // "default" (0 преобразуется в false)
console.log(5 && "value"); // "value" (5 преобразуется в true)
Таблица преобразования типов в различных контекстах:
| Значение | К String | К Number | К Boolean |
|---|---|---|---|
| undefined | "undefined" | NaN | false |
| null | "null" | 0 | false |
| true | "true" | 1 | – |
| false | "false" | 0 | – |
| "" | – | 0 | false |
| "123" | – | 123 | true |
| 0 | "0" | – | false |
| [] | "" | 0 | true |
| {} | "[object Object]" | NaN | true |
Практические задачи и решения
- Проверка типа данных
console.log(typeof 42); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (это баг JavaScript)
console.log(typeof []); // "object" (массивы – это объекты)
console.log(typeof {}); // "object"
// Для массивов лучше использовать Array.isArray()
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
- Проверка на пустоту
const isEmpty = str => str.trim().length === 0;
// Проверка пустого объекта
const isEmptyObject = obj => Object.keys(obj).length === 0;
// Проверка пустого массива
const isEmptyArray = arr => arr.length === 0;
- Безопасное получение значений
// Проблема: получение вложенных свойств может вызвать ошибку
const user = { profile: { address: { city: "New York" } } };
// const user = {}; // если структура не та, что ожидается
// Решение 1: проверка на каждом уровне
const city1 = user && user.profile && user.profile.address && user.profile.address.city;
// Решение 2: оператор опциональной цепочки (ES2020)
const city2 = user?.profile?.address?.city;
// Решение 3: с установкой значения по умолчанию
const city3 = (user?.profile?.address?.city) || "Unknown";
- Приведение к числу с валидацией
function safeParseNumber(value) {
const num = Number(value);
if (isNaN(num)) {
return { success: false, error: "Invalid number" };
}
return { success: true, value: num };
}
console.log(safeParseNumber("42")); // { success: true, value: 42 }
console.log(safeParseNumber("abc")); // { success: false, error: "Invalid number" }
- Объединение массивов и объектов
// Объединение массивов
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// Объединение объектов
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 }; // b перезапишет значение из obj1
const mergedObj = { ...obj1, ...obj2 }; // { a: 1, b: 3, c: 4 }
- Деструктуризация данных
// Деструктуризация объекта
const user = { name: "John", age: 30, city: "New York" };
const { name, age, city = "Unknown" } = user;
console.log(name, age, city); // "John", 30, "New York"
// Деструктуризация массива
const rgb = [255, 128, 0];
const [red, green, blue] = rgb;
console.log(red, green, blue); // 255, 128, 0
- Валидация типов данных для функций
function calculateArea(width, height) {
// Проверка типов аргументов
if (typeof width !== 'number' || typeof height !== 'number') {
throw new TypeError('Both width and height must be numbers');
}
// Проверка валидности значений
if (width <= 0 || height <= 0) {
throw new RangeError('Dimensions must be positive');
}
return width * height;
}
try {
console.log(calculateArea(5, 10)); // 50
console.log(calculateArea("5", 10)); // Ошибка TypeError
console.log(calculateArea(-5, 10)); // Ошибка RangeError
} catch (error) {
console.error(error.message);
}
- Создание типобезопасных структур данных
// Простая реализация типизированного массива
function TypedArray(type) {
const validTypes = ['string', 'number', 'boolean'];
if (!validTypes.includes(type)) {
throw new Error(`Type must be one of: ${validTypes.join(', ')}`);
}
const array = [];
return {
push(item) {
if (typeof item !== type) {
throw new TypeError(`Item must be of type ${type}`);
}
array.push(item);
return array.length;
},
get(index) {
return array[index];
},
getAll() {
return [...array];
}
};
}
const numbers = TypedArray('number');
numbers.push(1);
numbers.push(2);
// numbers.push("3"); // Ошибка TypeError
console.log(numbers.getAll()); // [1, 2]
Правильное понимание переменных и типов данных в JavaScript — фундамент для построения стабильных и эффективных веб-приложений. Динамическая типизация языка даёт гибкость, но требует от разработчика большей осознанности и внимания к деталям. Используйте const по умолчанию для всех переменных, прибегайте к let только когда значение должно меняться, и полностью откажитесь от var в современном коде. Помните о разнице между примитивными и ссылочными типами, особенно когда работаете с объектами и массивами. Явно преобразовывайте типы данных там, где это необходимо, не полагаясь на автоматическое преобразование. И самое главное — практикуйтесь в решении реальных задач, ведь настоящее мастерство приходит только с опытом.
Читайте также
Станислав Плотников
фронтенд-разработчик