2012-09-07 10 views
12

Sto cercando un modo per unire due oggetti di configurazione insieme, qualcosa di simile:Qualcosa come jQuery.extend() ma standalone?

var developmentConfig = { 
    url: "localhost", 
    port: 80 
}; 

var productionConfig = { 
    url: "example.com" 
}; 

var config = isDevelopment ? developmentConfig : jQuery.extend(developmentConfig, productionConfig); 

Tuttavia, questo è un applicazione Node.js e non voglio includere jQuery e sono alla ricerca di qualcosa di simile ma standalone. So che potrei scrivere qualcosa di simile me stesso, ma io preferisco usare qualcosa testato e provato (ci sono casi limite, complicazioni quando gli oggetti di configurazione utilizzano le gerarchie più ricchi etc.)

Modifica: semplice iterazione non è sufficiente perché non gestisce strutture gerarchiche. Neanche Underscore's extend.

+4

utilizzare la sorgente, Luke :) – epoch

+2

C'è un sito web che aiuta veramente con il controllo fonte di jQuery. Per 'jQuery.extend', [qui vai] (http://james.padolsey.com/jquery/#v=git&fn=jQuery.extend). –

+1

Ho dato un'occhiata prima di chiedere ma ci sono dipendenze esterne dalla funzione extend() quindi c'è più lavoro da fare che copiare semplicemente alcune righe. – Borek

risposta

18

Se tutto ciò che serve è esteso, allora è piuttosto semplice scriverlo in un paio di righe. Se si desidera che l'estensione ricorsiva, è difficile da fare che del tutto genericamente, se si vuole avere strutture circolari, oggetti con catene prototipo complesse, ecc Se è solo alcuni oggetti semplici nidificati, allora questo dovrebbe funzionare:

function extend (target, source) { 
    target = target || {}; 
    for (var prop in source) { 
    if (typeof source[prop] === 'object') { 
     target[prop] = extend(target[prop], source[prop]); 
    } else { 
     target[prop] = source[prop]; 
    } 
    } 
    return target; 
} 

Se Stai cercando una libreria leggera che faccia questo (meno la ricorsione, per le ragioni sopra elencate) e altre funzioni simili non fornite da javascript, guarda allo Underscore che è disponibile via NPM anche per il nodo.

+0

Anche io ho bisogno di un comportamento ricorsivo, vedi la domanda. – Borek

+0

@Borek Ho aggiornato la risposta ora – nickf

+3

anche convertendo gli array in oggetti. –

4

Un altro esempio di semplice funzione stand-alone per i futuri pellegrini attraverso questa domanda con protezione dalle fusione delle proprietà di diverse tipologie:

function extend(obj) { 
    Array.prototype.slice.call(arguments, 1).forEach(function(source) { 
     if (source) { 
      for (var prop in source) { 
       if (source[prop].constructor === Object) { 
        if (!obj[prop] || obj[prop].constructor === Object) { 
         obj[prop] = obj[prop] || {}; 
         extend(obj[prop], source[prop]); 
        } else { 
         obj[prop] = source[prop]; 
        } 
       } else { 
        obj[prop] = source[prop]; 
       } 
      } 
     } 
    }); 
    return obj; 
} 

Usage:

extend({ name:'Maria', address:{ city:'Moscow', street:'Lenina str, 52' } }, { name:'Marianna', address:{ zip:1200003 }}) 
=> { name:'Marianna', address:{ city:'Moscow', street:'Lenina str, 52', zip:1200003 } } 
+0

prima "if" in "for": source [prop]! == null && source [prop] .constructor === Oggetto –

1

Questa soluzione crea un nuova oggetto ed è in grado di gestire più oggetti .

Inoltre, è ricorsivo e si può scegliere tempo si desidera a sovrascrittura Valori e oggetti.

function extendObjects() { 

     var newObject  = {}; 
     var overwriteValues = false; 
     var overwriteObjects = false; 

     for (var indexArgument = 0; indexArgument < arguments.length; indexArgument++) { 

      if (typeof arguments[indexArgument] !== 'object') { 

       if (arguments[indexArgument] == 'overwriteValues_True') { 

        overwriteValues = true;    
       } else if (arguments[indexArgument] == 'overwriteValues_False') { 

        overwriteValues = false;        
       } else if (arguments[indexArgument] == 'overwriteObjects_True') { 

        overwriteObjects = true;  
       } else if (arguments[indexArgument] == 'overwriteObjects_False') { 

        overwriteObjects = false; 
       } 

      } else { 

       extendObject(arguments[indexArgument], newObject, overwriteValues, overwriteObjects); 
      } 

     } 

     function extendObject(object, extendedObject, overwriteValues, overwriteObjects) { 

      for (var indexObject in object) { 

       if (typeof object[indexObject] === 'object') { 

        if (typeof extendedObject[indexObject] === "undefined" || overwriteObjects) { 
         extendedObject[indexObject] = object[indexObject]; 
        } 

        extendObject(object[indexObject], extendedObject[indexObject], overwriteValues, overwriteObjects); 

       } else { 

        if (typeof extendedObject[indexObject] === "undefined" || overwriteValues) { 
         extendedObject[indexObject] = object[indexObject]; 
        } 

       } 

      }  

      return extendedObject; 

     } 

     return newObject; 
    } 

    var object1   = { a : 1, b : 2, testArr : [888, { innArr : 1 }, 777 ], data : { e : 12, c : { lol : 1 }, rofl : { O : 3 } } }; 
    var object2   = { a : 6, b : 9, data : { a : 17, b : 18, e : 13, rofl : { O : 99, copter : { mao : 1 } } }, hexa : { tetra : 66 } }; 
    var object3   = { f : 13, g : 666, a : 333, data : { c : { xD : 45 } }, testArr : [888, { innArr : 3 }, 555 ] }; 

    var newExtendedObject = extendObjects('overwriteValues_False', 'overwriteObjects_False', object1, object2, object3); 

Contenuto del newExtendedObject:

{"a":1,"b":2,"testArr":[888,{"innArr":1},777],"data":{"e":12,"c":{"lol":1,"xD":45},"rofl":{"O":3,"copter":{"mao":1}},"a":17,"b":18},"hexa":{"tetra":66},"f":13,"g":666} 

Fiddle: http://jsfiddle.net/o0gb2umb/

Problemi correlati