2013-02-12 5 views
30

C'è un modo per ottenere Underscore.js extend funzione:Recursive/deep extend/assign in Underscore.js?

copia tutte le proprietà negli oggetti della sorgente verso l'oggetto destinazione, e restituire l'oggetto di destinazione. È in ordine, così l'ultima sorgente sovrascriverà le proprietà con lo stesso nome negli argomenti precedenti .

... funzionare in modo ricorsivo?

In realtà, query proprietà in creditOperation sta per ignorare completamente la proprietà query definito baseOperation:

var url = require('url') 
    , _ = require('underscore'), 
    , baseOperation = { 
     host: 'gateway.skebby.it', 
     pathname: 'api/send/smseasy/advanced/http.php', 
     protocol: 'https', 
     query: { 
      'username': 'foo', 
      'password': 'bar', 
     } 
    }; 

var creditOperation = _.extend(baseOperation, { 
    query: { 
     'method': 'baz' 
    } 
}); 

console.log(url.format(creditOperation)); 

Mi piacerebbe ottenere questo creditOperation:

{ 
    host: 'gateway.skebby.it', 
    pathname: 'api/send/smseasy/advanced/http.php', 
    protocol: 'https', 
    query: { 
     'username': 'foo', 
     'password': 'bar', 
     'method': 'baz' 
    } 
} 
+1

È possibile aggiungere parole "profonde" e "assegnate" nel titolo in modo che il thread possa essere trovato facilmente tramite Google. Come "Recursive/deep extend/assign in Underscore.js?" –

risposta

20

No, Underscore will not contain a deep extend dal momento che è troppo complicato trattare con diversi tipi di oggetti. Invece, gli utenti sono incoraggiati a implementare le proprie soluzioni con il supporto per ciò di cui hanno bisogno.

Nel tuo caso è solo oggetti semplici, in modo da un'implementazione è abbastanza semplice:

_.deepObjectExtend = function(target, source) { 
    for (var prop in source) 
     if (prop in target) 
      _.deepObjectExtend(target[prop], source[prop]); 
     else 
      target[prop] = source[prop]; 
    return target; 
} 
+6

Sembra che questo genererà un'eccezione così com'è quando colpisce una proprietà che non è un oggetto. Devi verificare che sia target [prop] che source [prop] siano oggetti prima di provare a recurse. Forse qualcosa come 'if (prop in target && typeof (target [prop]) == 'object' && typeof (source [prop]) == 'object')' invece per la terza riga. – wizzard

+0

Sì, mi aspettavo che questa funzione 'estendersi 'estendesse (espandere?) Gli oggetti, non sovrascrivere alcuna proprietà in essi (la descrizione dice * solo oggetti semplici *). Se lo vuoi, 'if (typeof target [prop] == 'object')' dovrebbe essere sufficiente. – Bergi

+1

Non sono sicuro di come avere due oggetti con la stessa proprietà li rende _non_ oggetti semplici. Questa funzione è circa 5 volte più utile se gestisce oggetti con le stesse proprietà (e più nello spirito di _.extend). Inoltre, solo il controllo che il target [prop] è un oggetto darà comunque (in modo selvatico) risultati imprevisti nel caso in cui il prop di origine non sia un oggetto e l'oggetto di destinazione sia: http://jsfiddle.net/wizzard/HY4yQ/ Certo, potreste voler aggiungere qualche pensiero in più a questa funzione se avete casi del genere. – wizzard

36

Con Lodash (fork di sottolineatura) u can. Il metodo _.extend di Lodash accetta il terzo (o più alto) parametro per essere una funzione, che riceve valori (vecchi e nuovi); Così u può fare qualcosa di simile:

var deep = function(a, b) { 
    return _.isObject(a) && _.isObject(b) ? _.extend(a, b, deep) : b; 
}; 

var a = {a:{b:{c:1}}}, 
    b = {a:{b:{z:1}}}; 

_.extend(a,b,deep); 

upd. Come Paolo Moretti detto nei commenti, v'è la stessa funzione in lodash chiamato _.merge:

_.merge(a,b); 
+12

Puoi anche usare ['_.merge'] (http://lodash.com/docs#merge): _incorpora in modo sequenziale le proprie proprietà enumerabili dell'oggetto sorgente (s), che non si risolve in undefined nell'oggetto di destinazione_. –

+0

questo non risponde alla domanda – dovidweisz

+3

@wapsee, al contrario, penso che questa sia la risposta più utile. – weaver

19

jQuery ha una funzione extend(), che fa la stessa cosa come la sua controparte sottolineatura, ma ha anche una profonda argomento che gli permette di unire in modo ricorsivo come volete:

var creditOperation = $.extend(true, baseOperation, { 
    query: { 
     'method': 'baz' 
    } 
}); 

Oppure, se non si desidera sovrascrivere baseOperation:

var creditOperation = $.extend(true, {}, baseOperation, { 
    query: { 
     'method': 'baz' 
    } 
}); 
+0

Grazie per questo, è preferibile usarlo piuttosto che scriverlo, comunque in molti casi jquery viene usato nel progetto. – Kostanos

+3

Questo è quello che molte persone effettivamente vogliono quando trovano questa pagina :) –

+0

la seconda è la risposta Million Dollar !!! Posso solo darti +1 :) – Gogol

6

versione stand-alone di Bergi di profonda estendono, compresa la correzione per quando un valore è una stringa invece di un oggetto. Anche patch per essere più severi.

function deepObjectExtend (target, source) { 
    for (var prop in source) { 
     if (source.hasOwnProperty(prop)) { 
      if (target[prop] && typeof source[prop] === 'object') { 
       deepObjectExtend(target[prop], source[prop]); 
      } 
      else { 
       target[prop] = source[prop]; 
      } 
     } 
    } 
    return target; 
} 
2

Kurt Milam ha pubblicato un mixin that adds a deepExtend method to underscore.js. Si occupa anche di espressioni regolari (se lo si desidera). Estratto dalla documentazione:

Miscelare con trattino basso.JS: _.mixin({deepExtend: deepExtend});

chiamare in questo modo: var myObj = _.deepExtend(grandparent, child, grandchild, greatgrandchild)

Note: tenerlo asciutto.

Questa funzione è particolarmente utile se si lavora con documenti di configurazione JSON. Consente di creare un documento di configurazione predefinito con le impostazioni più comuni, quindi sovrascrivere quelle impostazioni per casi specifici. Accetta qualsiasi numero di oggetti come argomenti , offrendo un controllo preciso sulla gerarchia del documento di configurazione .

0

underscore's extend() non estende in profondità; in effetti, non vi è alcuna funzione in underscore che possa estendersi in profondità.

È possibile utilizzare il lodash merge per quello.