Обзор всех видов значений в языке программирования JS: от undefined до Object и BigInt

Раздел: JavaScript -> Основы JavaScript

Типы значений в 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');       // 10

Javascript 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

Значения в JavaScript - comments

En
Js значение (javascript)