36

I have a JS object like this:

var tenants = {
    'first': {
        'name': 'first',
        'expired': 1
    },
    'second': {
        'name': 'second'
    }
}

And I'd like to delete the 'expired' property of tenant 'first', should I just do this?

delete tenants['first']['expired'];

Note: this question is more specific than the question: How do I remove a property from a JavaScript object?, in that my question focuses on the 'nested' part.

1

7 Answers 7

30

Yes. That would work.

delete tenants['first']['expired']; or delete tenants.first.expired;.

If you are deleting it only because you wanted to exclude it from JSON.stringify(), you can also just set it to undefined, like tenants['first']['expired'] = undefined;

Sign up to request clarification or add additional context in comments.

Comments

17

If the property you want to delete is stored in a string, you can use this function

function deletePropertyPath (obj, path) {

  if (!obj || !path) {
    return;
  }

  if (typeof path === 'string') {
    path = path.split('.');
  }

  for (var i = 0; i < path.length - 1; i++) {

    obj = obj[path[i]];

    if (typeof obj === 'undefined') {
      return;
    }
  }

  delete obj[path.pop()];
};

Example Usage

var tenants = {
    'first': {
        'name': 'first',
        'expired': 1
    },
    'second': {
        'name': 'second'
    }
}

var property = 'first.expired';    
deletePropertyPath(tenants, property);

1 Comment

This doesn't work well with arrays has it leave a "empty" value at the removed array index.
17

If your app is using lodash, then _.unset is a safe way for deleting nested properties. You can specify nested keys without worrying about their existence.

let games = { 'hitman': [{ 'agent': { 'id': 47 } }] };
_.unset(games, 'hitman[0].agent.id');
_.unset(games, 'hitman[0].muffin.cupcake'); // won't break

further reading: https://lodash.com/docs/4.17.15#unset

2 Comments

I knew lodash had something but could not find what I was looking for. Thanks for putting up a standard solution instead of a custom function.
I love how lodash takes away all the anxiety of nested data operations.
5

If you want to delete a property with a particular name in an arbitrarily deep object, I would recommend that you use a battle-tested library. You can use DeepDash, an extension to Lodash.

  // Recursively remove any "expired" properties
  _.eachDeep(e, (child, prop, parent, ctx):boolean => {
    if (prop === 'expired') {
      delete parent[prop];
      return false; // per docs, this means do not recurse into this child
    }
    return true;
  });

And if you would rather have a new copy (rather than mutating the existing object), DeepDash also has an omitDeep function you can use that will return the new object.

Comments

4

I came up with this:

const deleteByPath = (object, path) => {
  let currentObject = object
  const parts = path.split(".")
  const last = parts.pop()
  for (const part of parts) {
    currentObject = currentObject[part]
    if (!currentObject) {
      return
    }
  }
  delete currentObject[last]
}

Usage:

deleteByPath({ "a" : { "b" : true }},"a.b")

Comments

2

If you have the path of the key separated by ., say first.expired in your case, you can do deleteKey(tenants, 'first.expired'):

const deleteKey = (obj, path) => {
    const _obj = JSON.parse(JSON.stringify(obj));
    const keys = path.split('.');

    keys.reduce((acc, key, index) => {
        if (index === keys.length - 1) {
            delete acc[key];
            return true;
        }
        return acc[key];
    }, _obj);

    return _obj;
}

let tenants = {
    'first': {
        'name': 'first',
        'expired': 1
    },
    'second': {
        'name': 'second'
    }
};

const PATH_TO_DELETE = 'first.expired';

tenants = deleteKey(tenants, PATH_TO_DELETE);
console.log('DELETE SUCCESSFUL:', tenants);

Comments

0

With modern JS you can simple do it this way:

const tenants = {
  first: {
    name: 'first',
    expired: 1
  },
  second: {
    name: 'second'
  }
}

delete tenants?.first?.expired;
delete tenants?.second?.expired;
delete tenants?.third?.expired;

console.log(tenants);

By using optional chaining you're able to safely try to remove nested properties on objects that might not exist.

Check the mdn site to check browser compatibility

NOTE: Optional chaining does also works with braces

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.