JavaScript клонирование экземпляра класса
У меня есть класс, который выглядит следующим образом:
function Element(){
this.changes = {};
}
Теперь у меня есть экземпляр этого "класса", например, el = new Element()
. Эти экземпляры хранятся в массиве, например elements.push(el)
.
Этот массив элементов теперь хранится в объекте, который затем помещается в массив, states
.
Теперь есть случаи, когда мне нужна копия одного из элементов, поэтому мне нужно будет сделать что-то вроде var cloned = $.extend(true, {}, states[0])
. Здесь я предположил, что мы клонируем первое состояние.
Теперь проблема в том, что то, что я получаю, state[1].elements[0]
все еще указывает на исходный экземпляр. Таким образом, любые изменения, которые я делаю для клонированного объекта, также меняют оригинал.
Это разочаровывает то, что застревает в такой тривиальной проблеме...
Вот скрипка, которую я создал, чтобы проверить ее:
http://jsfiddle.net/E6wLW/
Ответы
Ответ 1
$.extend
- это клонирование простых объектов. Если объект имеет конструктор, то он не клонирован, а просто скопирован.
Из $.extend
источник:
if ( jQuery.isPlainObject(copy) /* ... */) {
// do the recursive $.extend call and clone the object
} else if ( copy !== undefined ) {
target[ name ] = copy;
// ^^^^^ just copy
}
Итак $.extend()
вызовет isPlainObject(el)
который вернет false, потому что el
имеет конструктор и вместо клонирования el
копируется. Итак, states[1].elements[0]
- это тот же объект, что и states[0].elements[0]
, потому что он не был клонирован.
Если мы изменим ваш пример:
function Element(){
this.changes = {};
}
var el = new Element(); // $.isPlainObject(el); <- false
// ...
в
var el = { changes: {} }; // $.isPlainObject(el); <- true
// ...
Он будет клонировать el
правильно. Смотрите ЗДЕСЬ.
Ответ 2
Вы можете использовать http://documentcloud.github.com/underscore/#clone для клонирования объекта, например:
var cloned = _.clone(states[0]);