Recursive / deep extend / assign in Underscore.js?

C’è un modo per ottenere la funzione di extend Underscore.js:

Copiare tutte le proprietà negli oggetti di origine oltre all’object di destinazione e restituire l’object di destinazione. È in ordine, quindi l’ultima sorgente sovrascriverà le proprietà con lo stesso nome negli argomenti precedenti.

… lavorare in modo ricorsivo?

In realtà, la proprietà della query in creditOperation sostituirà completamente la proprietà della query definita in 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' } } 

No, Underscore non contiene un’estensione profonda poiché è troppo complicato per gestire 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 sono solo oggetti semplici, quindi 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; } 

Con Lodash (forchetta di sottolineatura) puoi. Il metodo _.extend di Lodash accetta il terzo (o più alto) parametro per essere una funzione, che riceve valori (vecchi e nuovi); Quindi puoi fare qualcosa del genere:

 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 ha detto Paolo Moretti nei commenti, c’è la stessa funzione in lodash chiamata _.merge :

 _.merge(a,b); 

jQuery ha una funzione extend () , che fa la stessa cosa della sua controparte Underscore, ma ha anche un argomento profondo che gli consente di unire ricorsivamente come desideri:

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

Oppure, se non si desidera sovrascrivere baseOperazione :

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

Versione stand-alone dell’estensione profonda di Bergi, inclusa la correzione per quando un valore è una stringa anziché un object. 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; } 

Kurt Milam ha pubblicato un mixin che aggiunge un metodo deepExtend a underscore.js . Si occupa anche di espressioni regolari (se lo si desidera). Estratto dalla documentazione:

_.mixin({deepExtend: deepExtend}); con underscore.js: _.mixin({deepExtend: deepExtend});

Chiamalo così: var myObj = _.deepExtend(grandparent, child, grandchild, greatgrandchild)

Note: tenerlo ASCIUTTO.

Questa funzione è particolarmente utile se si sta lavorando con i documenti di configurazione JSON. Ti 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 dei documenti di configurazione.

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

Puoi usare l’ unione di lodash per quello.