Подтвердить что ты не робот

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/

4b9b3361

Ответ 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 правильно. Смотрите ЗДЕСЬ.