Comment puis-je cloner un objet JavaScript à l'exception d'une clé?


308

J'ai un objet JS plat:

{a: 1, b: 2, c: 3, ..., z:26}

Je veux cloner l'objet à l'exception d'un élément:

{a: 1, c: 3, ..., z:26}

Quelle est la façon la plus simple de le faire (préférant utiliser es6 / 7 si possible)?


Sans changer l'objet d'origine: JSON.parse (JSON.stringify ({... obj, 'key2': undefined}))
infinity1975

Réponses:


441

Si vous utilisez Babel, vous pouvez utiliser la syntaxe suivante pour copier la propriété b de x dans la variable b, puis copier le reste des propriétés dans la variable y :

let x = {a: 1, b: 2, c: 3, z:26};
let {b, ...y} = x;

et il sera transposé en:

"use strict";

function _objectWithoutProperties(obj, keys) {
  var target = {};
  for (var i in obj) {
    if (keys.indexOf(i) >= 0) continue;
    if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
    target[i] = obj[i];
  }
  return target;
}

var x = { a: 1, b: 2, c: 3, z: 26 };
var b = x.b;

var y = _objectWithoutProperties(x, ["b"]);

58
Si vous peluchez votre code pour les variables inutilisées, cela se traduira par une "variable inutilisée 'b'". " avertissement cependant.
Ross Allen

1
à quoi ressemblerait la syntaxe si vous aviezlet x = [{a: 1, b: 2, c: 3, z:26}, {a: 5, b: 6, c: 7, z:455}];
ke3pup

14
@RossAllen Une option a ignoreRestSiblingsété ajoutée dans la v3.15.0 (3 février 2017). Voir: commit c59a0ba
Ilya Palkin

4
@IlyaPalkin Intéressant. Cela semble un peu paresseux car cela ne change pas le fait qu'il y ait une bportée.
Ross Allen

2
Si vous obtenez l'échec de la construction du module: SyntaxError: jeton inattendu, vous devrez probablement ajouter le plugin de transformation de propagation babel rest. Voir babeljs.io/docs/plugins/transform-object-rest-spread
jsaven

133
var clone = Object.assign({}, {a: 1, b: 2, c: 3});
delete clone.b;

ou si vous acceptez que la propriété ne soit pas définie:

var clone = Object.assign({}, {a: 1, b: 2, c: 3}, {b: undefined});

7
La simple suppression de la propriété est un moyen clair et simple de le faire.
sshow

24
La mise en garde avec suppression est que ce n'est pas une opération immuable.
Javid Jamae

1
cela garde la clé
Fareed Alnamrouti

1
Mon commentaire a été écrit avant de modifier sa réponse et d'ajouter la déclaration de suppression
Fareed Alnamrouti

C'est exactement ce que je cherchais, mais un peu plus implémenté d'une manière légèrement différente: var cake = {... currentCake, requestorId: undefined};
abelito

73

Pour ajouter à la réponse d'Ilya Palkin: vous pouvez même supprimer dynamiquement des clés:

const x = {a: 1, b: 2, c: 3, z:26};

const objectWithoutKey = (object, key) => {
  const {[key]: deletedKey, ...otherKeys} = object;
  return otherKeys;
}

console.log(objectWithoutKey(x, 'b')); // {a: 1, c: 3, z:26}
console.log(x); // {a: 1, b: 2, c: 3, z:26};

Démo dans Babel REPL

La source:


3
Ceci est une belle syntaxe.
Hinrich

2
C'est très bien, mais existe-t-il un moyen d'éviter la var suppriméKey non utilisée? Non pas que cela cause des problèmes, mais fait se plaindre JSHint, et semble étrange car nous ne l'utilisons vraiment pas.
Johnson Wong

6
@JohnsonWong Que diriez-vous d'utiliser _ce qui est autorisé pour une variable que vous n'avez pas l'intention d'utiliser?
Ryan H.

var b = {a:44, b:7, c:1}; let {['a']:z, ...others} = b; console.log(z , others ); // logs: 44, {b:7, c:1}
jimmont

70

Pour ceux qui ne peuvent pas utiliser ES6, vous pouvez utiliser lodashou underscore.

_.omit(x, 'b')

Ou ramda.

R.omit('b', x)

6
ne serait-il pas plus logique d'utiliser omit ici? _.omit(x, 'b')
tibalt

Merci @tibalt. Mis à jour la réponse avec.
Noel Llevares

supprimer est plus concis - l'utilisation de lodash, underscore ou ramda ne concerne que les projets qui les utilisent déjà et les connaissent, sinon cela est de plus en plus hors de propos en 2018 et au-delà.
jimmont

1
@jimmont delete est déjà mentionné dans d'autres réponses. Vous n'avez pas besoin de réponses en double, vous ne pensez pas? Et bien sûr, cela ne concerne que ceux qui utilisent déjà le lodash ou le ramda. Et cela n'est également pertinent que pour ceux qui sont bloqués avec ES5 et plus tôt, comme indiqué dans cette réponse.
Noel Llevares

@dashmug mon commentaire précédent était une critique de l'approche (pas de votre réponse) qui devrait être notée lors du choix d'utiliser l'approche représentée dans cette réponse. Je voudrais cette information si je lisais les réponses et c'est la raison pour ajouter mon commentaire et mentionner delete.
jimmont

63

J'utilise cette doublure ESNext one

const obj = { a: 1, b: 2, c: 3, d: 4 }
const clone = (({ b, c, ...o }) => o)(obj) // remove b and c
console.log(clone)


Si vous avez besoin d'une fonction à usage général:

function omit(obj, props) {
  props = props instanceof Array ? props : [props]
  return eval(`(({${props.join(',')}, ...o}) => o)(obj)`)
}

// usage
const obj = { a: 1, b: 2, c: 3, d: 4 }
const clone = omit(obj, ['b', 'c'])
console.log(clone)


9
Au lieu d'envelopper dans un tableau et mapvous pouvez faire:(({b, c, ...others}) => ({...others}))(obj)
bucabay

@bucabay: Brillant! C'est la meilleure réponse du lot! Conforme aux normes, fonctionne parfaitement dans Node etc. Vous devez soumettre une réponse.
david.pfx

3
Fantastic answer mate .. <3
Ajithkumar S

5
@totymedli: Pas par moi. Je prendrai la forme syntaxique, qui fait partie de la norme ES6, sur une fonction magique à tout moment, pour des raisons de lisibilité.
david.pfx

1
Brillant. C'est tout.
darksoulsong

22

Vous pouvez lui écrire une fonction d'assistance simple. Lodash a une fonction similaire avec le même nom: omettre

function omit(obj, omitKey) {
  return Object.keys(obj).reduce((result, key) => {
    if(key !== omitKey) {
       result[key] = obj[key];
    }
    return result;
  }, {});
}

omit({a: 1, b: 2, c: 3}, 'c')  // {a: 1, b: 2}

Notez également qu'il est plus rapide que Object.assign et supprimez ensuite: http://jsperf.com/omit-key


11

Peut-être quelque chose comme ça:

var copy = Object.assign({}, {a: 1, b: 2, c: 3})
delete copy.c;

Est-ce assez bon? Ou ne pouvez-vous pas créellement les copier?


11

Utilisation de la déstructuration d'objets

const omit = (prop, { [prop]: _, ...rest }) => rest;
const obj = { a: 1, b: 2, c: 3 };
const objWithoutA = omit('a', obj);
console.log(objWithoutA); // {b: 2, c: 3}


Excellente solution!
Denys Mikhalenko

2
Je suppose que cette solution est destinée à empêcher l'avertissement «Variable inutilisée» dans JSLint. Malheureusement, l'utilisation _ne résout pas le problème pour ESLint ...
bert bruynooghe

6

Hé, vous semblez rencontrer des problèmes lorsque vous essayez de copier un objet, puis de supprimer une propriété. Quelque part, vous devez attribuer des variables primitives afin que javascript crée une nouvelle valeur.

Truc simple (peut-être horrible) que j'ai utilisé était-ce

var obj = {"key1":"value1","key2":"value2","key3":"value3"};

// assign it as a new variable for javascript to cache
var copy = JSON.stringify(obj);
// reconstitute as an object
copy = JSON.parse(copy);
// now you can safely run delete on the copy with completely new values
delete copy.key2

console.log(obj)
// output: {key1: "value1", key2: "value2", key3: "value3"}
console.log(copy)
// output: {key1: "value1", key3: "value3"}

En fait, je l'aime. Pourrait faire JSON.parse(JSON.stringify(Object.assign({}, obj, { key2: undefined })));. Vous n'avez même pas besoin de le supprimer, il suffit d'une valeur falsifiée.
Chad

6

Voici une option pour omettre les clés dynamiques qui, je crois, n'a pas encore été mentionnée:

const obj = { 1: 1, 2: 2, 3: 3, 4: 4 };
const removeMe = 1;

const { [removeMe]: removedKey, ...newObj } = obj;

removeMeest aliasé removedKeyet ignoré. newObjdevient { 2: 2, 3: 3, 4: 4 }. Notez que la clé supprimée n'existe pas, la valeur n'était pas simplement définie sur undefined.


Belle solution. J'ai eu un cas d'utilisation similaire (clé dynamique dans le réducteur).
ericgio

4

PLUS FACILE

const allAlphabets = {a: 1, b: 2, c: 3, ..., z:26};
const { b, ...allExceptOne } = allAlphabets;
console.log(allExceptOne);   // {a: 1, c: 3, ..., z:26}

3

Lodash omettent

let source = //{a: 1, b: 2, c: 3, ..., z:26}
let copySansProperty = _.omit(source, 'b');
// {a: 1, c: 3, ..., z:26}

oui, Lodash est une option élégante, mais j'essayais de faire la même chose avec vanilla ES6
andreasonny83

3

Vous pouvez également utiliser l'opérateur d'étalement pour ce faire

const source = { a: 1, b: 2, c: 3, z: 26 }
const copy = { ...source, ...{ b: undefined } } // { a: 1, c: 3, z: 26 }

2
Semble super astucieux. Cela garde cependant la clé non définie danscopy
kano

vous pouvez donc supprimer les clés non définies s'il y en a les seules
Victor

1
Je ne sais pas pourquoi vous avez fait l'étalement supplémentaire dans la copie, const copy = { ...source, b: undefined } se résume exactement à la même chose.
bert bruynooghe

3

Les solutions ci-dessus utilisant la structuration souffrent du fait que vous avez une variable utilisée, ce qui peut provoquer des plaintes d'ESLint si vous l'utilisez.

Voici donc mes solutions:

const src = { a: 1, b: 2 }
const result = Object.keys(src)
  .reduce((acc, k) => k === 'b' ? acc : { ...acc, [k]: src[k] }, {})

Sur la plupart des plateformes (sauf IE sauf si vous utilisez Babel), vous pouvez également faire:

const src = { a: 1, b: 2 }
const result = Object.fromEntries(
  Object.entries(src).filter(k => k !== 'b'))


2

Si vous avez affaire à une énorme variable, vous ne voulez pas la copier puis la supprimer, car cela serait inefficace.

Une simple boucle for avec un contrôle hasOwnProperty devrait fonctionner, et elle est beaucoup plus adaptable aux besoins futurs:

for(var key in someObject) {
        if(someObject.hasOwnProperty(key) && key != 'undesiredkey') {
                copyOfObject[key] = someObject[key];
        }
}

1
La solution d'opérateur d'étalement fait exactement la même chose avec une syntaxe beaucoup plus agréable.
david.pfx

2

Et ça? Je n'ai jamais trouvé ce bagout mais j'essayais simplement d'exclure une ou plusieurs propriétés sans avoir besoin de créer un objet supplémentaire. Cela semble faire l'affaire, mais il y a des effets secondaires que je ne peux pas voir. Pour sûr, ce n'est pas très lisible.

const postData = {
   token: 'secret-token',
   publicKey: 'public is safe',
   somethingElse: true,
};

const a = {
   ...(({token, ...rest} = postData) => (rest))(),
}

/**
a: {
   publicKey: 'public is safe',
   somethingElse: true,
}
*/

2

Je l'ai fait de cette façon, comme un exemple de mon réducteur Redux:

 const clone = { ...state };
 delete clone[action.id];
 return clone;

En d'autres termes:

const clone = { ...originalObject } // note: original object is not altered
delete clone[unwantedKey]           // or use clone.unwantedKey or any other applicable syntax
return clone                        // the original object without the unwanted key

Semble beaucoup de travail supplémentaire, par rapport à la réponse acceptée d'il y a 3 ans (et les deux options reposent sur le transpiling pour de nombreux navigateurs).
carpiediem

J'ai un cas d'utilisation similaire (réducteur), j'ai donc trouvé une belle façon de prendre en charge les clés dynamiques sans mutation. Fondamentalement: const { [removeMe]: removedKey, ...newObj } = obj;- voir ma réponse sur cette question.
goldins

1

Je l'ai fait récemment de cette manière très simple:

const obj = {a: 1, b: 2, ..., z:26};

en utilisant simplement l' opérateur spread pour séparer la propriété indésirable:

const {b, ...rest} = obj;

... et object.assign pour ne prendre que la partie "reste":

const newObj = Object.assign({}, {...rest});

3
restest déjà un nouvel objet - vous n'avez pas besoin de la dernière ligne. De plus, cela est identique à la solution acceptée.
carpiediem

0
const x = {obj1: 1, pass: 2, obj2: 3, obj3:26};

const objectWithoutKey = (object, key) => {
  const {[key]: deletedKey, ...otherKeys} = object;
  return otherKeys;
}

console.log(objectWithoutKey(x, 'pass'));

1
Bien que ce code puisse fournir une solution à la question, il est préférable d'ajouter du contexte pour expliquer pourquoi / comment cela fonctionne. Cela peut aider les futurs utilisateurs à apprendre et à appliquer ces connaissances à leur propre code. Vous êtes également susceptible d'avoir des commentaires positifs des utilisateurs sous forme de votes positifs, lorsque le code est expliqué.
borchvm
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.