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

Что можно клонировать в JSON из объекта?

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

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Что можно клонировать в JSON из объекта?

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

Совместимые с JSON типы данных

Следующие типы данных успешно клонируются через JSON:

  • Примитивы:
    *   `string`, `number`, `boolean`, `null`.
  • Структуры данных:
    *   Объекты (`{}`) и массивы (`[]`), содержащие только JSON-совместимые значения.
  • Вложенные структуры: Любая комбинация объектов и массивов с допустимым содержимым.

Пример успешного клонирования:

const original = {
  name: "Alice",
  age: 30,
  isAdmin: true,
  hobbies: ["reading", "coding"],
  address: {
    city: "Moscow",
    zip: 101000
  },
  scores: [95, 87, null]
};

const cloned = JSON.parse(JSON.stringify(original));
console.log(cloned.name); // "Alice"
console.log(cloned.hobbies === original.hobbies); // false - это действительно глубокая копия
console.log(cloned.scores); // [95, 87, null]

НЕсовместимые с JSON типы данных (будут потеряны или преобразованы)

Эти типы нельзя корректно клонировать через JSON.parse(JSON.stringify()):

  1. Функции (methods): Полностью игнорируются.

    const obj = { greet: () => "Hello" };
    const cloned = JSON.parse(JSON.stringify(obj));
    console.log(cloned.greet); // undefined
    
  2. undefined: Значения undefined в объектах пропадают, в массивах преобразуются в null.

    const obj = { a: 1, b: undefined };
    const arr = [1, undefined, 3];
    const clonedObj = JSON.parse(JSON.stringify(obj));
    const clonedArr = JSON.parse(JSON.stringify(arr));
    console.log(clonedObj); // { "a": 1 }
    console.log(clonedArr); // [1, null, 3]
    
  3. Symbol: Игнорируются.

    const obj = { key: Symbol('id') };
    const cloned = JSON.parse(JSON.stringify(obj));
    console.log(cloned); // {}
    
  4. Циклические ссылки: Вызовут ошибку.

    const obj = {};
    obj.self = obj;
    // JSON.stringify(obj); // TypeError: Converting circular structure to JSON
    
  5. Специальные объекты JavaScript:

    *   **`Date`:** Преобразуется в строку (потеряется объектный тип).
    ```javascript
    const obj = { date: new Date() };
    const cloned = JSON.parse(JSON.stringify(obj));
    console.log(typeof cloned.date); // "string"
    console.log(cloned.date); // "2024-05-24T10:30:00.000Z"
    ```
    *   **`Map`, `Set`, `WeakMap`, `WeakSet`:** Сериализуются как пустой объект `{}`.
    *   **`RegExp`:** Сериализуется как пустой объект `{}`.
    *   **`Error`:** Сериализуется только в объект с перечисляемыми свойствами (например, `message`), но теряет прототип и стектрейс.
    *   **`Promise`, `Proxy`:** Поведение непредсказуемо, обычно пустой объект.
    *   **`ArrayBuffer`, `TypedArray`, `Blob`, `File`:** Не клонируются.

  1. Геттеры/сеттеры и неперечисляемые свойства: JSON.stringify работает только с собственными перечисляемыми свойствами объекта. Значения, получаемые через геттер, будут сериализованы, но сам аксессор (функция) — нет.

Когда использовать JSON-клонирование?

  • Для создания глубокой копии простых структур данных (DTO, состояние приложения).
  • Когда нужно быстро обойтись без сторонних библиотек.
  • Для сравнения объектов по содержимому (JSON.stringify(obj1) === JSON.stringify(obj2)).

Альтернативы для полного клонирования

  • Поверхностное клонирование: Object.assign(), spread-оператор (...).
  • Глубокое клонирование:
    *   **Рекурсивная функция,** самостоятельно обрабатывающая все типы.
    *   **`structuredClone()` (современный стандарт):** Поддерживает больше типов (Date, Map, Set, ArrayBuffer и даже циклические ссылки), но всё ещё не клонирует функции, DOM-узлы или дескрипторы свойств.
    ```javascript
    const original = { date: new Date(), map: new Map([['key', 'value']]) };
    const cloned = structuredClone(original);
    console.log(cloned.date instanceof Date); // true
    console.log(cloned.map instanceof Map); // true
    ```
    *   **Сторонние библиотеки:** Lodash (`_.cloneDeep()`).

Вывод: JSON-клонирование — это быстрый и эффективный способ для простых, сериализуемых данных. Оно бесполезно для объектов, содержащих методы, специальные встроенные объекты или циклические ссылки. Для сложных сценариев предпочтительнее использовать structuredClone() или специализированные библиотеки.

Что можно клонировать в JSON из объекта? | PrepBro