简体   繁体   English

动态删除对象属性 JavaScript

[英]Dynamically delete object property JavaScript

I have the following code to get a key for a given object.我有以下代码来获取给定对象的键。 So for the object {"hello": {"data": {"a": "world", "b": "random"}}} if the key passed in was hello.data.a , the output would be world .所以对于对象{"hello": {"data": {"a": "world", "b": "random"}}}如果传入的键是hello.data.a ,则输出将是world .

(object, key) => {
    const keyParts = key.split(".");
    let returnValue = object;
    keyParts.forEach((part) => {
        if (returnValue) {
            returnValue = returnValue[part];
        }
    });
    return returnValue;
}

I'm trying to figure out how I can delete a property dynamically in the same fashion.我试图弄清楚如何以相同的方式动态删除属性。 So for example for the same object and key, it would mutate the object to be {"hello": {"data": {"b": "random"}}} .因此,例如对于相同的对象和键,它会将对象变异为{"hello": {"data": {"b": "random"}}}

Basically I want the same behavior as delete object.hello.data.a .基本上我想要delete object.hello.data.a相同的行为。 But the problem is the hello.data.a part is a dynamic string passed in. Of course something like delete object[key] wouldn't work since the key has nested levels.但问题是hello.data.a部分是传入的动态字符串。当然,像delete object[key]这样的东西不起作用,因为键具有嵌套级别。 It would work if it is only 1 level deep, but wouldn't work for nested items.如果它只有 1 级深,它会起作用,但不适用于嵌套项目。

One other important note is that performance is extremely important in this case.另一个重要的注意事项是,在这种情况下,性能极其重要。 So although creating a new object and copying over all the properties except for the one I want to delete might work, but I have severe concerns of the performance impact of that vs the delete keyword.因此,尽管创建一个新对象并复制除我要删除的对象之外的所有属性可能会起作用,但我非常担心该对象与delete关键字对性能的影响。

Due to other external factors I also do not want to set the property value to null or undefined .由于其他外部因素,我也不想将属性值设置为nullundefined I want the key to actually be removed from the object.我希望从对象中实际删除密钥。

How can I achieve this?我怎样才能做到这一点?

To delete, .pop() off the last key to identify the property to remove.要删除,请关闭最后一个键的.pop()以标识要删除的属性。 If you want to avoid the delete keyword, you'll also want to replace the last object on which that key is on, rather than mutate it, so .pop() off the next last key as well.如果您想避免使用delete关键字,您还需要替换该键所在的最后一个对象,而不是对其进行变异,因此.pop()关闭下一个最后一个键。

Then, use your current method (or .reduce ) to access the last outer object .然后,使用您当前的方法(或.reduce )访问最后一个外部对象 To delete one of its keys:要删除其中一个键:

  • To mutate with delete , using the saved key, use delete[nextLastKey][lastKey]要使用delete进行变异,请使用保存的密钥,使用delete[nextLastKey][lastKey]
  • To create an entirely new object but without the saved key, use rest syntax to exclude that lastKey during the creation of a new one, then assign the new object to the nextLastKey of the parent object:要创建一个全新的对象但没有保存的键,请使用 rest 语法在创建新对象期间排除该lastKey ,然后将新对象分配给父对象的nextLastKey

 const fn = (object, key) => { const keys = key.split("."); const lastKey = keys.pop(); const nextLastKey = keys.pop(); const nextLastObj = keys.reduce((a, key) => a[key], object); // delete version: // delete nextLastObj[nextLastKey][lastKey] // non-delete version: const { [lastKey]: _, ...rest } = nextLastObj[nextLastKey]; nextLastObj[nextLastKey] = rest; return object; } const obj = {"hello": {"data": {"a": "world", "b": "random"}}}; const result = fn(obj, 'hello.data.a'); console.log(result);

Actually your answer is right there - in the code snippet that you provided.实际上,您的答案就在那里 - 在您提供的代码片段中。 It just needs a little modification, like so:它只需要一点点修改,就像这样:

 const delProp = (object, key) => { const keyParts = key.split("."); let returnValue = object; let parent, lastKey; // added keyParts.forEach((part) => { if (returnValue) { parent = returnValue; // added lastKey = part; // added returnValue = parent[lastKey]; } }); if(parent) { delete parent[lastKey]; // added } return returnValue; } const obj = {"hello": {"data": {"a": "world", "b": "random"}}}; console.log(delProp(obj, 'hello.data.a')); console.log(obj)

Also note that in JS for loops are essentially more efficient than forEach Array function.还要注意,在 JS 中for循环本质上比forEach Array 函数更有效 Thus I would change the related part a la:因此,我将更改相关部分 a la:

for (const i = 0, i = keyParts.length; i++) {
    // ...
}

you can use lodash library _.omit function你可以使用lodash库 _.omit 函数

_omit(object, path)

https://lodash.com/docs/4.17.15#omit https://lodash.com/docs/4.17.15#omit

be careful cause this function doesn't mutate the object instead it returns a new object without the removed key.请小心,因为此函数不会改变对象,而是返回一个没有删除键的新对象。

You can still delete using the bracket syntax.您仍然可以使用括号语法进行删除。

I added another example since the naysayers seem to think it cannot be done.我添加了另一个例子,因为反对者似乎认为这是不可能的。 As long as you know the basic object it should make no difference.只要您知道基本对象,它就应该没有区别。 I will leave the split by "."我将通过“。”离开拆分。 as a simple exercise here as it is not part of the core question.作为这里的一个简单练习,因为它不是核心问题的一部分。

 var thing = {"hello": {"data": {"a": "world", "b": "random"}}}; delete thing.hello.data["a"]; console.log(thing); var thing2 = {"hello": {"data": {"a": "world", "b": "random"}}}; delete thing2["hello"]["data"]["a"]; console.log(thing2);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM