2013-05-12 20 views
11

jsFiddle here.jquery.extend (true, [], obj) non crea una copia profonda

Se la copia profonda ha funzionato, l'output sarebbe "Curious George" e non "Ender's Game". Come posso fare una copia profonda? Una risposta a this question indica che $.extend(true, [], obj) crea una copia profonda. Eppure il mio esempio mostra che non è così.

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]); 

SOLUZIONE

ho aggiornato il jsFiddle. Risulta che è necessario copiare in profondità ogni oggetto nell'array singolarmente se l'oggetto è un oggetto personalizzato (ovvero, $.isPlainObject restituisce false).

+0

utilizzare .clone() vedere http://api.jquery.com/clone/ –

+6

@Paul Sullivan: '.clone()' deve essere utilizzato con le entità DOM – zerkms

+0

ok, quindi sfogliare il codice sorgente .extend e vedere perché la funzione ricorsiva non copia gli attributi –

risposta

17

Ed ora ecco la risposta vera:

Al momento jQuery può solo clone semplici oggetti JavaScript, mentre stai utilizzando quelli personalizzati. Ed è ovvio, dal momento che jQuery non può sapere esattamente come istanziare un nuovo oggetto personalizzato. Quindi, questo funziona come previsto:

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); 

riferimento ad un codice jQuery: https://github.com/jquery/jquery/blob/master/src/core.js#L305

vedere che controlla se è jQuery.isPlainObject(copy) o è un array. Altrimenti esegue solo una copia di riferimento.

+0

@Rose Perrone: perché hai creato una copia profonda. Quindi l'oggetto originale viene mantenuto così com'è, e quello modificato viene modificato indipendentemente. Non sei sicuro di cosa ti stia confondendo. – zerkms

+0

@RoyiNamir hai specificato che dovrebbe essere una copia profonda (il primo argomento) – zerkms

+0

Si prega di verificare quale primo argomento booleano nella chiamata alla funzione '$ .extend' significa. E fai un'altra domanda se non è ancora chiaro per te. – zerkms

2

Interessante ... non sembra un array di copie profonde.

È necessario copiare in profondità ciascun oggetto singolarmente.

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

EDIT: Certo, guardare a questo fork di fiddle del PO:

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

+0

"oggetti di copie profonde, non matrici" --- qualche prova per questo? L'array non è un tipo speciale di oggetto? – zerkms

+0

https://github.com/jquery/jquery/blob/master/src/core.js # L305 - Dovrebbe gestire gli array – zerkms

+0

Se è necessario copiare in profondità ciascun oggetto singolarmente, è necessario ricorrere a un codice ricorsivo per copiare completamente verso il basso, a meno che non si supponga che questo copra solo il caso di test dell'OP piuttosto che una soluzione generica? – nnnnnn

7

Ecco come ho fatto dopo aver provato molti approcci:

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

Questo creerà una nuova copia profonda, non una copia.

Anche questo ovviamente non clonerà eventi e funzioni, ma la cosa buona è che puoi farlo in una riga, e può essere usato per qualsiasi re dell'oggetto (matrici, stringhe, numeri, oggetti, ecc.).

+2

Non funzionerà per gli oggetti data. –

Problemi correlati