web-dev-qa-db-fra.com

Cloner un objet js sauf une clé

J'ai un objet plat JS:

{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 procéder (préférant utiliser es6/7 si possible)?

207
fox

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 transpilé 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"]);
310
Ilya Palkin
var clone = Object.assign({}, {a: 1, b: 2, c: 3});
delete clone.b;

ou si vous acceptez que la propriété soit indéfinie:

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

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:

55
Paul Kögel

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

_.omit(x, 'b')

Ou ramda.

R.omit('b', x)
53
dashmug

J'utilise cette syntaxe one-liner ES6,

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

Vous pouvez écrire une fonction d'assistance simple pour cela. Lodash a une fonction similaire portant 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

20
just-boris

Peut-être quelque chose comme ça:

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

Est-ce suffisant? Ou est-ce que c ne peut pas être copié?

9
clean_coding

Utilisation de la destruction 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}
6
Ivan Nosov

Hey, vous avez apparemment tendance à faire référence à 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"}
6
Chris Fust

Lodash omettre

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

Et ça? Je n'ai jamais trouvé ce motif, 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. Bien 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
andreasonny83

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

Une simple boucle for avec une vérification 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];
        }
}
2
HoldOffHunger

Vous pouvez aussi utiliser l'opérateur spread pour le faire

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

Les solutions ci-dessus qui utilisent la structuration souffrent du fait que vous avez une variable utilisée, ce qui pourrait entraîner des plaintes de la part d'ESLint si vous l'utilisez.

Alors voici 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 effectuer les opérations suivantes:

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

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

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

en utilisant simplement opérateur de propagation 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});
2
Pepdbm 7

Je l'ai accompli de cette façon, à titre d'exemple avec 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
1
Jonathan Tuzman

Cela devrait aussi le faire; Je suis à peu près sûr que 'delete' fonctionne aussi avec les tableaux associatifs:

var copy = (obj, del)=>{
    delete obj.del;
    return obj;
}
0
Raphael Spoerri