Come duplicare le proprietà dell'oggetto in un altro oggetto?


185

Dato l'oggetto:

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

come posso copiare le proprietà all'interno di un altro oggetto ( secondObject) in questo modo:

var secondObject = {
    key1 : 'value1',
    key2 : 'value2',
    key3 : 'value3',
    key4 : 'value4'
};

usando un riferimento a firstObject? Qualcosa come questo:

var secondObject = {
    firstObject,
    key3 : 'value3',
    key4 : 'value4'
};

(questo non funziona ... lo metto solo per mostrare a grandi linee come vorrei strutturare il codice).

È possibile una soluzione senza utilizzare alcun framework JavaScript?



1
La domanda è: vuoi una copia superficiale o profonda? Se profondo, quanto profondo?
Georg,

5
FWIW, sono chiamati "proprietà", non "attributi".
TJ Crowder,

Ecco qualcosa di veramente brutto che funziona comunque (in realtà non consigliato! Solo una prova di concetto di una riga):secondObject = JSON.parse('{' + JSON.stringify(firstObject).match(/^.(.*).$/)[1] + ',' + JSON.stringify(secondObject).match(/^.(.*).$/)[1] + '}');
Ben Lee

@TJCrowder: ho corretto la domanda ... grazie.
Igor Popov,

Risposte:


213
for(var k in firstObject) secondObject[k]=firstObject[k];

3
@BenLee, quello che ti manca qui è che Igor ha mostrato l'esatto uso che ha per esso, in cui hasOwnPropertyè inutile. Mentre trovo il puntatore utile, ritengo l'idea di applicare eventuali regole da qualsiasi situazione dannosa e poco saggio. Come tutte queste pratiche di sviluppo basate su schemi che stanno accadendo, quindi non prenderlo sul personale ...
Michael Krelin - hacker

1
@ MichaelKrelin-hacker, quello che ti manca qui è che StackOverflow non è solo a beneficio dell'OP. È usato come riferimento per i futuri visitatori che potrebbero avere casi d'uso leggermente diversi, in cui quel puntatore può essere utile.
Ben Lee,

@BenLee, non sono IgorPopov ;-) E non essendo l'OP, ho già detto che trovo utile il puntatore e anche la tua risposta, è la parte "dovresti davvero usare" che non mi piace.
Michael Krelin - hacker,

23
Ometti un hasOwnProperty()test e le cose continuano a funzionare. Fino a quando non si fermano, perché i tuoi oggetti sono diventati più complessi nel tempo. Tranne poi si rompe misteriosamente in una parte non correlata del codice perché è stato copiato troppo. E non hai alcun contesto per il debug. JS fa così schifo, quindi è prudente codificare con cura per evitare che si verifichino tali problemi.
Eli Bendersky,

2
Penso che questa risposta debba essere aggiornata secondo il seguente link developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… const target = {a: 1, b: 2}; const const = {b: 4, c: 5}; const restituitoTarget = Object.assign (target, source); console.log (target); // output previsto: Object {a: 1, b: 4, c: 5} console.log (ReturnsTarget); // output previsto: Object {a: 1, b: 4, c: 5}
Elbassel

170

Prendendo spunto dalla risposta di @ Bardzuśny qui, ES6 ha fornito una soluzione nativa: la Object.assign()funzione!

L'uso è semplice:

Object.assign(secondObject, firstObject);

Questo è tutto!

Il supporto in questo momento è ovviamente scarso; solo Firefox (34+) lo supporta immediatamente, mentre Chrome (45+) e Opera (32+) richiedono l'impostazione del "flag sperimentale".

Il supporto sta migliorando, con le ultime versioni di Chrome, Firefox, Opera, Safari e Edge che lo supportano (IE in particolare non ha supporto.) Sono disponibili anche Transpiler, come Babel e Traceur. Vedi qui per maggiori dettagli.


4
+1, un'altra fantastica funzionalità ES6. Naturalmente per ora il browser / persino il supporto di Node.JS è carente, ma come hai detto, ci sono transpilers disponibili. E se non ti piacciono - shims: github.com/paulmillr/es6-shim (o standalone, Object.assign()-solo shim: github.com/ljharb/object.assign ).
bardzusny,

1
@Xoyce Se controlli la pagina MDN collegata, indica chiaramente "Se il valore di origine è un riferimento a un oggetto, copia solo quel valore di riferimento". Quindi conserva effettivamente il riferimento e non copia l'oggetto. Il tuo avvertimento contro comportamenti imprevisti è ancora appropriato e si riduce ad avere aspettative adeguate.
Il DIMM Reaper il

@mostafiz Ho ripristinato la tua modifica, perché la domanda e le altre risposte in questa pagina usano i nomi "firstObject" e "secondObject", quindi ho usato gli stessi nomi qui per chiarezza e coerenza.
Il DIMM Reaper

Se questo è coerente con la domanda, allora va bene.
Mostafiz Rahman,


101

Per ES6 - Sintassi diffusa :

Puoi semplicemente usare:

const thirdObject = {
   ...firstObject,
   ...secondObject   
}

Questo evita problemi di passaggio di questi oggetti per riferimento.

Inoltre si prende cura degli oggetti che hanno un annidamento profondo.


2
Caspita, è davvero fantastico :) Grazie per la risposta. Ovviamente, non ne ho più bisogno (dato che era tempo fa), ma potrebbe aiutare qualcun altro.
Igor Popov,

1
+1 per un utilizzo ancora più interessante di ES6! I documenti MDN citati sopra non menzionano l'uso dell'operatore spread sugli oggetti, quindi ho fatto un violino per vederlo in azione: es6fiddle.net/im3ifsg0
The DIMM Reaper

1
@jaepage - buon commento per riferimento. Un oggetto (secondo la domanda originale) con nomi di proprietà semplici è iterabile.
kingPuppy

1
Funziona in Chrome, questo è ES6, al momento avrai bisogno di Babel o di qualche transpiler ES6. In futuro tutti i browser dovrebbero supportare questa sintassi.
kingPuppy

89

Scorri le proprietà del primo oggetto e assegnale al secondo oggetto, in questo modo:

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

for (var prop in firstObject) {
    if (firstObject.hasOwnProperty(prop)) {
        secondObject[prop] = firstObject[prop];
    }
}

Il ciclo for- innon è abbastanza; hai bisogno hasOwnProperty. Vedi http://bonsaiden.github.com/JavaScript-Garden/#object.forinloop per una spiegazione dettagliata del perché.


@RobW, non pensavo che l'OP stesse usando referencein senso tecnico. Penso che intenda semplicemente "riferirsi" al linguaggio naturale.
Ben Lee,

1
@RobW: l'OP ha effettivamente detto "copia".
TJ Crowder,

49

Suonando il negromante qui, perché ES5 ci ha portato Object.keys(), con il potenziale per salvarci da tutti questi .hasOwnProperty()controlli.

Object.keys(firstObject).forEach(function(key) {
  secondObject[key] = firstObject[key];
});

Oppure, avvolgendolo in una funzione ("copia" limitata di lodash _.assign()):

function assign(object, source) {
  Object.keys(source).forEach(function(key) {
    object[key] = source[key];
  });
}

assign(secondObject, firstObject); // assign firstObject properties to secondObject

Object.keys()è un metodo relativamente nuovo, in particolare: non disponibile in IE <9. Lo stesso vale per il .forEach()metodo array, che ho usato al posto del normale forciclo.

Fortunatamente, es5-shim è disponibile per questi antichi browser, che riempiono polifunzionalmente molte funzionalità ES5 (comprese quelle due).

(Sono tutto per polifillamenti invece di trattenermi dall'usare nuove funzioni linguistiche interessanti.)


Improvvisamente, 2 downvotes dal nulla. Scommettendo sulla piccola possibilità che quei ragazzi leggano questo commento - qual è la vera ragione per loro? Qualcosa che suggeriresti di cambiare / migliorare nella mia risposta?
bardzusny,

1
Questo merita sicuramente di salire in alto, così come l'inizializzazione della diffusione dell'oggetto più in basso (ES6) - questo sembra ancora più pulito con le funzioni freccia!
mjohnsonengr,

12

Necro'ing in modo che le persone possano trovare un metodo di copia approfondita con hasOwnProperty e controllo dell'oggetto reale:

var extend = function (original, context, key) {
  for (key in context)
    if (context.hasOwnProperty(key))
      if (Object.prototype.toString.call(context[key]) === '[object Object]')
        original[key] = extend(original[key] || {}, context[key]);
      else
        original[key] = context[key];
  return original;
};

Si noti che questo non copia in profondità matrici o oggetti funzione (ma copia in profondità tutti gli altri tipi di oggetti).
Matt Browne,

1
Sì, se vuoi copiare in profondità array devi solo modificare il controllo del tipo per includere'[object Array]'
Nijikokun,

12

Si può usare Object.assign per combinare oggetti. Combinerà e sovrascriverà la proprietà comune da destra a sinistra, ovvero la stessa proprietà a sinistra verrà ignorata da destra.

E questo è importante fornire un oggetto vuoto nel primo per evitare di mutare gli oggetti sorgente. Gli oggetti di origine devono essere lasciati puliti poiché Object.assign()da soli restituisce un nuovo oggetto.

Spero che questo ti aiuti!

var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject = {
    key3 : 'value3',
    key4 : 'value4'
};

var finalObject = Object.assign({}, firstObject, secondObject)

console.log(finalObject)


ma cosa succede se si desidera che muti il ​​primo oggetto? Hai l'oggetto A e l'oggetto B e vuoi che muti l'oggetto A in modo che tutte le proprietà siano uguali a quelle che sono sull'oggetto B? Vuoi fare Object.assign (A, B)?
TKoL

Purtroppo non supportato su IE, Android WebView, Android Opera secondo la pagina della rete di sviluppatori Mozilla.
Yetti99

6

Miglioramento dell'idea kingPuppy e dell'idea OP (copia superficiale) - Aggiungo solo 3 punti all'OP "esempio" :)

var secondObject = {
    ...firstObject,
    key3 : 'value3',
    key4 : 'value4'
};


4

Dovrebbe funzionare, testato qui .

var secondObject = {
    firstObject: JSON.parse(JSON.stringify(firstObject)),
    key3 : 'value3',
    key4 : 'value4'
};

Nota : questo non copierà i metodi della firstObject
Nota 2 : per l'uso nei browser più vecchi, avrai bisogno di un parser json
Nota 3 : l'assegnazione per riferimento è un'opzione praticabile, specialmente se firstObjectcontiene metodi. Modificato di conseguenza l'esempio jsfiddle indicato


3

Sfortunatamente, non è possibile inserire un riferimento a una variabile in un oggetto del genere. Tuttavia, è possibile creare una funzione che copia i valori dell'oggetto in un altro oggetto.

function extend( obj1, obj2 ) {
    for ( var i in obj2 ) {
        obj1[i] = obj2[i];
    }
    return obj1;
}

var firstObject = {
    key1: "value1",
    key2: "value2"
};

var secondObject = extend({
    key3: "value3",
    key4: "value4"
}, firstObject );

Questo copierà anche le proprietà native. E che dire delle proprietà che sono gli oggetti stessi?
KooiInc,

1

Se si desidera afferrare solo le proprietà esistenti nel secondo oggetto, è possibile utilizzare Object.keysper afferrare le proprietà del primo oggetto, è possibile eseguire due metodi:

A.) map per assegnare le proprietà del primo oggetto al secondo oggetto usando gli effetti collaterali:

var a = {a:100, b:9000, c:300};
var b = {b:-1};

Object.keys(a).map(function(key, index) {
    if (typeof b[key] !== 'undefined') {
        console.log(key);
        b[key] = a[key];    
    }
});

B.) o reduceper creare un nuovo oggetto e assegnarlo al secondo oggetto. Tenere presente che questo metodo sostituisce altre proprietà che il secondo oggetto potrebbe avere prima di quello che non corrispondeva al primo oggetto:

var a = {a:100, b:9000, c:300};
var b = {b:-1, d:-1}; // d will be gone

b = Object.keys(a).reduce(function(result, current) {
    if (typeof b[current] !== 'undefined') {
        result[current] = a[current];   
    }
    return result;
}, {});

1

Utilizzare la notazione di diffusione della proprietà. È stato aggiunto in ES2018 (lo spread per array / iterables era precedente, ES2015), {... firstObject} distribuisce tutte le proprietà enumerabili come proprietà discrete.

let secondObject = {
      ...firstObject,
      key3 : 'value3',
      key4 : 'value4'
    }

puoi per favore dare un po 'di contesto sulla tua risposta e perché sta risolvendo la domanda a portata di mano
Tamir Klein,

0

Preferirei usare firstObject come prototipo di secondObject e aggiungere un descrittore di proprietà:

var secondObject = Object.create(firstObject, {
      key3: {value: "value3", writable: true, configurable: true, enumerable: true},
      key4: {value: "value4", writable: true, configurable: true, enumerable: true}
      });

Non è certo una linea, ma ti dà più controllo. Se sei interessato ai descrittori di proprietà, ti suggerisco di leggere questo articolo: http://patrickdelancy.com/2012/09/property-descriptors-in-javascript/#comment-2062 e la pagina MDN https: //developer.mozilla. org / it-IT / docs / Web / JavaScript / Reference / Global_Objects / oggetto / creare

Puoi anche semplicemente assegnare valori e omettere i descrittori e renderlo un po 'più breve:

var secondObject = Object.create(firstObject, {
      key3: {value: "value3"}
      key4: {value: "value4"}
  });

Compatibilità: ECMAScript 5, quindi IE9 +


0
var firstObject = {
     key1: "value1",
     key2: "value2"
};

var secondObject = {
     key3: "value3",
     key4: "value4"
     copy: function(firstObject){
           this.key1 = firstObject.key1;
           this.key2 = firstObject.key2;
     }
 };

L'uso del metodo follwing copierà le proprietà

secondObject.copy(firstObject)

Sono molto nuovo su JavaScript, ma ho trovato che funziona. Un po 'troppo a lungo credo, ma funziona.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.