如何从JavaScript对象中删除属性?

7445

给定一个对象:

let myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};

如何删除属性regex以得到以下的myObject

let myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI"
};
38个回答

14
如果你想要删除嵌套在对象中的属性,那么可以使用以下递归函数,并将属性路径作为第二个参数传入:
var deepObjectRemove = function(obj, path_to_key){
    if(path_to_key.length === 1){
        delete obj[path_to_key[0]];
        return true;
    }else{
        if(obj[path_to_key[0]])
            return deepObjectRemove(obj[path_to_key[0]], path_to_key.slice(1));
        else
            return false;
    }
};

示例:

var a = {
    level1:{
        level2:{
            level3: {
                level4: "yolo"
            }
        }
    }
};

deepObjectRemove(a, ["level1", "level2", "level3"]);
console.log(a);

//Prints {level1: {level2: {}}}

13

丹的声明认为,使用 'delete' 删除 JavaScript 对象属性的速度非常慢,并且他发布的基准测试结果受到了质疑。因此我在 Chrome 59 中进行了测试,似乎 'delete' 操作要慢约 30 倍:

var iterationsTotal = 10000000;  // 10 million
var o;
var t1 = Date.now(),t2;
for (let i=0; i<iterationsTotal; i++) {
   o = {a:1,b:2,c:3,d:4,e:5};
   delete o.a; delete o.b; delete o.c; delete o.d; delete o.e;
}
console.log ((t2=Date.now())-t1);  // 6135
for (let i=0; i<iterationsTotal; i++) {
   o = {a:1,b:2,c:3,d:4,e:5};
   o.a = o.b = o.c = o.d = o.e = undefined;
}
console.log (Date.now()-t2);  // 205

注意,我故意在一个循环周期内执行了多个"删除"操作,以最小化其他操作引起的影响。


13

Object.assign() & Object.keys() & Array.map()

const obj = {
    "Filters":[
        {
            "FilterType":"between",
            "Field":"BasicInformationRow.A0",
            "MaxValue":"2017-10-01",
            "MinValue":"2017-09-01",
            "Value":"Filters value"
        }
    ]
};

let new_obj1 = Object.assign({}, obj.Filters[0]);
let new_obj2 = Object.assign({}, obj.Filters[0]);

/*

// old version

let shaped_obj1 = Object.keys(new_obj1).map(
    (key, index) => {
        switch (key) {
            case "MaxValue":
                delete new_obj1["MaxValue"];
                break;
            case "MinValue":
                delete new_obj1["MinValue"];
                break;
        }
        return new_obj1;
    }
)[0];


let shaped_obj2 = Object.keys(new_obj2).map(
    (key, index) => {
        if(key === "Value"){
            delete new_obj2["Value"];
        }
        return new_obj2;
    }
)[0];


*/


// new version!

let shaped_obj1 = Object.keys(new_obj1).forEach(
    (key, index) => {
        switch (key) {
            case "MaxValue":
                delete new_obj1["MaxValue"];
                break;
            case "MinValue":
                delete new_obj1["MinValue"];
                break;
            default:
                break;
        }
    }
);

let shaped_obj2 = Object.keys(new_obj2).forEach(
    (key, index) => {
        if(key === "Value"){
            delete new_obj2["Value"];
        }
    }
);


12

JavaScript中的属性删除

本页面提供了许多不同的选项,不是因为大多数选项都是错误的或答案重复,而是因为适当的技术取决于您所处的情况和您和/或您的团队试图实现的任务目标。要明确回答您的问题,需要知道以下几点:

  1. 您正在针对的ECMAScript版本
  2. 您想要在哪些对象类型上删除属性以及您需要能够省略哪些类型的属性名称(仅字符串?符号?从任意对象映射的弱引用?这些都是JavaScript中多年来已经存在的属性指针类型)
  3. 您和您的团队使用的编程理念/模式。您是否支持函数式方法并且在您的团队中变异被禁止,还是采用野生西部的变异面向对象技术?
  4. 您是否希望在纯JavaScript中实现此目标,还是愿意并能够使用第三方库?

一旦回答了这四个问题,就基本上有四种JavaScript“属性删除”类别可供选择以满足您的目标。它们是:

变异对象属性删除,不安全

此类别适用于在您想要保留/继续使用原始引用并且在代码中不使用无状态函数式原则时,对对象字面量或对象实例进行操作。此类别中的一个示例语法:

'use strict'
const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
delete iLikeMutatingStuffDontI[Symbol.for('amICool')] // true
Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
delete iLikeMutatingStuffDontI['amICool'] // throws

这个类别是最古老、最直接和得到广泛支持的属性移除类别。除了 JavaScript 的第一个版本之外,它支持 Symbol 和数组索引,而不仅仅是字符串,并且在每个 JavaScript 版本中都可以工作。但是,它是可变的,违反了某些编程原则,并具有性能影响。当在strict模式下的不可配置属性上使用时,它还可能导致未捕获的异常。
基于 Rest 的字符串属性省略是用于在新的 ECMAScript 版本中操作普通对象或数组实例的类别,当需要非可变方法时,并且您不需要考虑 Symbol 键时使用。
const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
const { name, ...coolio } = foo // coolio doesn't have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(

可变对象属性删除,安全

此类别适用于在操作对象字面量或对象实例时,您想保留/继续使用原始引用,同时又要防止在不可配置属性上抛出异常的情况:

'use strict'
const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
Reflect.deleteProperty(iLikeMutatingStuffDontI, Symbol.for('amICool')) // true
Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
Reflect.deleteProperty(iLikeMutatingStuffDontI, 'amICool') // false

此外,虽然原地改变对象不是无状态的,但您可以利用 Reflect.deleteProperty 的函数式特性进行部分应用和其他函数式技术,这些技术在使用 delete 语句时是不可能的。
基于语法的字符串属性省略是针对较新的 ECMAScript 版本中的普通对象或数组实例进行操作的,当需要非变异方法且不需要考虑符号键时使用。
const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
const { name, ...coolio } = foo // coolio doesn't have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(

基于库的属性省略

这种分类通常允许更大的功能灵活性,包括考虑符号并在一个语句中省略超过一个属性:

const o = require("lodash.omit")
const foo = { [Symbol.for('a')]: 'abc', b: 'b', c: 'c' }
const bar = o(foo, 'a') // "'a' undefined"
const baz = o(foo, [ Symbol.for('a'), 'b' ]) // Symbol supported, more than one prop at a time, "Symbol.for('a') undefined"

12

这是一种使用 ES6 的简单删除条目的方法:

let myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};

const removeItem = 'regex';

const { [removeItem]: remove, ...rest } = myObject;

console.log(remove); // "^http://.*"
console.log(rest); // Object { ircEvent: "PRIVMSG", method: "newURI" }


11

您可以使用以下类似的筛选器

var myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI",
    "regex": "^http://.*"
};

// Way 1

let filter1 = {}
  Object.keys({...myObject}).filter(d => {
  if(d !== 'regex'){
    filter1[d] = myObject[d];
  }
})

console.log(filter1)

// Way 2

let filter2 = Object.fromEntries(Object.entries({...myObject}).filter(d =>
d[0] !== 'regex'
))

console.log(filter2)


但是,filter() 方法创建一个数组,其中包含通过测试的所有数组元素,因此 filter 的唯一目的是减少并创建一个新数组。 - ANIK ISLAM SHOJIB
是的,它确实可以这样做,但只有在将过滤器的返回值重新分配给原始变量或另一个变量时才有用。而且,它只在传递给它作为参数的函数中给出返回值时才有效,但这里没有执行这些操作,因此它的唯一目的是迭代数组元素,这正是forEach的作用。 - B''H Bi'ezras -- Boruch Hashem
2
你可以使用以下代码代替:let filter = Object.fromEntries(Object.entries(myObject).filter(d => d !== 'regex')); - B''H Bi'ezras -- Boruch Hashem

11
@johnstock,我们还可以使用JavaScript的原型概念将方法添加到对象中,以删除在调用对象中可用的任何传递的键。感谢上述答案。

var myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};

// 1st and direct way 
delete myObject.regex; // delete myObject["regex"]
console.log(myObject); // { ircEvent: 'PRIVMSG', method: 'newURI' }

// 2 way -  by using the concept of JavaScript's prototyping concept
Object.prototype.removeFromObjectByKey = function(key) {
  // If key exists, remove it and return true
  if (this[key] !== undefined) {
    delete this[key]
    return true;
  }
  // Else return false
  return false;
}

var isRemoved = myObject.removeFromObjectByKey('method')
console.log(myObject) // { ircEvent: 'PRIVMSG' }

// More examples
var obj = {
  a: 45,
  b: 56,
  c: 67
}
console.log(obj) // { a: 45, b: 56, c: 67 }

// Remove key 'a' from obj
isRemoved = obj.removeFromObjectByKey('a')
console.log(isRemoved); //true
console.log(obj); // { b: 56, c: 67 }

// Remove key 'd' from obj which doesn't exist
var isRemoved = obj.removeFromObjectByKey('d')
console.log(isRemoved); // false
console.log(obj); // { b: 56, c: 67 }


10

我使用了Lodash "unset"来实现对嵌套对象的操作,只需要编写一小段逻辑代码即可获取omit方法所需的属性键路径。

  1. 返回属性路径数组的方法

var a = {"bool":{"must":[{"range":{"price_index.final_price":{"gt":"450", "lt":"500"}}}, {"bool":{"should":[{"term":{"color_value.keyword":"Black"}}]}}]}};

function getPathOfKey(object,key,currentPath, t){
    var currentPath = currentPath || [];

    for(var i in object){
        if(i == key){
            t = currentPath;
        }
        else if(typeof object[i] == "object"){
            currentPath.push(i)
            return getPathOfKey(object[i], key,currentPath)
        }
    }
    t.push(key);
    return t;
}
document.getElementById("output").innerHTML =JSON.stringify(getPathOfKey(a,"price_index.final_price"))
<div id="output">

</div>

  1. 然后只需使用Lodash unset方法从对象中删除属性。

var unset = require('lodash.unset');
unset(a, getPathOfKey(a, "price_index.final_price"));


5

直接方式

2023年开始,您只需一行代码即可完成:

delete myObject.regex;

或者

delete myObject["regex"];

例如,如果您有一个名为obj的对象,并且该对象具有一个名为key-one的属性,则无法使用obj.key-one访问该属性,因此可以使用obj["key-one"]来访问。

5

如果您不想修改原始对象。

在不改变对象的情况下删除属性

如果可变性是一个问题,您可以通过复制旧对象的所有属性(除了您要删除的属性)来创建一个全新的对象。

let myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};

let prop = 'regex';
const updatedObject = Object.keys(myObject).reduce((object, key) => {
  if (key !== prop) {
    object[key] = myObject[key]
  }
  return object
}, {})

console.log(updatedObject);


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