在JavaScript对象中删除嵌套属性

31

我有一个如下的JS对象:

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

我想删除名为“first”的租户的“已过期”属性,我应该这样做吗?

delete tenants['first']['expired'];
注意:此问题比问题How do I remove a property from a JavaScript object?更具体,因为我的问题关注于“嵌套”的部分。

1
简短回答:是的。更多信息请参见:https://dev59.com/5nVC5IYBdhLWcg3wsTfv - jeff carey
7个回答

29

可以,这个方法可行。

delete tenants['first']['expired']; 或者 delete tenants.first.expired;

如果你只是想把它从JSON.stringify()中排除,在这种情况下你也可以将其设置为undefined,比如 tenants['first']['expired'] = undefined;


17
如果您的应用程序正在使用lodash,则_.unset是删除嵌套属性的安全方法。您可以指定嵌套键,而不必担心它们是否存在。
let games = { 'hitman': [{ 'agent': { 'id'47 } }] };
_.unset(games, 'hitman[0].agent.id');
_.unset(games, 'hitman[0].muffin.cupcake'); // won't break

进一步阅读:https://lodash.com/docs/4.17.15#unset

2
我知道lodash有一些东西,但找不到我要的。谢谢你提供了一个标准解决方案,而不是一个自定义函数。 - Jordan Papaleo
1
我喜欢lodash如何消除嵌套数据操作的所有焦虑。 - nipunasudha

16
如果您想删除的属性以字符串形式存储,您可以使用此函数。
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()];
};

使用示例

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

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

这在处理数组时效果不佳,因为它会在删除的数组索引处留下一个“空”值。 - Andrew Gray

5
如果您想要删除任意深度对象中特定名称的属性,建议使用一款经过实战验证的库。您可以使用 DeepDash,这是 Lodash 的扩展。DeepDash
  // 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;
  });

如果你更愿意获得一个新的副本(而不是改变现有对象),那么DeepDash还有一个omitDeep函数可供使用,它将返回新的对象。


3
我想到了这个:
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]
}

使用方法:

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

2

如果您的密钥路径由.分隔,例如在您的情况下为first.expired,您可以执行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);


0

使用现代的JS,您可以简单地这样做:

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

通过使用可选链,您可以安全地尝试删除可能不存在的对象上的嵌套属性。
请查看mdn网站以检查浏览器兼容性。
注意:可选链也适用于大括号

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接