45

In JavaScript, I can delete an object's key with

delete myObject[myKey];

Is there an efficient way to delete multiple keys using one line? Something that looks like:

multiDelete myObject[keyOne, keyTwo, keyThree];

Robin De Schepper
  • 4,942
  • 4
  • 35
  • 56
  • 1
    Efficient from what perspective? Using `delete` is already inefficient in first place. – zerkms Sep 12 '15 at 02:39
  • 1
    *but not all of the values in the parent key that encapsulate the keys I want to delete* Could you clarify? What do you mean by "parent key" or "encapsulate the keys"? –  Sep 12 '15 at 05:13

8 Answers8

101

Here's a one-liner similar to what you're requesting.

var obj = {a: 1, b: 2, c: 3, d: 4, e: 5 };

['c', 'e'].forEach(e => delete obj[e]);

// obj is now {a:1, b:2, d:4}
James
  • 20,957
  • 5
  • 26
  • 41
37

You can also use Object Destructuring.

const obj = {
        a: 'dog',
        b: 'cat',
        c: 'mouse',
        d: 'cow',
        e: 'horse',
    };
const {a, e, ...updatedObject} = obj;

// output
console.log(updatedObject)
Abhinash Majhi
  • 499
  • 1
  • 4
  • 16
roraima
  • 609
  • 5
  • 6
10

There is one simple fix using the library lodash.

The _.omit function takes your object and an array of keys that you want to remove and returns a new object with all the properties of the original object except those mentioned in the array.

This is a neat way of removing keys as using this you get a new object and the original object remains untouched. This avoids the problem of mutation where if we removed the keys in the original object all the other parts of code using that object might have a tendency to break or introduce bugs in the code.

Example:

var obj = {x:1, y:2, z:3};
var result = _.omit(obj, ['x','y']);
console.log(result);

//Output
result = {z:3};

Link for the documentation of the same Click Here

Eksa
  • 121
  • 1
  • 4
7

There is no built in js function to delete multiple keys yet, you can use any library for this such as underscore.js to do this.

_.omit({name: 'moe', age: 50, userid: 'moe1'}, 'userid');
=> {name: 'moe', age: 50}

//or you can use function to filter keys 

_.omit({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object){
  return _.isNumber(value);
});
=> {name: 'moe', userid: 'moe1'}
Mohan Dere
  • 4,497
  • 1
  • 25
  • 21
4

There is no built-in function, but one way you could do it is to add the multidelete method to the Object prototype. It's perhaps a little bit overkill, but you might find it useful.

if (!('multidelete' in Object.prototype)) {
    Object.defineProperty(Object.prototype, 'multidelete', {
        value: function () {
            for (var i = 0; i < arguments.length; i++) {
                delete this[arguments[i]];
            }
        }
    });
}

var obj = { a: 1, b: 2, c: 3, d: 4, e: 5 };

obj.multidelete('c', 'e'); // { a: 1, b: 2, d: 4 };

DEMO

Andy
  • 61,948
  • 13
  • 68
  • 95
  • If you're going to loop over the arguments like that, there is no need to slice it first. Also, `enumerable` and `configurable` default to `false` and do not need to be explicitly specified. –  Sep 12 '15 at 05:11
1

If you want a solution that feels built-in, you could add a utility function that works like Object.defineProperties(), so you can add properties to a given object, but now also delete properties by handing in a null property descriptor.

Object.defineProperties() throws an error if a property descriptor is not an object, so we can safely use a "falsy" value to indicate that the property is to be deleted.

Here is the code:

function unDefineProperties(obj, propertyDescriptors) {
  const [normalDescriptors, toBeDeletedDescriptors] =
    partition(Object.entries(propertyDescriptors),([_, descriptor]) => descriptor);
  Object.defineProperties(obj, Object.fromEntries(normalDescriptors));
  toBeDeletedDescriptors.forEach(([name, _]) => delete obj[name]);
  return obj;
}

The name of the function is supposed to be read as "(un)define properties", i.e. "define or delete properties".

It splits the given propertyDescriptors into the "normal" ones with a non-"falsy" value and the "to-be-deleted" ones with a "falsy" value, using the utility function partition (defined in the code snippet below, borrowed from this answer).

It then calls Object.defineProperties() with a property descriptors object reconstructed from the "normal" entries.

After that (because the first step may fail due to incorrect property descriptors), all "to-be-deleted" entries delete the corresponding properties in obj.

Finally, obj is returned, to mimic the convenient behavior of Object.defineProperties().

The resulting function is compatible with the original Object.defineProperties() (of course apart from the behavior for "falsy" property descriptors) and thus could be used as a replacement for that original function. If you want to do so, for consistency, you should also replace Object.defineProperty() (singular!) by a similar function that handles a "falsy" property descriptor by deleting the corresponding property (left as an exercise for the reader ;-)).

Here is the complete code with a usage example:

const partition = (array, filter) =>
    array.reduce(([pass, fail], e, i) =>
        ((filter(e, i, array) ? pass : fail).push(e), [pass, fail]),
        [[], []]);

function unDefineProperties(obj, propertyDescriptors) {
  const [normalDescriptors, toBeDeletedDescriptors] =
    partition(Object.entries(propertyDescriptors),([_, descriptor]) => descriptor);
  Object.defineProperties(obj, Object.fromEntries(normalDescriptors));
  toBeDeletedDescriptors.forEach(([name, _]) => delete obj[name]);
  return obj;
}

// Usage example:

const obj = { a: 'A', b: 'B', c: 'C'};

unDefineProperties(obj, {
  a: null,
  c: null,
  d: { value: "D", enumerable: true }
});

console.log(obj); // logs { "b": "B", "d": "D" }
YetAnotherFrank
  • 386
  • 1
  • 8
0

You may create an array of keys to delete by a string and iterate over the object to delete them

var obj = {key1: 1, key2: 2, key3: 3 };

"key1 key2 key3".split(" ").forEach(e => delete obj[e]);
MsO
  • 87
  • 1
  • 13
0

I found another solution using a loop through Object.entries() which may be helpful:

var array = {1:'a',2:'b',3:'c',4:'d'};

for (var [key, char] of Object.entries(array)) {
   delete array[key];
}
  • I don't think `array` is initialized properly... – kelsny May 20 '22 at 19:48
  • Thank you, I didn't pay attention, it should be braces { } and not square brackets [] – yassine mt May 23 '22 at 07:45
  • It makes no sense to use `Object.entries()` and then just use the keys. `Object.keys()` is what you are looking for. Anyway, it does not answer the OP's question, because you would remove _all_ properties from the "array" (which is an object). – YetAnotherFrank Feb 13 '23 at 11:05