Обзор всех видов значений в языке программирования JS: от undefined до Object и BigInt
Типы значений в JavaScript
В JavaScript любое значение относится к одному из восьми встроенных типов. Семь из них примитивные (string, number, bigint, boolean, undefined, symbol, null) и один ссылочный - object. Примитивы передаются по значению, объекты - по ссылке. Это определяет поведение переменных при копировании и сравнении.
Основное разделение: примитивы и объекты
Примитивные значения неизменяемы. Операции над ними возвращают новые значения. Объекты изменяемы - их свойства можно менять через ссылку. При копировании примитива создаётся независимая копия, при копировании объекта копируется ссылка.
// Примитив
let a = 5;
let b = a;
b = 10;
console.log(a); // 5 - копия не затронула исходное значение
// Объект
let obj1 = { x: 1 };
let obj2 = obj1;
obj2.x = 2;
console.log(obj1.x); // 2 - обе переменные ссылаются на один объектJs json (json в javascript)
5 2
Js данные (данные в javascript)
Эта разница критична при работе с данными: изменение объекта через одну переменную отражается на всех остальных ссылках.
Как определить тип значения?
Для проверки типа применяется оператор typeof. Он возвращает строку с названием типа.
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' - историческая ошибка
console.log(typeof Symbol('id'));// 'symbol'
console.log(typeof 123n); // 'bigint'
console.log(typeof {}); // 'object'
console.log(typeof []); // 'object'
Js значение (значения в javascript)
Проблема: typeof null возвращает 'object', что вводит в заблуждение. Для точного определения null следует использовать строгую проверку: value === null. Для массивов лучше применить Array.isArray().
Как преобразовать значение в другой тип?
Явное преобразование выполняется через функции String(), Number(), Boolean() или унарные операторы +, !!. Неявное преобразование происходит при использовании операторов (например, + со строкой, *, -).
// Явное
console.log(String(123)); // '123'
console.log(Number('456')); // 456
console.log(Boolean(0)); // false
console.log(!!'text'); // true
// Неявное
console.log('5' + 3); // '53' - строка
console.log('5' - 3); // 2 - число
console.log('5' * '2'); // 10Javascript let (оператор let в javascript)
Проблема: Некорректное преобразование даёт NaN (Not-a-Number). Например, Number('5a') → NaN. Для проверки на NaN используется Number.isNaN(), а не глобальная isNaN(), так как последняя преобразует аргумент в число перед проверкой.
В чем разница между undefined и null?
undefined означает, что значение не было присвоено. null - намеренное указание на отсутствие объекта.
let a;
console.log(a); // undefined
let b = null;
console.log(b); // null
console.log(undefined == null); // true (нестрогое равенство)
console.log(undefined === null); // false (строгое равенство)Js code (код на javascript)
Проблема: Нестрогое сравнение может скрыть разницу. Рекомендуется всегда использовать строгое равенство (=== и !==).
Что такое NaN и Infinity?
NaN появляется при ошибочных математических операциях (например, деление 0/0). Infinity - результат деления ненулевого числа на ноль.
console.log(0 / 0); // NaN
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(typeof NaN); // 'number'
console.log(Number.isNaN(NaN)); // true
console.log(isNaN('строка')); // true - но это не NaN, а строкаПроблема: isNaN() не различает NaN и нечисловые строки. Правильная проверка - Number.isNaN() (ES6).
Как работают строки и специальные символы?
Строки неизменяемы и могут содержать управляющие символы через обратную косую черту (\n, \t и др.). Шаблонные литералы позволяют встраивать выражения.
let str = 'Строка с \'кавычками\' и \n переносом';
let template = `Привет, ${2 + 3}!`;
console.log(str);
console.log(template);Строка с 'кавычками' и переносом Привет, 5!
Что такое Symbol и BigInt?
Symbol создаёт уникальный идентификатор, используется как ключ объекта. BigInt нужен для целых чисел произвольной точности.
let sym1 = Symbol('id');
let sym2 = Symbol('id');
console.log(sym1 === sym2); // false - уникальность
let big = 123456789012345678901234567890n; // cуффикс n
console.log(typeof big); // 'bigint'Как скопировать объект?
Поверхностное копирование: Object.assign() или spread-оператор. Глубокое копирование: JSON.parse(JSON.stringify(obj)) или structuredClone().
const original = { a: 1, b: { c: 2 } };
// Поверхностное
const shallow = { ...original };
shallow.b.c = 100;
console.log(original.b.c); // 100 - вложенный объект общий
// Глубокое (JSON)
const deep = JSON.parse(JSON.stringify(original));
deep.b.c = 200;
console.log(original.b.c); // 100 - независимоПроблема: JSON.parse(JSON.stringify()) не копирует функции, undefined, Symbol, а также не обрабатывает циклические ссылки. structuredClone() решает часть проблем, но доступен не во всех окружениях (Node.js 17+).
Расширенные примеры работы со значениями
Сравнение объектов и примитивов
Объекты сравниваются по ссылке, примитивы - по значению. Даже одинаковые по содержанию объекты считаются разными.
const objA = { x: 1 };
const objB = { x: 1 };
console.log(objA === objB); // false - разные ссылки
const objC = objA;
console.log(objA === objC); // true - одна ссылка
// Примитивы
console.log(1 === 1); // true
console.log('a' === 'a'); // true
false true true true
Неявное преобразование в условных конструкциях
В if все значения преобразуются в булевы. Falsy значения: false, 0, '', null, undefined, NaN. Все остальные - truthy.
if ('строка') {
console.log('truthy');
}
if (0) {
console.log('не выполнится');
}
if ({}) {
console.log('пустой объект - truthy');
}
truthy пустой объект - truthy
Использование Symbol для приватных свойств
Символы дают возможность создавать скрытые ключи, не конфликтующие с другими свойствами.
const secret = Symbol('секрет');
const obj = {
name: 'Открытый',
[secret]: 'Скрытый'
};
console.log(Object.keys(obj)); // ['name']
console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(секрет) ]
obj[secret]; // доступ только при наличии символа
['name'] [ Symbol(секрет) ]
BigInt: операции и ограничения
BigInt нельзя смешивать с обычными числами в арифметических операциях без явного преобразования.
let big = 10n;
// console.log(big + 5); // TypeError: Cannot mix BigInt and other types
let sum = big + BigInt(5); // 15n
console.log(sum.toString()); // '15'
// Деление с дробной частью отбрасывается
console.log(5n / 2n); // 2n (целая часть)
15 2n
Обработка NaN в цепочках вычислений
NaN распространяется: любая операция с NaN возвращает NaN. Необходима проверка перед использованием.
function safeMultiply(a, b) {
if (Number.isNaN(a) || Number.isNaN(b)) {
return null; // или другое значение по умолчанию
}
return a * b;
}
console.log(safeMultiply(NaN, 5)); // null
console.log(safeMultiply(3, 4)); // 12
null 12
Глубокое копирование с structuredClone
Современный способ - structuredClone() копирует даже циклические ссылки и поддерживает многие типы (Map, Set, ArrayBuffer).
const original = {
numbers: [1, 2, 3],
nested: { a: 1 },
date: new Date()
};
original.circular = original; // циклическая ссылка
const clone = structuredClone(original);
console.log(clone.numbers === original.numbers); // false
console.log(clone.circular === clone); // true (цикл сохранён)
false true