Яндекс.Метрика

Клонирование объектов в JavaScript

При написании своих работ на JS часто приходится создавать копии своих объектов, но вот не задача, в JavaScript не существует функции прямо с таким назначением. Если быть точнее она существует но работает иначе.

Для библиотек и новых версий

JQuery

Не глубокая копия объектов

var copiedObject = $.extend({}, originalObject);

Для новых браузеров (ES6 и выше)

Не глубокая копия объектов

var copiedObject = Object.assign({}, originalObject);

Для версий

JSON

Глубокая копия объектов, но нагруженная

var copiedObject = JSON.parse(JSON.stringify(originalObject));

Альтернативный (нативный сопособ)

В языке JS есть метод изначально задуманный для создания нового объекта, на основании другого.

var newObject = Object.create(obj);

Таким способом вы получаете новый пустой объект унаследованный, у объекта obj. И все свойства наследуемого объекта будут доступны его наследнику.

var foo = { a : 1 };
var bar = Object.create(foo);
foo.a; // 1
bar.a; // 1
foo.a = 2;
bar.a; // 2 - изменения от наследуемого объекта передались наследнику
bar.a = 3;
foo.a; // 2 - обратный эффект от наследников отсутствует
foo.a = 4;
bar.a; // 3 - так как свойство уже определено у объекта bar, оно не будет наследоватся

В такой ситуации вы можете столкнутся с неприятностью передачи вашего значения.

var foo = { a : 1 };
var bar = Object.create(foo);
JSON.stringify(foo); // "{"a":4}"
bar.a; // 1
JSON.stringify(bar); // "{}" - вернётся пустой массив, так как свойство не принадлежит объекту bar

Чтобы это исправить можно доработать функцию преобразования.

Object.prototype.toJSON = function() {
    var tmp = {};

    for(var key in this) {
        if(typeof this[key] !== 'function')
            tmp[key] = this[key];
    }

    return tmp;
}

Функция JSON.stringify перед своей обработкой вызывает метод .toJSON у всех объектов. После того как мы его переопределили, он будет копировать все наследуемые свойства нашего объекта для сериализации. При этом наш объект bar останется неизменным.