How to omit specific properties from an object in JavaScript
Asked Answered
L

20

132

Is there a clean way to return a new object that omits certain properties that the original object contains without having to use something like lodash?

Lockyer answered 25/3, 2017 at 2:9 Comment(3)
Code? I would suggest create a new anonymous type, passing in what you want to keepFrederik
A similar question was asked here #34699405Carmel
Possible duplicate of clone a js object except for one keyCalefaction
A
233
const { bar, baz, ...qux } = foo

Now your object qux has all of the properties of foo except for bar and baz.

Archuleta answered 12/3, 2019 at 1:6 Comment(8)
Keep in mind, this will not clone the object. Updating any values ion qux will update the values in foo. Javascript objects are passed by reference.Norvell
@MiroslavGlamuzina that's not correct. If you change a value in qux then foo's value will not be updated. However, if the value of a property of qux is an object and you change something in that object, then the object referenced by the corresponding property of foo would also be changed.Butylene
Just a small note, in chrome (as of version 87.0.4280.141), this doesn't work with quoted property names. I don't know about other environments: const { "bar", 'baz', ...qux } = fooTunic
@Tunic some of your keys are quoted, that's probably whyIrremeable
I don't think this is a great solution, because it has the side effect of creating new variables. If any of the properties you're trying to omit happen to match preexisting constants or variables, you'll get an error or unexpected behaviour const x = "Anything"; const obj = { x: "Foo", y:"Bar"}; const {x, ...no_x} = obj;Chokebore
for picking 'string' fields you can use such syntax: const { ["bar"]:bar, ["baz"]:bas, ...qux } = foo If you have const objKey = "bar"; you can usr such syntax: const { [${objKey}]:bar, ["baz"]:bas, ...qux } = fooRitenuto
@Chokebore You could always rename them: const { x: _x, ...no_x } = obj;Befriend
@VictorZamanian True, and that's better because you can pick new names, but it does still create variables. E.g. now if const _x = "Something" was declared earlier this will fail, as _x is being reassigned. Just feels odd there's not a good shorthand that doesn't force you to create new variables.Chokebore
T
58

In modern environments you can use this code snippet:

function omit(key, obj) {
  const { [key]: omitted, ...rest } = obj;
  return rest;
}
Trommel answered 26/6, 2019 at 12:57 Comment(4)
"modern environments" meaning if you're shipping un-transpiled code, this will work on 93% of browsers. See full compatibility at caniuse.com/…Vicereine
who ships untranspiled code?Cobber
Not supported by IE. But IE was dead at june 14, 2022.I think the word "modern" here means forward thinkingSterculiaceous
Updated caniuse link: caniuse.com/es6 Currently 97.08% of users have full es6 compatability in their browserPhosphatase
C
43

If you know the list of the properties that you want preserved as well as omitted, the following "whitelisting" approach should work:

const exampleFilter = ({ keepMe, keepMeToo }) => ({ keepMe, keepMeToo })

console.log(
  exampleFilter({
    keepMe: 'keepMe',
    keepMeToo: 'keepMeToo',
    omitMe: 'omitMe',
    omitMeToo: 'omitMeToo'
  })
)
Calefaction answered 25/3, 2017 at 2:20 Comment(3)
This has blown my mind, could you explain how it works?Olympium
It uses a combination of parameter destructuring and default object values (each key is mapped to the value held by the variable of the same name, e.g. { keepMe, keepMeToo } is like { keepMe: keepMe, keepMeToo: keepMeToo }.Calefaction
Great anwser! Wonder if there is a way to avoid duplicating field names, couldn't find any.Askew
B
27

There's the blacklist package on npm which has a very flexible api.

Also a situational trick using the object rest-spread proposal (stage-3).

const {a, b, ...rest} = {a: 1, b: 2, c: 3, d: 4};
a // 1
b // 2
rest // {c: 3, d: 4}

This is often used in react components where you want to use a few properties and pass the rest as props to a <div {...props} /> or similar.

Beachcomber answered 25/3, 2017 at 3:27 Comment(0)
A
24

A solution that hasn't been mentioned yet:

Omit single

o = {a: 5, b: 6, c: 7}
Object.fromEntries(Object.entries(o).filter(e => e[0] != 'b'))
// Object { a: 5, c: 7 }

Omit multiple

o = {a: 1, b: 2, c: 3, d: 4}
exclude = new Set(['a', 'b'])
Object.fromEntries(Object.entries(o).filter(e => !exclude.has(e[0])))
// Object { c: 3, d: 4 }

The Set above is used because it leads to linearithmic complexity even if the number of elements in exclude is in the same asymptotic equivalence class as the number of elements in o.

Aciculum answered 13/4, 2021 at 12:14 Comment(2)
Solution that helps you omit a field without leaving unused variable in codeRitenuto
Great answer. I turned these into functions are posted it as a separate answer https://mcmap.net/q/172460/-how-to-omit-specific-properties-from-an-object-in-javascriptFrigate
I
12

Omit and array of keys, using ES7 w/ recursion.

function omit(keys, obj) {
  if (!keys.length) return obj
  const { [keys.pop()]: omitted, ...rest } = obj;
  return omit(keys, rest);
}

This builds on top of @Eddie Cooro answer.

Importance answered 29/2, 2020 at 19:57 Comment(3)
non-recursive version: ` function omit(keys, obj) { return keys.reduce((a, e) => { const { [e]: omit, ...rest } = a; return rest; }, obj) } `Grapheme
typescript non recursive version: export function omitObjectKeys<T extends object = {}>( keys: string[], obj: T, ): Partial<T> { return (keys as any).reduce((a: Partial<T>, e: keyof T) => { const { [e]: omitted, ...rest } = a; return rest; }, obj); }Modernistic
This is unnecessarily inefficient (with practical implications), since it copies the entire object for every key that needs to be omitted.Seena
C
7

You can use Object.assign(), delete

var not = ["a", "b"]; // properties to delete from obj object
var o = Object.assign({}, obj);
for (let n of not) delete o[n];

Alternatively

var props = ["c", "d"];
let o = Object.assign({}, ...props.map(prop => ({[prop]:obj[prop]})));
Constanceconstancia answered 25/3, 2017 at 2:22 Comment(0)
O
7

Sure, why not something like:

var original = {
  name: 'Rory',
  state: 'Bored',
  age: '27'
};

var copied = Object.assign({}, original);
delete copied.age;

console.log(copied);

https://jsfiddle.net/4nL08zk4/

Olympium answered 25/3, 2017 at 2:22 Comment(0)
I
7

If you already use lodash, you may also do omit(obj, ["properties", "to", "omit"]) to get a new Object without the properties provided in the array.

Indescribable answered 4/6, 2019 at 9:21 Comment(0)
C
6

Building on other answers: if there's not a need for reusability or abstraction this will remove blacklisted properties inline with an IIFE.

(
  ({
    // Properties to remove from `someObject`.
    omitMe,
    omitMeToo,
    // The rest of `someObject`, to keep.
    ...keep
  }) => keep
)(someObject)

Example

const someObject = {
  keepMe: 'keepMe',
  keepMeToo: 'keepMeToo',
  omitMe: 'omitMe',
  omitMeToo: 'omitMeToo',
};

console.log(
  (
    ({
      omitMe,
      omitMeToo,
      ...keep
    }) => keep
  )(someObject)
);
Chantal answered 4/9, 2022 at 22:50 Comment(0)
O
1

No answer seemed to allow nested path specifications using dot notation. Here's a solution for that:

const omit = (obj, keys) => {
  if (!keys.length) return obj;
  const key = keys.pop();
  const parts = key.split(".");
  if (parts.length > 1) {
    const { [parts[0]]: todo, ...rest } = obj;
    return {
      ...omit(rest, keys),
      [parts[0]]: omit(todo, [parts[1]]),
    };
  }
  const { [key]: omitted, ...rest } = obj;
  return omit(rest, keys);
};
    
var obj = {
  a: 1,
  b: 2,
  c: 3,
  d: {
    c: 3,
    e: 5
  }
};
console.log(omit(obj, ['b', 'd.c']));
Oxheart answered 5/5, 2022 at 13:21 Comment(0)
K
1

We want to exclude specific property of an javascript object.

Sample Input:

const foo={
    "bar":"sangram",
    "baz":"sagar",
    "mux":"sachin",
    "fch":"swapnil"

}
we want to omit a 'bar' property of this object foo.

Sample Output:

const foo={
    "baz":"sagar",
    "mux":"sachin",
    "fch":"swapnil"
}

Solution:

const foo={
    "bar":"sangram",
    "baz":"sagar",
    "mux":"sachin",
    "fch":"swapnil"

}
const { bar, ...qux } = foo
console.log(qux)

Output:

{ baz: 'sagar', mux: 'sachin', fch: 'swapnil' }

Kraigkrait answered 28/3 at 10:56 Comment(0)
R
0
function omitKeys(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; 
    }
Roswell answered 25/3, 2017 at 2:22 Comment(0)
D
0

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

Object.extract = function(obj, keys, exclude) {
  var clone = Object.assign({}, obj);
  if (keys && (keys instanceof Array)) {
    for (var k in clone) {
      var hasKey = keys.indexOf(k) >= 0;
      if ((!hasKey && !exclude) || (hasKey && exclude)) {
        delete clone[k];
      }
    }
  }
  return clone;
};

console.log('Extract specified keys: \n-----------------------');
var clone1 = Object.extract(obj, ['a', 'd']);
console.log(clone1);
console.log('Exclude specified keys: \n-----------------------');
var clone2 = Object.extract(obj, ['a', 'd'], true);
console.log(clone2);
Dairyman answered 25/3, 2017 at 4:17 Comment(0)
P
0
const data = { name : 'Micheal', passowrd : 'password', age: '44'}
const dataClean = data.toObject();
delete dataClean.password;
console.log(dataClean);
Puisne answered 7/6, 2022 at 22:5 Comment(0)
F
0

Taking Grant Zvolsky's answer and turning it into functions

function omit(obj, key) {
  return Object.fromEntries(Object.entries(obj).filter(e => e[0] != key))
}
/** Omits multiple keys. The exclude parameter is a Set of keys to exclude **/
function omitSet(obj, exclude) {
  return Object.fromEntries(
    Object.entries(obj).filter((e) => !exclude.has(e[0]))
  );
}

o = {a: 1, b: 2, c: 3, d: 4}
exclude = new Set(['a', 'b'])
console.log(omitSet(o, exclude));
// Object { c: 3, d: 4 }

Or in Typescript:

function omitSet(obj: object, exclude: Set<string>) {
  return Object.fromEntries(
    Object.entries(obj).filter((e) => !exclude.has(e[0]))
  );
}
Frigate answered 27/8, 2023 at 3:55 Comment(0)
C
0

Method for overwriting the value:

const props = { primary: true, anotherProp: "hello" };
const newProps = { ...props, primary: undefined }; // Overwrite primary property

result:

{ primary: undefined, anotherProp: "hello" }

Which is a useful case for React native elements:

<button
  {...{ ...props, primary: undefined }}
  type="button"
  className="my-button"
/>

React should not pass the undefined value as an argument and this should also work with TypeScript.

Cynewulf answered 9/10, 2023 at 18:30 Comment(0)
B
0

Taking Jeremy's answer but with the following modifications:

  • Adding type annotations (TypeScript)
  • Handling of Set internally so that you can pass an arbitrary amount of strings to the resulting variadic function
  • Key arguments will only be allowed that are actual keys inside the object

The following is TypeScript, for anyone finding that useful. You can also just remove the type annotations and get JS if that's what you need.

function omit<T extends Record<string, any>, K extends keyof T>(
  obj: T,
  ...keys: K[]
): Omit<T, K> {
  // I'm sure this could be done in a better way,
  // but if we don't do this we run into issues with
  // the interaction between Object.entries() and
  // Set<string | number | symbol>.
  const omitKeys = new Set(keys as string[]);

  return Object.fromEntries(
    Object.entries(obj).filter(([k]) => !omitKeys.has(k)),
  ) as Omit<T, K>;
}

const obj = {
  a: 1,
  b: 2,
  c: 4,
  x: "hello",
  y: "world",
};

console.log(omit(obj)); // { a: 1, b: 2, c: 4, x: "hello", y: "world" }
console.log(omit(obj, "x")); // { a: 1, b: 2, c: 4, y: "world" }
console.log(omit(obj, "x", "y")); // { a: 1, b: 2, c: 4 }
console.log(omit(obj, "d")); // Error! No property "d" in obj.
Befriend answered 5/1 at 11:7 Comment(0)
O
-1

One solution, I'm sure many others exist.

const testObj = {
    prop1: 'value1',
    prop2: 'value2',
    prop3: 'value3'
};

const removeProps = (...propsToFilter) => obj => {
   return Object.keys(obj)
   .filter(key => !propsToFilter.includes(key))
   .reduce((newObj, key) => {
       newObj[key] = obj[key];
       return newObj;
   }, {});
};


console.log(removeProps('prop3')(testObj));
console.log(removeProps('prop1', 'prop2')(testObj));

Edit: I always forget about delete...

const testObj = {
    prop1: 'value1',
    prop2: 'value2',
    prop3: 'value3'
};

const removeProps = (...propsToFilter) => obj => {
   const newObj = Object.assign({}, obj);
   propsToFilter.forEach(key => delete newObj[key]);
   return newObj;
};


console.log(removeProps('prop3')(testObj));
console.log(removeProps('prop1', 'prop2')(testObj));
Ottinger answered 25/3, 2017 at 2:24 Comment(0)
D
-3

I saw this question and I wanted to remove 1 specific key, not a full method, so here's my suggestion:

const originalObj = {wantedKey: 111, anotherWantedKey: 222, unwantedKey: 1010};
const cleanedObj = Object.assign(originalObj, {unwantedKey: undefined});
Doublecheck answered 16/9, 2020 at 18:50 Comment(3)
It does not work this way: if you have the value in the source - it overwrites the corresponding value in the target. In the given case, unwantedKey will be copied and be 1010.Shark
@Alexander, no. unwantedKey will be copied from the source to the target, yes, but it will be undefined in the target. Do note however that Object.hasOwn(cleanedObj, "unwantedKey") will be true. Another point to note here is that originalObj will also be modified, which may or may not be desirable.Befriend
"but it will be undefined in the target" is the reason why this solution is down-voted. The target must not have the unwatedKey at allSisyphean

© 2022 - 2024 — McMap. All rights reserved.