Clone Javascript object > Snowcore’s блог - Magento разработчик

Clone Javascript object

В javascript объекты передаются и копируются по ссылке. Рассмотрим пример:

// Создаем объект с единственным полем number
var obj = { number: 1 };

// Копируем объект
var copy = obj;
copy.number = 777;

alert(obj.number);

В результате выполнения данного кода на экран будет выведено число 777 (а не 1 как ожидалось). Переменные obj и copy - одна и та же ссылка.

Как передать объект по значению? Нам нужна функция clone.

Я пробовал множество функций, но в них было много недостатков (не копировались методы объекта, или массивы). В итоге нашлась хорошая реализация (из фреймворка ExtJS). Я немного подправил эту функцию, вот результат:

function clone(o) {
 if(!o || ‘object’ !== typeof o)  {
   return o;
 }
 varc = ‘function’ === typeof o.pop ? [] : {};
 var p, v;
 for(p in o) {
 if(o.hasOwnProperty(p)) {
  v = o[p];
  if(v && ‘object’ === typeof v) {
    c[p] = clone(v);
  }
  else {
    c[p] = v;
  }
 }
}
 return c;
}

Проверяем действие функции:

var o = { a:1, get:function(){ alert(this.arr[1]);}, arr: [1,2,3] };
var c = clone(o); // делаем клон объекта

c.arr[0] = 77;
c.arr[1] = 88;
c.arr[2] = 99;

// Значения остались прежними
alert(o.arr[0]); // 1
alert(o.arr[1]); // 2
alert(o.arr[2]); // 3

// Методы тоже были скопированы
c.get(); // 88
o.get(); // 2

Как видно из примера, функция clone скопировала объект o вместе со всеми его свойствами и методами.

Пользуйтесь на здоровье :)

19 Responses

  1. Cidor Says:

    Согласен. Так удобнее.

  2. admin Says:

    @ evol1980:

    Мой блог - это, в первую очередь ресурс для меня, и размещать чужие статьи здесь я не собираюсь.

  3. Фанат Says:

    Я вам очень благодарен, мне понравилось.

  4. evol1980 Says:

    oj sorri oshibsa

  5. evol1980 Says:

    opat vernylsa na etot sajt ctob skazat spasibo :)

  6. Octane Says:

    На самом деле, ситуаций, когда нужна одна лишь функция «clone(…)», практически не бывает. В реальных проектах обычно есть функция «extent», а на её основе строят функцию «clone».
    function extend(obj, hash) {
    for(var key in hash)
    if(hash.hasOwnProperty(key))
    obj[key] = hash[key];
    }

    function clone(obj) {
    return extend({}, obj);
    }
    То есть для копирование объекта, создаётся новый объект и расширяется методами и атрибутами переданного.

  7. Voland Says:

    Хорошая статья. Спасибо =)

    2Octane: а функция extend не должна возвращать объект??

    return obj;

  8. iln Says:

    не должна - объекты передаются по ссылки.

  9. ШкодеРРу » Blog Archive » Клонирование объектов в JavaScript Says:

    […] повторное использование кода - это хорошо, я выгуглил кое-что существующее. Однако, меня не устроило то, что эта реализация не […]

  10. Shcoder Says:

    Tnanx! Немножко модифицировал.
    http://shcoder.ru/2009/01/23/javascript-utils-clone/

  11. Pufik Says:

    Хм… читаю блоги по близкой тематике, а к Вам ни разу не наведывалась, добавила в избранное, я теперь Ваш постоянный читатель :)

  12. Алексей Says:

    Не понял как сделать, что бы работало 2 копии одного объекта но с разными свойствами?

    У меня работал объект, который подгружал контент в div, теперь пытаюсь использовать этот же класс, что бы подгрузить во второй div.
    Пишу:
    engine.init(null, $(”#d1″), 0 );
    var engine2 = engine;
    engine2.init(null, $(”#d2″), 1);

    А контент выводит во втором div, который должен быть в первом, а в первом вообще пусто.

  13. Дмитрий Says:

    Встретил в гугловском коде похожую функцию (obj target object, vals source object):
    var setVals = function (obj, vals) {
    if (obj && vals) {
    for (var x in vals) {
    if (vals.hasOwnProperty(x)) {
    if (obj[x] && typeof vals[x] === ‘object’) {
    obj[x] = setVals(obj[x], vals[x]);
    } else {
    obj[x] = vals[x];
    }
    }
    }
    }
    return obj;
    };

  14. ddosia Says:

    спасибо за пример функции для клонирования, есть небольшое добавление:
    функция клонирует только свойства и методы объекта, но оставляет неизменным его прототип.

    можно заменить:
    var c = ‘function’ === typeof o.pop ? [] : {};

    на:
    var c = []
    if (o.constructor !== Array) {
    function P () {}
    P.prototype = o.constructor.prototype;
    c = new P();
    }

  15. Slaffko Says:

    Через JQuery тоже можно вот так:
    $.extend(target, object1, …, objectN);

  16. dejavu Says:

    http://oranlooney.com/functional-javascript/

    Клонируйте просто ;)

  17. Константин Says:

    2 дня убил, пока разобрался
    в jquery есть метод extend, которая объединяет массивы в один объект.
    Чтобы создать точную копию - первым элементом нужно задать пустой объект {}.
    Чтобы рекурсивно скопировать все свойства - первым параметром передается true;
    То есть готовая функция выглядит как
    a=$.extend(true,{},b)

  18. Paul Loyd Says:

    Я думаю следует обновить статью до актуального состояния, добавив копирование геттеров и сеттеров.

Оставить комментарий

I'm not spammer :)

Внимание: Комментарии проходят ручную модерацию