JavaScript собеседование: Как создать полную копию объекта?

Давайте вместе рассмотрим ответ на этот весьма специфичный для JavaScript вопрос. С ним часто можно столкнуться на собеседованиях на позицию Frontend-разработчика. Статья будет особенно полезна, если вы готовитесь к собеседованию или начинаете глубже погружаться в JS.

Многие из нас, кто участвовал в разработке особенно крупных проектов, наверняка сталкивались с библиотеками JavaScript, такими как Lodash.js, Underscore.js. Упомянутые библиотеки предоставляют вспомогательные функции для вещей, которые не встроены в JavaScript. Одна из этих функций — глубокое копирование объектов в JavaScript. Многие из нас знают, как копировать объекты, у которых есть только один уровень вложенности. Как быть если объект содержит несколько уровней вложенности? В JavaScript нет встроенного способа скопировать этот объект так, чтобы созданная копия была полной копией оригинального объекта.

Многим из вас может быть интересно, почему задают этот вопрос? И какой в нем кроется подвох? Если у нас есть вспомогательные библиотеки, почему бы спокойно их не использовать? И вы абсолютно правы. Нам действительно необходимо их использовать. Но написание такой базовой функции станет проверкой на то как вы способны применять ваши фундаментальные знания, которые у вас должны присутствовать.

Перейдем к режиму решения задачи 👨‍💻⚔️ Но сначала давайте разберемся с правильностью ее постановки.

Итак, что имеется ввиду: Создайте полную копию объекта? 

Ответ: это глубокая копия, копия которая продублирует каждый объект на пути копирования.

Вот пример использования функции, которая принимает объект в качестве аргумента и возвращает полную копию этого объекта.

// Signature
function copyObject(source) {

}

// Usage
const source = {
    a: 10,
    b: 20,
    c: {
        d: 30
    }
}

const target = copyObject(source);

Прежде чем еще больше углубиться в вопрос, я настоятельно рекомендую вам не искать готовых решений в интернете, а  попробовать решить данную задачу самостоятельно.

Несколько советов:

  • Забудьте о вложенности. Попробуйте  сначала скопировать каждый ключ и значение.
  • Затем подумайте, как определить, является ли значение самим объектом, и что с ним делать.

И последний, самый главный совет: декомпозиция — разбивайте задачу посложнее и объемнее на мелкие подзадачи. Это совсем несложно сделать, если внимательно прочитать описание задачи.

Само решение:

Начнем с того, что просто вернем новый объект. Вот так:

function copyObject(source) {
    var target = {};

    return target;
}

Далее задача требует от нас получить глубокую копию объекта. Но прежде чем напрямую перейти к глубокому копированию, давайте сначала напишем простое решение для копирования каждого значения ключа для одного уровня вложенности. 

Что нам для этого потребуется?

  • Нам нужно получить все ключи исходного объекта.
  • Нам нужно скопировать все эти ключи в конечный объект.
function copyObject(source) {
    var target = {};
    const keys = Object.keys(source);
    keys.forEach(key => {
        target[key] = source[key];
    });

    return target;
}

Чудесно! Мы решили проблему для упрощенного варианта с ключами. 

Теперь пришло время подумать о вложенности. С помощью оператора typeof мы можем узнать является ли значение, соответствующее текущему ключу, объектом. И когда мы знаем, что текущее значение является объектом, мы можем создать его копию методом, известным как рекурсия (узнать больше о рекурсии здесь).

Решение задачи будет выглядеть примерно так:

function copyObject(source) {
    var target = {};

    // Getting source object keys
    const keys = Object.keys(source);
    keys.forEach(key => {
        // Checking if current value is an object
        if (typeof source[key] === "object") {
            // Calling our function recursively for current value
            target[key] = copyObject(source[key]);
        } else {
            // Directly assigning the value
            target[key] = source[key];
        }
    });

    return target;
}

Ура! Сейчас наше решение уже похоже на рабочее решение. Однако, в нем все еще присутствуют незначительные погрешности, такие, как обработка значений массивов и функций в объектах. Напишите код, который позволяет копировать массивы и функции и опубликуйте его в комментариях.

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Scroll to Top