← Назад к вопросам

Какие плюсы и минусы копирования объекта через JSON?

2.0 Middle🔥 171 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Копирование объекта через JSON

JSON способ — это техника для глубокого копирования объектов через JSON.stringify() и JSON.parse(). Это просто, но имеет серьёзные ограничения.

Как это работает

const original = { name: 'John', age: 30, address: { city: 'NY' } };

// Копирование через JSON
const copy = JSON.parse(JSON.stringify(original));

copy.name = 'Jane';
copy.address.city = 'LA';

console.log(original.name);            // 'John' (не изменился)
console.log(original.address.city);    // 'NY' (не изменился)

Плюсы

1. Очень просто

// Одна строка кода
const deepCopy = JSON.parse(JSON.stringify(obj));

2. Работает для обычных объектов и массивов

const user = {
  name: 'Иван',
  age: 30,
  skills: ['JS', 'React', 'Node.js'],
  address: {
    city: 'Москва',
    country: 'Россия'
  }
};

const copy = JSON.parse(JSON.stringify(user));
// Полное глубокое копирование

3. Создаёт полностью независимую копию

const arr = [[1, 2], [3, 4]];
const copy = JSON.parse(JSON.stringify(arr));

copy[0][0] = 999;
console.log(arr[0][0]);  // 1 (не изменился)

4. Работает быстро для большинства случаев

const large = { /* большой объект */ };
const copy = JSON.parse(JSON.stringify(large));  // Быстро

Минусы

1. Теряются функции

const obj = {
  name: 'John',
  greet: function() { return 'Hi'; }  // Функция
};

const copy = JSON.parse(JSON.stringify(obj));
console.log(copy.greet);  // undefined (функция потеряна!)

2. Теряются undefined значения

const obj = { name: 'John', email: undefined };

const copy = JSON.parse(JSON.stringify(obj));
console.log(copy);  // { name: 'John' } (email исчез!)

3. Теряются символы (Symbol)

const sym = Symbol('key');
const obj = { [sym]: 'value' };

const copy = JSON.parse(JSON.stringify(obj));
console.log(copy[sym]);  // undefined (символ потерян!)

4. Теряются классы и прототипы

class User {
  constructor(name) { this.name = name; }
  greet() { return `Hi, ${this.name}`; }
}

const user = new User('John');
const copy = JSON.parse(JSON.stringify(user));

console.log(copy instanceof User);  // false
console.log(copy.greet);            // undefined (метод потерян)

5. Date становятся строками

const obj = { createdAt: new Date('2024-01-15') };

const copy = JSON.parse(JSON.stringify(obj));
console.log(copy.createdAt);        // "2024-01-15T00:00:00.000Z" (строка!)
console.log(typeof copy.createdAt); // 'string' (не Date)

6. NaN, Infinity становятся null

const obj = { value: NaN, max: Infinity };

const copy = JSON.parse(JSON.stringify(obj));
console.log(copy);  // { value: null, max: null }

7. Set, Map теряются

const obj = {
  set: new Set([1, 2, 3]),
  map: new Map([['key', 'value']])
};

const copy = JSON.parse(JSON.stringify(obj));
console.log(copy);  // { set: {}, map: {} } (пусто!)

8. Циклические ссылки вызывают ошибку

const obj = { name: 'John' };
obj.self = obj;  // Циклическая ссылка

const copy = JSON.parse(JSON.stringify(obj));
// TypeError: Converting circular structure to JSON

9. Может быть медленно на очень больших объектах

const huge = { /* миллионы вложенных объектов */ };

// Может заметно замедлить приложение
const copy = JSON.parse(JSON.stringify(huge));

Примеры проблем

Потеря методов:

class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }
  
  validate() {
    return this.email.includes('@');
  }
}

const user = new User('John', 'john@example.com');
const copy = JSON.parse(JSON.stringify(user));

copy.validate();  // TypeError: copy.validate is not a function

Проблема с Dates:

const event = {
  name: 'Meeting',
  date: new Date('2024-12-25')
};

const copy = JSON.parse(JSON.stringify(event));
console.log(copy.date.getTime());  // TypeError: copy.date.getTime is not a function

Альтернативы

1. structuredClone (современный стандарт)

const original = { name: 'John', date: new Date() };
const copy = structuredClone(original);

// Работает даже с Date, но не работает с функциями
copy.date instanceof Date;  // true

2. Spread оператор (поверхностное копирование)

const original = { name: 'John', address: { city: 'NY' } };
const copy = { ...original };

// Только первый уровень скопирован
copy.address.city = 'LA';
console.log(original.address.city);  // 'LA' (изменился!)

3. Object.assign (поверхностное копирование)

const copy = Object.assign({}, original);
// То же самое что spread

4. Lodash функции

import { cloneDeep } from 'lodash';

const copy = cloneDeep(original);
// Глубокое копирование, сохраняет типы

5. structuredClone + вспомогательная функция

function deepClone(obj) {
  if (typeof obj !== 'object' || obj === null) return obj;
  
  try {
    return structuredClone(obj);
  } catch (e) {
    // Если есть функции или циклические ссылки
    return JSON.parse(JSON.stringify(obj));
  }
}

Когда использовать JSON способ

Используй когда:

  • Работаешь с простыми данными (примитивы, массивы, объекты)
  • Нет функций, методов, классов
  • Нет Date, Set, Map, Symbol
  • Нет циклических ссылок
  • Скорость разработки важнее

НЕ используй когда:

  • Объект содержит методы или функции
  • Нужна Date (станет строкой)
  • Используются классы
  • Есть Set, Map, Symbol
  • Есть циклические ссылки

Вывод

JSON способ копирования:

  • ✅ Просто и быстро
  • ❌ Теряет функции, методы, типы
  • ❌ Проблемы с Date, Set, Map
  • ❌ Не работает с циклическими ссылками

Для продакшена лучше использовать structuredClone() или библиотеки типа lodash.

Какие плюсы и минусы копирования объекта через JSON? | PrepBro