Типы данных

В JavaScript 8 типов данных: 7 примитивных (string, number, boolean, null, undefined, symbol, bigint) и 1 ссылочный (object).

Зачем нужно

Понимание типов данных — фундамент. От типа зависит, какие операции доступны, как работает сравнение, как данные хранятся в памяти и передаются в функции.

Где используется

Каждая переменная в JavaScript имеет тип. Типы определяют поведение операторов, проверки условий, работу с API и структурами данных.

Предпосылки

Переменные

Примитивные типы

7 примитивов

// 1. string — строки
const name = 'Алиса';
const greeting = "Привет";
const template = `Привет, ${name}!`;

// 2. number — числа (целые и дробные)
const age = 25;
const price = 19.99;
const negative = -10;

// 3. boolean — логический
const isActive = true;
const isDeleted = false;

// 4. null — явное «ничего»
const empty = null;

// 5. undefined — значение не присвоено
let notAssigned;
console.log(notAssigned); // undefined

// 6. symbol — уникальный идентификатор
const id = Symbol('id');

// 7. bigint — большие целые числа
const huge = 9007199254740991n;

Свойства примитивов

// Примитивы неизменяемы (immutable)
let str = 'hello';
str[0] = 'H';        // Не сработает
console.log(str);     // 'hello'

// Примитивы сравниваются по значению
console.log(5 === 5);          // true
console.log('abc' === 'abc');   // true

// Примитивы копируются по значению
let a = 10;
let b = a;
b = 20;
console.log(a); // 10 — не изменилось

Ссылочный тип (Object)

// Все непримитивные значения — объекты
const user = { name: 'Алиса', age: 25 };
const colors = ['red', 'green', 'blue'];
const greet = function { return 'Привет'; };
const now = new Date();
const pattern = /\d+/g;

// Объекты сравниваются по ссылке
const obj1 = { a: 1 };
const obj2 = { a: 1 };
console.log(obj1 === obj2); // false — разные ссылки!

const obj3 = obj1;
console.log(obj1 === obj3); // true — одна ссылка

// Объекты копируются по ссылке
const original = { x: 1 };
const copy = original;
copy.x = 999;
console.log(original.x); // 999 — изменился оригинал!

Оператор typeof

// typeof возвращает строку с названием типа
console.log(typeof 'hello');     // "string"
console.log(typeof 42);          // "number"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof Symbol);    // "symbol"
console.log(typeof 42n);         // "bigint"

// Особые случаи (исторические баги)
console.log(typeof null);        // "object" — баг с 1995 года!
console.log(typeof );          // "object"
console.log(typeof {});          // "object"
console.log(typeof function{}); // "function" — подтип объекта

console.log(typeof NaN);         // "number" — NaN это число!

Проверка типов

Надёжные способы

// Проверка null
const value = null;
console.log(value === null); // true

// Проверка массива
console.log(Array.isArray([1, 2]));  // true
console.log(Array.isArray('hello')); // false

// Проверка NaN
console.log(Number.isNaN(NaN));     // true
console.log(Number.isNaN('hello')); // false

// Проверка числа (не NaN, не Infinity)
console.log(Number.isFinite(42));       // true
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite('42'));     // false

// Проверка целого числа
console.log(Number.isInteger(42));    // true
console.log(Number.isInteger(42.5));  // false

// Object.prototype.toString() — универсальный способ
function getType(value) {
  return Object.prototype.toString().call(value).slice(8, -1);
}

console.log(getType(42));         // "Number"
console.log(getType('hello'));    // "String"
console.log(getType(null));       // "Null"
console.log(getType());         // "Array"
console.log(getType({}));         // "Object"
console.log(getType(new Date)); // "Date"
console.log(getType(/regex/));    // "RegExp"

instanceof

// instanceof проверяет цепочку прототипов
console.log( instanceof Array);    // true
console.log({} instanceof Object);   // true
console.log(new Date instanceof Date); // true

// Не работает для примитивов
console.log('hello' instanceof String); // false
console.log(42 instanceof Number);      // false

Обёртки примитивов (Wrapper Objects)

// JS автоматически оборачивает примитивы в объекты для вызова методов
const str = 'hello';
console.log(str.toUpperCase()); // "HELLO"
// Под капотом: new String('hello').toUpperCase()

// Не создавай обёртки вручную!
const strObj = new String('hello');
console.log(typeof strObj);     // "object" — не "string"!
console.log(strObj === 'hello'); // false

// Иерархия:
// String, Number, Boolean — обёртки
// Symbol, BigInt — НЕ имеют конструкторов с new

Схема типов

Типы JavaScript
├── Примитивные (по значению)
│   ├── string    → "hello"
│   ├── number    → 42, 3.14, NaN, Infinity
│   ├── boolean   → true, false
│   ├── null      → null
│   ├── undefined → undefined
│   ├── symbol    → Symbol('id')
│   └── bigint    → 42n
│
└── Ссылочные (по ссылке)
    └── object
        ├── Object     → { key: 'value' }
        ├── Array      → [1, 2, 3]
        ├── Function   → function {}
        ├── Date       → new Date
        ├── RegExp     → /pattern/
        ├── Map/Set    → new Map
        ├── Error      → new Error
        └── ...

Частые ошибки

1. typeof null === "object"

// Всегда проверяй null явно
if (value !== null && typeof value === 'object') {
  // Точно объект, не null
}

2. Сравнение объектов по значению

// Неправильно
console.log([1, 2] === [1, 2]); // false

// Правильно: сравнивай содержимое
JSON.stringify([1, 2]) === JSON.stringify([1, 2]); // true (простые случаи)

3. Мутация через ссылку

function addItem(arr) {
  arr.push('new'); // Мутирует оригинал!
}
const list = ['a', 'b'];
addItem(list);
console.log(list); // ['a', 'b', 'new']

// Решение: создавай копию
function addItemSafe(arr) {
  return [...arr, 'new'];
}

Практика

  1. Определи тип каждого значения: 42, "42", true, null, undefined, ``, {}, Symbol, 42n
  2. Напиши функцию isObject(value), которая возвращает true только для объектов (не null, не массив)
  3. Покажи разницу между копированием примитива и объекта
  4. Используй Object.prototype.toString().call для определения типа 5 разных значений

Связанные темы

Ресурсы


🎓 Источник: 👶 JavaScript для начинающих 4. Значения и типы

  • 📅 2021-10-02 · YouTube
  • Тезисы: значение vs тип — это две оси. Тип определяет набор операций. Динамическая типизация = тип привязан к значению, а не к идентификатору

⚡ Источник: Как одни фантазируют на тему типов, а другие верят · AsForJS

  • 📅 2021-10-10 · YouTube
  • Тезисы:
    • Миф "примитивы передаются по значению, объекты — по ссылке" не соответствует спеке
    • В ECMAScript есть primitive value и Reference — но Reference это про идентификатор, не про "передачу"
    • Когда вы пишете let a = 5; let b = a — это не "копирование значения 5", а связывание идентификатора b с тем же значением 5
    • Значения примитивов уникальны и неизменяемы — само число 5 одно на всех

⚡ Источник: Я тип простой - я говорю стихами · AsForJS

  • 📅 2023-03-29 · YouTube
  • Тезисы: обзор всех типов спецификации ECMAScript — Language Types vs Specification Types (Reference, Completion Record). typeof для null = "object" это исторический баг V0

⚡ Источник: Почему в JavaScript прибавить число к обьекту - это круто · AsForJS

  • 📅 2023-05-18 · YouTube
  • Тезисы: {} + 1 запускает ToPrimitive[[ToPrimitive]]Symbol.toPrimitive/valueOf/toString. Это не баг, а гибкость семантики