2013-05-12 2 views
11

jsFiddle here.jquery.extend (true, [], obj), не создавая глубокую копию

Если сработало глубокое копирование, выход будет «Любопытный Джордж», а не «Игра Эндера». Как я могу сделать глубокую копию? Ответ на this question указывает, что $.extend(true, [], obj) создает глубокую копию. Однако мой пример показывает, что это не так.

function Person(){} 
Person.prototype.favorite_books = []; 

var george = new Person(); 
george.favorite_books = ["Curious George"]; 

var kate = new Person(); 
kate.favorite_books = ["The Da Vinci Code", "Harry Potter"]; 

var people = [kate, george]; 

var people_copy = $.extend(true, [], people); 
people_copy[0].favorite_books[0] = "Ender's Game"; 

$('#text').text(people[0].favorite_books[0]); 

РЕШЕНИЕ

Я обновил jsFiddle. Оказывается, мне нужно глубоко скопировать каждый объект в массиве отдельно , если объект является настраиваемым объектом (то есть $.isPlainObject возвращает false).

+0

использование .clone() см. Http://api.jquery.com/clone/ –

+6

@Paul Sullivan: '.clone()' должен использоваться с объектами DOM – zerkms

+0

в порядке, поэтому просмотрите .extend исходный код и посмотрите, почему рекурсивная функция не копирует атрибуты –

ответ

17

А теперь вот реальный ответ:

На данный момент JQuery может только клон простые объекты JavaScript, в то время как вы используете пользовательские. И это очевидно, так как jQuery не может знать, как точно создать новый пользовательский объект. Так что это работает, как ожидалось:

var george = {}; 
george.favorite_books = ["Curious George"]; 

var kate = {}; 
kate.favorite_books = ["The Da Vinci Code", "Harry Potter"]; 

var people = [kate, george]; 

var people_copy = $.extend(true, [], people); 

console.log(people_copy[0].favorite_books == people[0].favorite_books); 

Ссылка на код JQuery: https://github.com/jquery/jquery/blob/master/src/core.js#L305

Смотрите, что он проверяет, является ли это jQuery.isPlainObject(copy) или это массив. В противном случае он выполняет только ссылочную копию.

+0

@Rose Perrone: потому что вы создали глубокую копию. Таким образом, исходный объект сохраняется как есть, а модифицированный изменяется независимо. Не уверен, что вас смущает. – zerkms

+0

@RoyiNamir вы указали, что это должна быть глубокая копия (первый аргумент) – zerkms

+0

Проверьте, что первый логический аргумент в вызове функции $ .extend'. И задайте другой вопрос, если вам все еще не ясно. – zerkms

2

Интересно .... это не похоже на массивы глубоких копий.

Вы должны глубоко копировать каждый объект по отдельности.

var people_copy = []; 
$.each(people,function(i,obj) { 
    people_copy.push($.extend(true,{},obj)); 
}); 

EDIT: Конечно, смотреть на эту развилку скрипку в ФП в:

http://jsfiddle.net/s2bLv/4/

+0

"объекты с глубокими копиями, а не массивы" --- какие-либо доказательства для этого? Разве массив не является особым видом объекта? – zerkms

+0

https://github.com/jquery/jquery/blob/master/src/core.js # L305 - он должен обрабатывать массивы – zerkms

+0

Если вам нужно выполнить глубокую копию каждого объекта индивидуально, вам потребуется какой-то рекурсивный код, чтобы скопировать весь путь вниз, если только это не должно охватывать простой тестовый пример OP, а не быть общим решением? – nnnnnn

7

Это, как я сделал это после попытки многих подходов:

var newArray = JSON.parse(JSON.stringify(orgArray)); 

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

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

+2

Он не будет работать для объектов даты. –

Смежные вопросы