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

Может кто-нибудь объяснить, почему obj возвращается {a:2} вместо {a:1} в этом случае?

var obj = {a:1};
var data = {b:obj};
data.b.a = 2;

console.log(obj); // {a:2}

3 ответа

Объекты в javascript являются ссылочными, поэтому при изменении одной ссылки вы меняете их. Смысл этого в том, что вы только что создали неглубокую копию, вам нужно сделать глубокий клон.

Глубокое копирование может быть сделано с помощью jQuery следующим образом:

// Deep copy
var newObject = jQuery.extend(true, {}, obj);

Прочитайте, почему я использовал jQuery: Какой самый эффективный способ глубокого клонирования объекта в JavaScript?
(Это Джон Резиг здесь, на Stackru...)

В этом случае вы не клонируете объекты, а устанавливаете дополнительные ссылки на одну и ту же переменную. data.obj.a и obj.a указывают на одну и ту же область памяти. Строка 3 устанавливает это значение памяти в 2.

Чтобы сделать глубокий клон, попробуйте это:

var data = JSON.parse(JSON.stringify(obj));

Если вы используете браузер, полученный из NS, такой как FF:

var data = { b: eval ( obj . toSource ( ) ) } ;

или же

var data = { b: eval ( uneval ( obj ) ) } ;

если не:

Object . function . deepClone = function(){ 
/*
     highly non-trivial to accommodate objects like:
              animal=123; animal.beastly=432;                                        ie. object "overloading"
              monster = new ( function ( ) { this . this = this } ) ( )            ie. self-referential / recursive
      Note: JSON cannot do these  but  toSource () can handle recursive structures
      alert ( new ( function ( ) { this . this = this } ) ( )  . toSource ( )  );
                                                                                                                   ie.    #1={this:#1#}
      alert ( new ( function ( ) { this [ this ] = this } ) ( )  . toSource ( )  );
                                                                                                                   ie.     #1={'[object Object]':#1#}
      alert ( new ( function ( ) { this [ this . toSource ( )  ] = this } ) ( )  . toSource ( )  );
                                                                                                                   ie.     #1={'({})':#1#}
      alert (    (     #1 = { '({})' : #1# }      )   . toSource ( )  );
                                                                                                                   ie.     #1={'({})':#1#}
*/
 }

var data = { b: obj . deepClone ( )  } ;

В SO опубликовано много, много, много попыток сделать deepClone, а также
Алгоритм структурированного клона - Руководство веб-разработчика | MDN

подсказка: у императора нет одежды

Другие вопросы по тегам