Какие типы данных в JavaScript относятся к сложным?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Какие типы данных в JavaScript относятся к сложным?
В JavaScript существует разделение между примитивными и сложными (ссылочными) типами данных. Это важное различие влияет на то, как данные хранятся, копируются и сравниваются.
Краткое резюме
Примитивные типы (6):
- String
- Number
- Boolean
- Undefined
- Null
- Symbol (BigInt в новых версиях)
Сложные типы (ссылочные):
- Object
- Array
- Function
- Date
- RegExp
- Map, Set, WeakMap, WeakSet
1. Object (Объект)
Object — базовый тип, из которого наследуются все остальные сложные типы:
// Объект
const user = {
id: 1,
name: 'John',
email: 'john@example.com'
};
// При присваивании копируется ссылка, не данные
const user2 = user;
user2.name = 'Jane';
console.log(user.name); // "Jane" — оба указывают на один объект
// Поверхностная копия
const user3 = { ...user }; // или Object.assign({}, user)
user3.name = 'Bob';
console.log(user.name); // "Jane" — теперь отдельные объекты
// Глубокая копия
const user4 = JSON.parse(JSON.stringify(user));
const user5 = structuredClone(user); // Современный способ
Особенности:
- Хранится по ссылке в памяти
- Изменяемо (mutable)
- Сравнение по ссылке, не по значению
2. Array (Массив)
Array — специализированный объект с индексированным доступом:
// Массив — это объект с числовыми ключами
const arr = [1, 2, 3];
console.log(typeof arr); // "object"
console.log(arr instanceof Array); // true
// Это эквивалентно
const obj = { 0: 1, 1: 2, 2: 3 };
// Тоже копируется по ссылке
const arr2 = arr;
arr2[0] = 99;
console.log(arr[0]); // 99
// Поверхностная копия
const arr3 = [...arr]; // или arr.slice(), arr.concat()
arr3[0] = 1;
console.log(arr[0]); // 99 — разные массивы
// Глубокая копия для вложенных массивов
const nested = [[1, 2], [3, 4]];
const copy = JSON.parse(JSON.stringify(nested));
const copy2 = structuredClone(nested);
Особенности:
- Подтип Object
- Индексированный доступ
- Свойство .length
- Полезные методы: map, filter, reduce, forEach и т.д.
3. Function (Функция)
Function — тоже объект, вызываемый код:
// Функции — объекты
function greet(name) {
return `Hello, ${name}`;
}
console.log(typeof greet); // "function"
console.log(greet instanceof Function); // true
// Функции можно присваивать переменным
const sayHi = greet;
console.log(sayHi('John')); // "Hello, John"
// Функции имеют свойства
greet.description = 'Greeting function';
greet.version = '1.0';
// Стрелочные функции
const add = (a, b) => a + b;
// Конструктор функции
const multiply = new Function('a', 'b', 'return a * b');
console.log(multiply(3, 4)); // 12
// Функции как значения
const operations = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b
};
Особенности:
- Первокласс (first-class citizen)
- Может быть параметром
- Может быть возвращаемым значением
- Может иметь свойства
4. Date (Дата)
Date — объект для работы с датой и временем:
// Создание
const now = new Date();
const date1 = new Date('2024-03-29');
const date2 = new Date(2024, 2, 29); // месяц 0-indexed
const date3 = new Date(1711737600000); // timestamp в мс
// Методы
console.log(date1.getFullYear()); // 2024
console.log(date1.getMonth()); // 2 (март, 0-indexed)
console.log(date1.getDate()); // 29
console.log(date1.getTime()); // timestamp
// Манипуляция
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
// Сравнение
const isAfter = date1 > date2;
const isSame = date1.getTime() === date2.getTime();
// Форматирование
console.log(now.toString()); // "Sat Mar 29 2024 ..."
console.log(now.toISOString()); // "2024-03-29T...Z"
console.log(now.toLocaleString('ru-RU')); // "29.03.2024, ..."
Особенности:
- Мутабельна (изменяемая)
- Хранит миллисекунды
- Сравнение — трудное, используй .getTime()
5. RegExp (Регулярное выражение)
RegExp — объект для поиска и замены текста:
// Создание
const regex1 = /hello/i; // case-insensitive
const regex2 = new RegExp('hello', 'i');
// Методы
const text = 'Hello, World!';
console.log(regex1.test(text)); // true
console.log(regex1.exec(text)); // Match array или null
// String методы
console.log(text.match(regex1)); // ["Hello"]
console.log(text.replace(regex1, 'Hi')); // "Hi, World!"
console.log(text.split(/\s/)); // ["Hello,", "World!"]
// Сложное регулярное выражение
const email = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
console.log(email.test('john@example.com')); // true
console.log(email.test('invalid-email')); // false
Особенности:
- Мутабельна (свойство lastIndex)
- Флаги: g (global), i (ignoreCase), m (multiline), s, u, y
- Производительность может быть критична
6. Map (Словарь)
Map — более надёжная альтернатива объекту для хранения пар ключ-значение:
// Создание
const map = new Map();
const map2 = new Map([['a', 1], ['b', 2]]);
// Методы
map.set('name', 'John');
map.set('age', 30);
map.set({}, 'object key'); // Даже объект может быть ключом
console.log(map.get('name')); // "John"
console.log(map.has('age')); // true
console.log(map.size); // 3
map.delete('age');
map.clear();
// Итерация
for (const [key, value] of map) {
console.log(key, value);
}
map.forEach((value, key) => {
console.log(key, value);
});
// Отличие от объекта
const obj = {};
const mapTest = new Map();
obj[{id: 1}] = 'object'; // ключ преобразуется в "[object Object]"
mapTest.set({id: 1}, 'map'); // ключ остаётся объектом
Преимущества перед Object:
- Ключи могут быть любыми типами
- Сохраняет порядок вставки
- Есть .size вместо Object.keys().length
- Лучше для большого количества пар
- Итерация встроена (не нужен Object.entries)
7. Set (Множество)
Set — коллекция уникальных значений:
// Создание
const set = new Set();
const set2 = new Set([1, 2, 3, 1, 2]);
console.log(set2); // Set(3) { 1, 2, 3 }
// Методы
set.add(1);
set.add(2);
set.add(1); // Дубликат, не добавляется
console.log(set.has(1)); // true
console.log(set.size); // 2
set.delete(1);
set.clear();
// Удаление дубликатов из массива
const arr = [1, 2, 2, 3, 3, 3];
const unique = [...new Set(arr)];
console.log(unique); // [1, 2, 3]
// Сравнение объектов (внимание!)
const set3 = new Set();
set3.add({id: 1});
set3.add({id: 1});
console.log(set3.size); // 2 (разные объекты в памяти)
Используется для:
- Удаления дубликатов
- Проверки уникальности
- Математические операции (объединение, пересечение)
8. WeakMap и WeakSet
WeakMap и WeakSet — версии с «слабыми» ссылками:
// WeakMap — ключи только объекты, могут быть GC
const weakMap = new WeakMap();
let obj = {id: 1};
weakMap.set(obj, 'value');
console.log(weakMap.get(obj)); // "value"
obj = null; // Объект может быть удалён из памяти
// WeakSet — для уникальных объектов
const weakSet = new WeakSet();
let obj2 = {id: 2};
weakSet.add(obj2);
console.log(weakSet.has(obj2)); // true
obj2 = null; // Объект может быть удалён
// Ограничения
// Нет .size, нельзя итерировать
// Используются для metadata, private данных
Сравнение примитивов и сложных типов
// Примитив — копируется значение
let a = 5;
let b = a;
b = 10;
console.log(a); // 5
// Сложный тип — копируется ссылка
let obj1 = {value: 5};
let obj2 = obj1;
obj2.value = 10;
console.log(obj1.value); // 10
// Сравнение
console.log(5 === 5); // true (значения)
console.log({a: 1} === {a: 1}); // false (разные ссылки)
const o = {a: 1};
console.log(o === o); // true (одна ссылка)
Таблица сравнения
| Тип | Хранение | Мутабельность | Сравнение | Использование |
|---|---|---|---|---|
| Object | По ссылке | Да | По ссылке | Данные |
| Array | По ссылке | Да | По ссылке | Списки |
| Function | По ссылке | Нет | По ссылке | Код |
| Date | По ссылке | Да | По ссылке | Время |
| RegExp | По ссылке | Да | По ссылке | Поиск |
| Map | По ссылке | Да | По ссылке | Пары ключ-значение |
| Set | По ссылке | Да | По ссылке | Уникальные значения |
| WeakMap | По ссылке | Да | По ссылке | Metadata |
| WeakSet | По ссылке | Да | По ссылке | Трекинг объектов |
Практические советы
- Помни о копировании — при работе со сложными типами
- Используй structuredClone() для глубокой копии
- Map вместо Object для произвольных ключей
- WeakMap для private данных в классах
- Set для уникальности элементов
- Сравнивай правильно — {a:1} !== {a:1}, но они эквивалентны по значению