How can I clone a JavaScript object except for one key?

JavascriptEcmascript 6Ecmascript HarmonyEcmascript 2016

Javascript Problem Overview


I have a flat JS object:

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

I want to clone the object except for one element:

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

What's the easiest way to do this (preferring to use es6/7 if possible)?

Javascript Solutions


Solution 1 - Javascript

If you use Babel you can use the following syntax to copy property b from x into variable b and then copy rest of properties into variable y:

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

and it will be transpiled into:

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

Solution 2 - Javascript

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

or if you accept property to be undefined:

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

Solution 3 - Javascript

I use this ESNext one liner

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

Solution 4 - Javascript

For those who can't use ES6, you can use lodash or underscore.

_.omit(x, 'b')

Or ramda.

R.omit('b', x)

Solution 5 - Javascript

To add to Ilya Palkin's answer: you can even dynamically remove keys:

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

Demo in Babel REPL

Source:

Solution 6 - Javascript

You can write a simple helper function for it. Lodash has a similar function with the same name: omit

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}

Also, note that it is faster than Object.assign and delete then: http://jsperf.com/omit-key

Solution 7 - Javascript

Here's an option for omitting dynamic keys that I believe has not been mentioned yet:

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

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

removeMe is aliased as removedKey and ignored. newObj becomes { 2: 2, 3: 3, 4: 4 }. Note that the removed key does not exist, the value was not just set to undefined.

Solution 8 - Javascript

Maybe something like this:

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

Is this good enough? Or can't c actually get copied?

Solution 9 - Javascript

Using Object Destructuring

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}

Solution 10 - Javascript

How about this:

let clone = Object.assign({}, value);
delete clone.unwantedKey;

Solution 11 - Javascript

Hey seems like you run in to reference issues when you're trying to copy an object then deleting a property. Somewhere you have to assign primitive variables so javascript makes a new value.

Simple trick (may be horrendous) I used was this

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

Solution 12 - Javascript

You also can use spread operator to do this

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

Solution 13 - Javascript

I recently did it this very simple way:

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

just using spread operator to separate the unwanted property:

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

...and object.assign to take only the 'rest' part:

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

Solution 14 - Javascript

I accomplished it this way, as an example from my Redux reducer:

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

In other words:

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

Solution 15 - Javascript

The solutions above using structuring do suffer from the fact that you have an used variable, which might cause complaints from ESLint if you're using that.

So here are my solutions:

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

On most platforms (except IE unless using Babel), you could also do:

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

Solution 16 - Javascript

If you're dealing with a huge variable, you don't want to copy it and then delete it, as this would be inefficient.

A simple for-loop with a hasOwnProperty check should work, and it is much more adaptable to future needs :

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

Solution 17 - Javascript

Lodash omit

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

Solution 18 - Javascript

What about this? I never found this patter around but I was just trying to exclude one or more properties without the need of creating an extra object. This seems to do the job but there are some side effects I'm not able to see. For sure is not very readable.

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

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

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

Solution 19 - Javascript

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

Solution 20 - Javascript

I don't know exactly what you want to use this for, so I'm not sure if this would work for you, but I just did the following and it worked for my use case:

const newObj ={...obj, [key]: undefined}

Solution 21 - Javascript

If you use Ramda you can use its omit and clone functions to make a deep clone of your object and omit the unnecessary fields.

var object = {a: 1, b: 2, c: 3, y:25, z:26};
R.clone(R.omit(["z", "y"], object));

Solution 22 - Javascript

The delete keyword solution will throw a compilation error if you're using typescript, because it breaks the contract of the object you instantiated. And the ES6 spread operator solution (const {x, ...keys} = object) may throw an error depending on the linting configuration you're using on your project, since the x variable is not beign used. So I came up with this solution:

const cloneObject = Object.entries(originalObject)
	.filter(entry => entry[0] !== 'keyToRemove')
	.reduce((acc, keyValueTuple) => ({ ...acc, [keyValueTuple[0]]: keyValueTuple[1] }), {});

It solves the problem using the combination of Object.entries method (to get an array of key/value pairs of the original object) and the array methods filter and reduce. It looks verbose, but I think it's nice to have a one line chainable solution.

Solution 23 - Javascript

I had an object that I wanted to remove after utilizing its method. This is what worked for me.


/* Sample data */
let items = [
  {
    name: 'John',
    doc: {
      set: async (item) => {/*...sets docs on remote server*/}
    }
  },{
    name: 'Mary',
    doc: {
      set: async (item) => {/*...sets docs on remote server*/}
    }
  },{
    name: 'Jack',
    doc: {
      set: async (item) => {/*...sets docs on remote server*/}
    }
  }
]

/* mapping to promises */
const promises = items.map(({doc, ...item}) => doc.set(item)); 
// utilized doc and utilized `rest` of the items :)


Good Luck :)

Solution 24 - Javascript

Here are my two cents, on Typescript, slightly derived from @Paul's answer and using reduce instead.

function objectWithoutKey(object: object, keys: string[]) {
    return keys.reduce((previousValue, currentValue) => {
        // @ts-ignore
        const {[currentValue]: undefined, ...clean} = previousValue;
        return clean
    }, object)
}

// usage
console.log(objectWithoutKey({a: 1, b: 2, c: 3}, ['a', 'b']))

Solution 25 - Javascript

I have one object named: options with some keys

  let options = {       
        userDn: 'somePropertyValue',
        username: 'someValue',
        userSearchBase: 'someValue',
        usernameAttribute: 'uid',
        userPassword: 'someValue'
    }

I want to log all object excelp userPassword Property because Im testing something, I am using this code:

console.log(Object.keys(options).map(x => x + ': ' + (x === "userPassword" ? '---' : options[x])));

If you want to make it dynamic, just make a function and instead of explicitly putting userPassword you can place the value of the property you want to exclude

Solution 26 - Javascript

Clean and fast using lodash, With this solution, you are able to remove multiple keys and also without changing the original object. This is more extendable and more usable in different situations:

import * as _ from 'lodash';

function cloneAndRemove(
    removeTheseKeys: string[],
    cloneObject: any,
): object | never {
    const temp = _.cloneDeep(cloneObject);
    removeTheseKeys.forEach((key) => {
        delete temp[key];
    });

    return temp;
}

export { cloneAndRemove };

Solution 27 - Javascript

Here is a Typescript method to do that. Expects 2 arguments, the object and an array of strings containing keys to be removed:

removeKeys(object: { [key: string]: any }, keys: string[]): { [key: string]: any } {
  const ret: { [key: string]: any } = {};

  for (const key in object) {
    if (!keys.includes(key)) {
      ret[key] = object[key];
    }
  }

  return ret;
}

Solution 28 - Javascript

Using loadash deepclone function You can do:

const _obj = _.cloneDeep(obj);
delete _obj.key;

First clones the whole object into new object and then delete the desired key from the cloned object so that the original one doesn't get affected.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfoxView Question on Stackoverflow
Solution 1 - JavascriptIlya PalkinView Answer on Stackoverflow
Solution 2 - Javascriptmadox2View Answer on Stackoverflow
Solution 3 - JavascriptvdegenneView Answer on Stackoverflow
Solution 4 - JavascriptNoel LlevaresView Answer on Stackoverflow
Solution 5 - JavascriptPaul KögelView Answer on Stackoverflow
Solution 6 - Javascriptjust-borisView Answer on Stackoverflow
Solution 7 - JavascriptgoldinsView Answer on Stackoverflow
Solution 8 - Javascriptclean_codingView Answer on Stackoverflow
Solution 9 - JavascriptIvan NosovView Answer on Stackoverflow
Solution 10 - JavascriptLars Juel JensenView Answer on Stackoverflow
Solution 11 - JavascriptChris FustView Answer on Stackoverflow
Solution 12 - JavascriptMickael M.View Answer on Stackoverflow
Solution 13 - JavascriptPepdbm 7View Answer on Stackoverflow
Solution 14 - JavascriptJonathan TuzmanView Answer on Stackoverflow
Solution 15 - Javascriptbert bruynoogheView Answer on Stackoverflow
Solution 16 - JavascriptHoldOffHungerView Answer on Stackoverflow
Solution 17 - JavascriptOscarRyzView Answer on Stackoverflow
Solution 18 - Javascriptandreasonny83View Answer on Stackoverflow
Solution 19 - Javascriptghiles ybeggazeneView Answer on Stackoverflow
Solution 20 - JavascriptBeto ShiverView Answer on Stackoverflow
Solution 21 - Javascriptvarad11View Answer on Stackoverflow
Solution 22 - JavascriptMatheus BaldissaraView Answer on Stackoverflow
Solution 23 - JavascriptAakashView Answer on Stackoverflow
Solution 24 - JavascriptOscar NevarezView Answer on Stackoverflow
Solution 25 - JavascriptcrazyXView Answer on Stackoverflow
Solution 26 - JavascriptKasir BaratiView Answer on Stackoverflow
Solution 27 - JavascriptRafa CamónView Answer on Stackoverflow
Solution 28 - JavascriptMR_AMDEVView Answer on Stackoverflow