Comment dupliquer les propriétés d'un objet dans un autre objet?


185

Compte tenu de l'objet:

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

comment puis-je copier les propriétés dans un autre objet ( secondObject) comme ceci:

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

en utilisant une référence au firstObject? Quelque chose comme ça:

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

(cela ne fonctionne pas ... je l'ai mis juste pour montrer en grandes lignes comment je voudrais structurer le code).

Une solution est-elle possible sans utiliser de frameworks JavaScript?



1
La question est, voulez-vous une copie superficielle ou profonde? Si profond, à quelle profondeur?
georg

5
FWIW, ils sont appelés «propriétés» et non «attributs».
TJ Crowder

Voici quelque chose de vraiment moche qui fonctionne néanmoins (pas vraiment recommandé! Juste une preuve de concept en une seule ligne):secondObject = JSON.parse('{' + JSON.stringify(firstObject).match(/^.(.*).$/)[1] + ',' + JSON.stringify(secondObject).match(/^.(.*).$/)[1] + '}');
Ben Lee

@TJCrowder: J'ai corrigé la question ... merci.
Igor Popov

Réponses:


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

3
@BenLee, ce qui vous manque ici, c'est qu'Igor a montré l'usage exact qu'il en a, ce qui hasOwnPropertyest inutile. Bien que je trouve votre pointeur utile, j'estime que l'idée d'appliquer des règles à toute situation est nuisible et imprudente. Comme toutes ces pratiques de développement axées sur les modèles qui sont en cours, alors ne le prenez pas personnel…
Michael Krelin - hacker

1
@ MichaelKrelin-hacker, ce qui vous manque ici, c'est que StackOverflow n'est pas seulement au profit de l'OP. Il est utilisé comme référence pour les futurs visiteurs qui peuvent avoir des cas d'utilisation légèrement différents, où ce pointeur peut être utile.
Ben Lee

@BenLee, je ne suis pas IgorPopov ;-) Et n'étant pas l'OP, j'ai déjà dit que je trouve le pointeur utile et votre réponse aussi, c'est la partie "vous devriez vraiment utiliser" que je n'aime pas.
Michael Krelin - hacker

23
Vous omettez un hasOwnProperty()test et les choses continuent de fonctionner. Jusqu'à ce qu'ils s'arrêtent, car vos objets sont devenus plus complexes avec le temps. Sauf que cela se brise mystérieusement dans une partie non liée du code parce que trop de choses ont été copiées. Et vous n'avez aucun contexte pour le débogage. JS est nul comme ça, il est donc prudent de coder soigneusement pour éviter que de tels problèmes ne se produisent.
Eli Bendersky du

2
Je pense que cette réponse doit être mise à jour selon le lien suivant developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... const target = {a: 1, b: 2}; source const = {b: 4, c: 5}; const returnTarget = Object.assign (cible, source); console.log (cible); // sortie attendue: Object {a: 1, b: 4, c: 5} console.log (returnedTarget); // résultat attendu: Object {a: 1, b: 4, c: 5}
Elbassel

170

S'inspirant de la réponse de @ Bardzuśny ici, ES6 a fourni une solution native: le Object.assign() fonction!

L'utilisation est simple:

Object.assign(secondObject, firstObject);

C'est tout!

Le soutien actuel est manifestement médiocre; seul Firefox (34+) le prend en charge par défaut, tandis que Chrome (45+) et Opera (32+) nécessitent que le «drapeau expérimental» soit défini.

Le support s'améliore, avec les dernières versions de Chrome, Firefox, Opera, Safari et Edge le prenant en charge (IE n'a notamment pas de support.) Des transpilers sont également disponibles, comme Babel et Traceur. Voir ici pour plus de détails.


4
+1, une autre fonctionnalité ES6 cool. Bien sûr, le support du navigateur / même de Node.JS fait défaut pour le moment, mais comme vous l'avez mentionné, il existe des transpileurs disponibles. Et si vous ne les aimez pas - shims: github.com/paulmillr/es6-shim (ou standalone, Object.assign()-only shim: github.com/ljharb/object.assign ).
bardzusny

1
@Xoyce Si vous vérifiez la page MDN liée, elle indique clairement "Si la valeur source est une référence à un objet, elle ne copie que cette valeur de référence." Il conserve donc effectivement la référence et ne copie pas l'objet. Votre mise en garde contre un comportement inattendu est toujours d'actualité, et cela revient à avoir des attentes appropriées.
The DIMM Reaper

@mostafiz J'ai annulé votre modification, car la question et les autres réponses de cette page utilisent les noms "firstObject" et "secondObject", j'ai donc utilisé les mêmes noms ici pour plus de clarté et de cohérence.
The DIMM Reaper

Si cela correspond à la question, alors ce n'est pas grave.
Mostafiz Rahman


101

Par ES6 - Syntaxe de propagation :

Vous pouvez simplement utiliser:

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

Cela évite les problèmes de passage de ces objets par référence.

De plus, il prend en charge les objets qui ont une imbrication profonde.


2
Wow, c'est vraiment génial :) Merci pour la réponse. Évidemment, je n'en ai plus besoin (puisque c'était il y a quelque temps), mais cela pourrait aider quelqu'un d'autre.
Igor Popov

1
+1 pour une utilisation encore plus cool de l'ES6! Les documents MDN référencés ci-dessus ne mentionnent pas l'utilisation de l'opérateur de diffusion sur les objets, j'ai donc fait un violon pour le voir en action: es6fiddle.net/im3ifsg0
The DIMM Reaper

1
@jaepage - bon commentaire pour référence. Un objet (selon la question d'origine) avec des noms de propriété simples est itérable.
kingPuppy

1
Fonctionne sous Chrome, c'est ES6, vous aurez besoin de Babel ou d'un transpilateur ES6 actuellement. À l'avenir, tous les navigateurs devraient prendre en charge cette syntaxe.
kingPuppy

89

Parcourez les propriétés du premier objet et attribuez-les au deuxième objet, comme ceci:

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

La boucle for- inne suffit pas; vous avez besoin hasOwnProperty. Voir http://bonsaiden.github.com/JavaScript-Garden/#object.forinloop pour une explication détaillée de la raison.


@RobW, je ne pensais pas que l'OP l'utilise referenceau sens technique. Je pense qu'il veut simplement dire «faire référence à» en langage naturel.
Ben Lee

1
@RobW: Le PO a en fait dit "copier".
TJ Crowder

49

Jouer le nécromancien ici, car ES5 nous a amenés Object.keys(), avec le potentiel de nous sauver de tous ces .hasOwnProperty()contrôles.

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

Ou, en l'enveloppant dans une fonction ("copie" limitée de 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()est une méthode relativement nouvelle, notamment: non disponible dans IE <9. Il en va de même pour la .forEach()méthode array, que j'ai utilisée à la place defor boucle .

Heureusement, il y a es5-shim disponible pour ces anciens navigateurs, qui polyfill de nombreuses fonctionnalités ES5 (y compris ces deux).

(Je suis tout à fait pour les polyfills plutôt que de ne pas utiliser de nouvelles fonctionnalités de langage sympas.)


Soudain, 2 votes négatifs sortis de nulle part. En espérant que ces gars liront ce commentaire, quelle en est la raison réelle? Quelque chose que vous suggéreriez de changer / améliorer dans ma réponse?
bardzusny

1
Cela mérite certainement de monter vers le haut, ainsi que l'initialiseur de propagation d'objets plus bas (ES6) - cela semble encore plus propre avec les fonctions fléchées!
mjohnsonengr

12

Necro'ing pour que les gens puissent trouver une méthode de copie profonde avec hasOwnProperty et une vérification d'objet réelle:

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

Notez que cela ne copie pas en profondeur les tableaux ou les objets de fonction (mais cela copie en profondeur tous les autres types d'objets).
Matt Browne

1
Ouais, si vous voulez copier des tableaux en profondeur, il vous suffit de modifier la vérification de type pour inclure'[object Array]'
Nijikokun

12

On peut utiliser Object.assign pour combiner des objets. Il combinera et remplacera la propriété commune de droite à gauche, c'est-à-dire que la même propriété à gauche sera remplacée par right.

Et il est important de fournir un objet vide dans le premier pour éviter de muter les objets source. Les objets source doivent être laissés propres carObject.assign() par lui-même renvoie un nouvel objet.

J'espère que cela t'aides!

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

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

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

console.log(finalObject)


mais que faire si vous voulez qu'il mute le premier objet? Vous avez l'objet A et l'objet B, et vous voulez qu'il mute l'objet A afin que toutes les propriétés soient égales à ce qu'elles sont sur l'objet B? Feriez-vous Object.assign (A, B)?
TKoL

Malheureusement non pris en charge sur IE, Android WebView, Android Opera selon cette page du Mozilla Developer Network.
Yetti99

6

Amélioration de l' idée de kingPuppy et de l'idée OP (copie superficielle) - Je n'ajoute que 3 points à OP "exemple" :)

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


4

Cela devrait fonctionner, testé ici .

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

Remarque : cela ne copiera pas les méthodes de la firstObject
note 2 : pour une utilisation dans les navigateurs plus anciens, vous aurez besoin d'un analyseur json.
Remarque 3 : l'assignation par référence est une option viable, surtout si elle firstObjectcontient des méthodes. Ajustement de l'exemple jsfiddle donné en conséquence


3

Malheureusement, vous ne pouvez pas mettre une référence à une variable dans un objet comme celui-là. Cependant, vous pouvez créer une fonction qui copie les valeurs de l'objet dans un autre objet.

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

Cela copiera également les propriétés natives. Et qu'en est-il des propriétés qui sont des objets eux-mêmes?
KooiInc

1

Si vous souhaitez récupérer uniquement les propriétés qui existent dans le deuxième objet, vous pouvez utiliser Object.keyspour récupérer les propriétés du premier objet, vous pouvez utiliser deux méthodes:

A.) map pour attribuer les propriétés du premier objet au deuxième objet à l'aide d'effets secondaires:

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.) ou reducepour créer un nouvel objet et l'affecter au deuxième objet. Sachez que cette méthode remplace les autres propriétés que le deuxième objet pourrait avoir avant celles qui ne correspondaient pas au premier objet:

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

Utilisez la notation de propagation de propriété. Il a été ajouté dans ES2018 (la propagation pour les tableaux / itérables était antérieure, ES2015), {... firstObject} répartit toutes les propriétés énumérables en tant que propriétés discrètes.

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

pouvez-vous s'il vous plaît donner un peu de contexte sur votre réponse et pourquoi elle résout la question à portée de main
Tamir Klein

0

Je préférerais utiliser firstObject comme prototype de secondObject et ajouter un descripteur de propriété:

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

Ce n'est certainement pas une seule ligne, mais cela vous donne plus de contrôle. Si vous êtes intéressé par les descripteurs de propriétés, je vous suggère de lire cet article: http://patrickdelancy.com/2012/09/property-descriptors-in-javascript/#comment-2062 et page MDN https: //developer.mozilla. org / en-US / docs / Web / JavaScript / Reference / Global_Objects / Object / create

Vous pouvez également simplement attribuer des valeurs et omettre les descripteurs et les raccourcir un peu:

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

Compatibilité: ECMAScript 5, donc 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'utilisation de la méthode suivante copiera les propriétés

secondObject.copy(firstObject)

Je suis très nouveau en javascript, mais j'ai trouvé que cela fonctionnait. Un peu trop longtemps je suppose, mais ça marche.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.