No public Twitter messages.


Этот блог устарел и, скорее всего, больше не будет обновляться. В ближайшем будущем он переедет сюда.
1 августа 2011 // Веб-разработка

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

Разрабатываю тут на работе шаблонизатор (эпопея, реально) на js и в одной из рекурсий столкнулся с проблемой — создаваемый объект не является совершенно новым, а лишь является ссылкой оригинального, что приводило к некоторым косякам.

var obj = { a: 1 };
var obj1 = obj;
obj1.a = 0; // при этом obj.a также становится равным 0.

Соответственно потребовалось нечто, что смогло бы создавать копию объекта без ссылки на оригинальный. После недолгого поиска было найдено решение — волшебная функция uneval (обратное от функции eval). Выглядит оно потрясающе элегантно:

function clone(o) {
return eval(uneval(o));
}

Радость была бы абсолютной не узнай я, что функция uneval не работает не только в IE, но и в Опере, и даже в WebKit. Печаль была безгранична. В замен этому решению было придумано собственное, не сильно сложнее:

function clone(o) {
var obj = {};
for(var i in o){
obj[i] = o[i];
}
return obj;
}

Очевидно — немного криво, поскольку не учитывается тип входящего объекта (вдруг это массив или строка?). Протестил и опечалился, в рекурсии оно почему-то опять портит воздух. Даже после всего этого я не стал унывать и спустя выходные решение нашлось внезапно в начале рабочего дня:

function clone(o) {
return eval("("+JSON.stringify(o)+")");
}

Честно говоря плохо понимаю, что это за глобальный объект JSON и откуда он взялся (вероятно какая-то дыра в моём убогом самообразовании), но его замечательный метод stringify выполняет примерно то же, что и print_r в php. При этом этот способ вполне кроссбраузерен — протестил в IE9, FF5, Opera 11 и Chrome 11 (более ранние версии проверять лень). Придётся убить заготовку поста про мой самописный скрипт print_r для js.

P.S. Коллега подсказал функцию которую он использовал сам (с учётом всякого), может пригодиться:

function clone(obj)
{
if(obj == null || typeof(obj) != 'object')
{
return obj;
}
var temp = {};
for(var key in obj)
{
temp[key] = clone(obj[key]);
}
return temp;
}

теги: , , , , ,

5 комментариев.



  • twitter
  • rss
  • хабр
  • жежека
  • ластфм