lgc_ustc
lgc_ustc

Reputation: 1664

Deleting nested property in javascript object

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.

Upvotes: 36

Views: 64952

Answers (7)

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

Upvotes: 0

Robert
Robert

Reputation: 1362

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.

Upvotes: 5

Richard
Richard

Reputation: 14625

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

Upvotes: 4

ksankar
ksankar

Reputation: 485

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

Upvotes: 17

Deepak Grover
Deepak Grover

Reputation: 41

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

Upvotes: 2

Dónal
Dónal

Reputation: 187529

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

Upvotes: 17

Meligy
Meligy

Reputation: 36594

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;

Upvotes: 30

Related Questions