Переменные и типы данных в JavaScript: полное руководство + примеры
Перейти

Переменные и типы данных в JavaScript: полное руководство + примеры

#Основы JavaScript  #Синтаксис и типы данных  #Переменные и области видимости  
Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • начинающие разработчики в 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

Практические задачи и решения

  1. Проверка типа данных
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

  1. Проверка на пустоту
const isEmpty = str => str.trim().length === 0;

// Проверка пустого объекта
const isEmptyObject = obj => Object.keys(obj).length === 0;

// Проверка пустого массива
const isEmptyArray = arr => arr.length === 0;

  1. Безопасное получение значений
// Проблема: получение вложенных свойств может вызвать ошибку
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";

  1. Приведение к числу с валидацией
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" }

  1. Объединение массивов и объектов
// Объединение массивов
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 }

  1. Деструктуризация данных
// Деструктуризация объекта
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

  1. Валидация типов данных для функций
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);
}

  1. Создание типобезопасных структур данных
// Простая реализация типизированного массива
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 в современном коде. Помните о разнице между примитивными и ссылочными типами, особенно когда работаете с объектами и массивами. Явно преобразовывайте типы данных там, где это необходимо, не полагаясь на автоматическое преобразование. И самое главное — практикуйтесь в решении реальных задач, ведь настоящее мастерство приходит только с опытом.

Читайте также

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Какой ключ используется для объявления переменной с блочной областью видимости в JavaScript?
1 / 5

Станислав Плотников

фронтенд-разработчик

Свежие материалы

Загрузка...