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

How do I remove a property from a JavaScript object?

提问人:johnstok 提问时间:10/16/2008 最后编辑:SuperStormerjohnstok 更新时间:10/31/2023 访问量:3144575

问:

给定一个对象:

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

如何删除属性以结束以下内容?regexmyObject

let myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI"
};
JavaScript 对象 属性

评论


答:

9802赞 nickf 10/16/2008 #1

要从对象中删除属性(改变对象),可以像这样操作:

delete myObject.regex;
// or,
delete myObject['regex'];
// or,
var prop = "regex";
delete myObject[prop];

演示

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

console.log(myObject);

对于任何有兴趣阅读更多相关信息的人,Stack Overflow 用户 kangax 在他们的博客上写了一篇关于该声明的非常深入的博客文章,了解删除。强烈推荐。delete

如果你想要一个新对象,除了一些之外,所有键都是原始的,你可以使用解构

演示

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

// assign the key regex to the variable _ indicating it will be unused
const {regex: _, ...newObj} = myObject;

console.log(newObj);   // has no 'regex' key
console.log(myObject); // remains unchanged

评论

22赞 Loolooii 6/11/2021
这是一个很好的方法,但只有在你实际要使用 时才好,否则 eslint 会抱怨一个未使用的变量。regex
3赞 PartyLich 7/28/2021
@Loolooii,您可以重命名解构赋值中的变量,以满足您的规则。容易解决的问题。argsIgnorePatternno-unused-vars
4赞 ankush981 8/25/2021
我在这种方法中遇到的问题是,如果破坏是在有条件的范围内,它会使 ESlint 变得疯狂。
3赞 Lea de Groot 12/4/2021
文章不见了 - 当好的内容消失时,我们很伤心,很高兴我们有回溯机器:web.archive.org/web/20210224201033/http://perfectionkills.com/... :)
2赞 kca 12/6/2021
了解删除文章:我发现 URL perfectionkills.com/understanding-delete 有效(没有最后一个斜杠)
318赞 redsquare 10/16/2008 #2

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

console.log(myObject.regex); // logs: undefined

这在Firefox和Internet Explorer中有效,我认为它适用于所有其他浏览器。

298赞 Braden Best 9/18/2012 #3

运算符用于从对象中删除属性。delete

const obj = { foo: "bar" };

delete obj.foo;
obj.hasOwnProperty("foo"); // false

请注意,对于数组,这与删除元素不同。要从数组中删除元素,请使用 或 。例如:Array#spliceArray#pop

arr;             // [0, 1, 2, 3, 4]
arr.splice(3,1); // 3
arr;             // [0, 1, 2, 4]

严格来说,在 JavaScript 中真正删除任何内容是不可能的。运算符既不删除对象,也不释放内存。相反,它将其操作数设置为父对象并对其进行操作,以便成员消失。deleteundefined

let parent = {
    member: { str: "Hello" }
};
let secondref = parent.member;

delete parent.member;
parent.member;        // undefined
secondref;            // { str: "Hello" }

不会删除该对象。只有引用是。仅释放内存 当删除对对象的所有引用时,由垃圾回收器提供。

另一个重要的警告是,操作员不会为您重新组织结构,这会产生似乎违反直觉的结果。例如,删除数组索引会在其中留下一个“洞”。delete

let array = [0, 1, 2, 3]; // [0, 1, 2, 3]
delete array[2];          // [0, 1, empty, 3]

这是因为数组对象。因此,索引与键相同。

let fauxarray = {0: 1, 1: 2, length: 2};
fauxarray.__proto__ = [].__proto__;
fauxarray.push(3);
fauxarray;                // [1, 2, 3]
Array.isArray(fauxarray); // false
Array.isArray([1, 2, 3]); // true

JavaScript 中不同的内置函数以不同的方式处理带有孔洞的数组。

  • for..in语句将完全跳过空索引。

  • 朴素循环将产生索引处的值。forundefined

  • 使用的任何方法都将返回索引处的值。Symbol.iteratorundefined

  • forEach,并且只会跳过缺少的索引,但不会将其删除mapreduce

例:

let array = [1, 2, 3]; // [1,2,3]
delete array[1];       // [1, empty, 3]
array.map(x => 0);     // [0, empty, 0]

因此,运算符不应用于从数组中删除元素的常见用例。数组具有用于删除元素和重新分配内存的专用方法:和 。deleteArray#splice()Array#pop

数组#splice(start[, deleteCount[, item1[, item2[, ...]]]])

Array#splice改变数组,并返回任何已删除的索引。 元素从索引中删除,并从索引插入到数组中。如果省略,则将 startIndex 中的元素删除到数组的末尾。deleteCountstartitem1, item2... itemNstartdeleteCount

let a = [0,1,2,3,4]
a.splice(2,2) // returns the removed elements [2,3]
// ...and `a` is now [0,1,4]

还有一个名称相似但不同的函数: 。Array.prototypeArray#slice

数组#slice([begin[, end]])

Array#slice是非破坏性的,并返回一个新数组,其中包含从 到 的指示索引。如果未指定,则默认为数组的末尾。如果为正数,则指定要停止的从零开始的非包容性索引。如果为负数,则通过从数组末尾开始倒计时来指定要停止的索引(例如,-1 将省略最终索引)。如果 ,则结果为空数组。startendendendendend <= start

let a = [0,1,2,3,4]
let slices = [
    a.slice(0,2),
    a.slice(2,2),
    a.slice(2,3),
    a.slice(2,5) ]

//   a           [0,1,2,3,4]
//   slices[0]   [0 1]- - -   
//   slices[1]    - - - - -
//   slices[2]    - -[3]- -
//   slices[3]    - -[2 4 5]

数组#pop

Array#pop从数组中删除最后一个元素,并返回该元素。此操作将更改数组的长度。相反的操作是push

数组#shift

Array#shift与 类似,只是它删除了第一个元素。相反的操作是 。popunshift

80赞 Mehran Hatami 2/12/2014 #4

您在问题标题中使用的术语“从 JavaScript 对象中删除属性”可以用一些不同的方式解释。一种是将其从整个内存和对象键列表中删除,另一种只是将其从对象中删除。正如在其他一些答案中提到的,关键字是主要部分。假设你有这样的对象:delete

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

如果您这样做:

console.log(Object.keys(myJSONObject));

结果将是:

["ircEvent", "method", "regex"]

您可以从对象键中删除该特定键,例如:

delete myJSONObject["regex"];

那么你的对象键是:Object.keys(myJSONObject)

["ircEvent", "method"]

但关键是,如果您关心内存,并且希望从内存中删除整个对象,建议在删除密钥之前将其设置为 null:

myJSONObject["regex"] = null;
delete myJSONObject["regex"];

这里另一个重要的一点是要小心你对同一对象的其他引用。例如,如果您创建一个变量,例如:

var regex = myJSONObject["regex"];

或者将其添加为指向另一个对象的新指针,例如:

var myOtherObject = {};
myOtherObject["regex"] = myJSONObject["regex"];

然后,即使您将其从对象中删除,该特定对象也不会从内存中删除,因为该变量仍然具有其值。那么我们怎样才能确定从内存中删除对象呢?myJSONObjectregexmyOtherObject["regex"]

答案是删除代码中的所有引用,指向该对象并且不使用 var 语句创建对该对象的新引用。关于语句的最后一点,是我们通常面临的最关键的问题之一,因为使用语句会阻止创建的对象被删除。varvar

这意味着在这种情况下,您将无法删除该对象,因为您已通过语句创建了变量,并且如果您这样做:regexvar

delete regex; //False

结果将是 ,这意味着您的 delete 语句尚未按预期执行。但是,如果您之前没有创建该变量,并且您仅将其作为最后一个现有引用,则可以通过删除它来完成此操作,例如:falsemyOtherObject["regex"]

myOtherObject["regex"] = null;
delete myOtherObject["regex"];

换言之,只要代码中没有指向该对象的引用,就有资格终止该对象。


更新:

感谢@AgentME:

在删除属性之前将属性设置为 null 无法完成 任何东西(除非对象已被 Object.seal 和 删除失败。除非您特别指出,否则通常不会出现这种情况 尝试)。

要获取更多信息:Object.seal()Object.seal

评论

0赞 Ted Brownlow 11/15/2022
“一旦代码中没有指向该对象的引用,JavaScript 对象就会被杀死。”这难道不应该说“有资格被杀死”吗,因为垃圾收集者可以拖延杀死对象?
1116赞 Dan 2/13/2014 #5

JavaScript 中的对象可以被认为是键和值之间的映射。运算符用于一次删除一个键(通常称为对象属性)。delete

var obj = {
  myProperty: 1    
}
console.log(obj.hasOwnProperty('myProperty')) // true
delete obj.myProperty
console.log(obj.hasOwnProperty('myProperty')) // false

运算符不直接释放内存,它与简单地将 或 的值分配给属性不同,因为属性本身已从对象中删除。请注意,如果已删除属性的值是引用类型(对象),并且程序的另一部分仍包含对该对象的引用,则在对该对象的所有引用消失之前,该对象当然不会被垃圾回收。deletenullundefined

delete仅适用于其描述符将其标记为可配置的属性。

126赞 Thaddeus Albers 5/25/2014 #6

另一种替代方法是使用 Underscore.js 库。

请注意,两者都返回对象的副本,并且不直接修改原始对象。将结果分配给原始对象应该可以解决问题(未显示)。_.pick()_.omit()

参考:link _.pick(object, *keys)

返回对象的副本,经过筛选后仅具有 列入白名单的密钥(或有效密钥数组)。

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

_.pick(myJSONObject, "ircEvent", "method");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

参考:link _.omit(object, *keys)

返回对象的副本,经过过滤以省略 列入黑名单的密钥(或密钥数组)。

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

_.omit(myJSONObject, "regex");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};

对于数组,可以以类似的方式使用。_.filter()_.reject()

评论

0赞 agm1984 10/22/2022
_.omit(obj, 'key')很酷,但我需要省略一个嵌套键,所以我使用了Object.assign(obj, { filters: { sort_by: '' }})
29赞 Willem 9/15/2014 #7

这里有很多很好的答案,但我只想指出,当使用 delete 删除 JavaScript 中的属性时,通常明智的做法是首先检查该属性是否存在以防止错误。

例如

var obj = {"property":"value", "property2":"value"};

if (obj && obj.hasOwnProperty("property2")) {
  delete obj.property2;
} else {
  //error handling
}

由于 JavaScript 的动态特性,通常情况下您根本不知道该属性是否存在。在 && 之前检查 obj 是否存在还可以确保您不会因在未定义的对象上调用 hasOwnProperty() 函数而引发错误。

很抱歉,如果这没有添加到您的特定用例中,但我相信这是一个很好的设计,可以在管理对象及其属性时进行调整。

26赞 talsibony 12/1/2014 #8

这篇文章很旧,我发现它很有帮助,所以我决定分享我写的 unset 函数,以防其他人看到这篇文章并思考为什么它不像 PHP unset 函数那么简单。

编写此新函数的原因是为了在此hash_map中保留所有其他变量的索引。请看以下示例,看看从hash_map中删除值后,“test2”的索引如何没有更改。unset

function unset(unsetKey, unsetArr, resort) {
  var tempArr = unsetArr;
  var unsetArr = {};
  delete tempArr[unsetKey];
  if (resort) {
    j = -1;
  }
  for (i in tempArr) {
    if (typeof(tempArr[i]) !== 'undefined') {
      if (resort) {
        j++;
      } else {
        j = i;
      }
      unsetArr[j] = tempArr[i];
    }
  }
  return unsetArr;
}

var unsetArr = ['test', 'deletedString', 'test2'];

console.log(unset('1', unsetArr, true)); // output Object {0: "test", 1: "test2"}
console.log(unset('1', unsetArr, false)); // output Object {0: "test", 2: "test2"}

56赞 madox2 1/11/2016 #9

ECMAScript 2015(或 ES6)带有内置的 Reflect 对象。可以通过调用 Reflect.deleteProperty() 函数来删除对象属性,并将目标对象和属性键作为参数:

Reflect.deleteProperty(myJSONObject, 'regex');

这相当于:

delete myJSONObject['regex'];

但是,如果对象的属性不可配置,则无法使用 deleteProperty 函数或 delete 运算符将其删除:

let obj = Object.freeze({ prop: "value" });
let success = Reflect.deleteProperty(obj, "prop");
console.log(success); // false
console.log(obj.prop); // value

Object.freeze() 使对象的所有属性都不可配置(除了其他属性)。 函数(以及 delete 运算符)在尝试删除其任何属性时返回。如果 property 是可配置的,则返回 ,即使 property 不存在。deletePropertyfalsetrue

和之间的区别在于使用严格模式时:deletedeleteProperty

"use strict";

let obj = Object.freeze({ prop: "value" });
Reflect.deleteProperty(obj, "prop"); // false
delete obj["prop"];
// TypeError: property "prop" is non-configurable and can't be deleted
42赞 emil 1/22/2016 #10

我个人使用 Underscore.jsLodash 进行对象和数组操作:

myObject = _.omit(myObject, 'regex');
53赞 John Slegers 2/22/2016 #11

假设您有一个如下所示的对象:

var Hogwarts = {
    staff : [
        'Argus Filch',
        'Filius Flitwick',
        'Gilderoy Lockhart',
        'Minerva McGonagall',
        'Poppy Pomfrey',
        ...
    ],
    students : [
        'Hannah Abbott',
        'Katie Bell',
        'Susan Bones',
        'Terry Boot',
        'Lavender Brown',
        ...
    ]
};

删除对象属性

如果要使用整个数组,正确的方法是这样做:staff

delete Hogwarts.staff;

或者,您也可以这样做:

delete Hogwarts['staff'];

同样,删除整个 students 数组将通过调用 或 来完成。delete Hogwarts.students;delete Hogwarts['students'];

删除数组索引

现在,如果要删除单个教职员工或学生,则过程略有不同,因为这两个属性本身都是数组。

如果您知道员工的索引,您可以简单地这样做:

Hogwarts.staff.splice(3, 1);

如果您不知道索引,您还必须进行索引搜索:

Hogwarts.staff.splice(Hogwarts.staff.indexOf('Minerva McGonnagall') - 1, 1);

注意

虽然从技术上讲,您可以将其用于数组,但使用它会导致在稍后调用时获得不正确的结果。换句话说,将删除元素,但不会更新属性的值。使用也会弄乱你的索引。deleteHogwarts.staff.lengthdeletelengthdelete

因此,从对象中删除值时,请始终首先考虑是处理对象属性还是处理数组值,并据此选择适当的策略。

如果你想尝试这个,你可以用这个小提琴作为起点。

14赞 ayushgp 6/23/2016 #12

如果要删除深嵌在对象中的属性,则可以使用以下递归函数,并将属性的路径作为第二个参数:

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: {}}}
19赞 Mohammed Safeer 7/6/2016 #13

请尝试以下方法。将属性值指定给 。然后对象和 .Objectundefinedstringifyparse

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

myObject.regex = undefined;
myObject = JSON.parse(JSON.stringify(myObject));

console.log(myObject);

404赞 Koen. 11/9/2016 #14

古老的问题,现代的答案。使用 ECMAScript 6 的一项功能对象解构,它非常简单:

const { a, ...rest } = { a: 1, b: 2, c: 3 };

或者使用问题示例:

const myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
const { regex, ...newObject } = myObject;
console.log(newObject);

您可以在 Babel 试用编辑器中看到它的实际效果。


编辑:

要重新分配给同一变量,请使用 :let

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

评论

3赞 Ceres 9/15/2021
如果属性名称发生变化,即如果我在变量中拥有它,我该如何解构?
1赞 Koen. 9/16/2021
请参阅下面的答案;stackoverflow.com/a/52301527
4赞 GreenAsJade 1/1/2022
为什么这比 ?“现代”并不是一个真正的理由......delete()
1赞 Koen. 1/2/2022
我不是说是,我是在证明另一种选择。虽然曾经有一些性能影响,但我认为本页的其他答案中已经描述了这些影响。delete
19赞 Silidrone 7/14/2022
@GreenAsJade 您更喜欢这样做的一个重要原因是因为它不会改变原始对象。对于像 React 这样的框架非常重要。我实际上是在寻找一个不会改变原始对象的答案。
20赞 Amio.io 11/28/2016 #15

使用 ramda#dissoc,您将获得一个没有属性的新对象:regex

const newObject = R.dissoc('regex', myObject);
// newObject !== myObject

您还可以使用其他功能来达到相同的效果 - 省略、选择......

34赞 kind user 3/26/2017 #16

另一种解决方案,使用 Array#reduce

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

myObject = Object.keys(myObject).reduce(function(obj, key) {
  if (key != "regex") {           //key you want to remove
    obj[key] = myObject[key];
  }
  return obj;
}, {});

console.log(myObject);

但是,它会改变原始对象。如果你想创建一个没有指定键的新对象,只需将reduce函数分配给一个新变量,例如:

(ES6 系列)

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

const myNewObject = Object.keys(myObject).reduce((obj, key) => {
  key !== 'regex' ? obj[key] = myObject[key] : null;
  return obj;
}, {});

console.log(myNewObject);

39赞 Alireza 4/8/2017 #17

使用 delete 方法是最好的方法,根据 MDN 描述,delete 运算符从对象中删除属性。所以你可以简单地写:

delete myObject.regex;
// OR
delete myObject['regex'];

delete 运算符从对象中删除给定属性。上 删除成功,将返回 true,否则返回 false。 但是,请务必考虑以下情况:

  • 如果尝试删除的属性不存在,请删除 不会有任何效果,并将返回 true
  • 如果对象的原型上存在同名的属性 chain,那么,在删除后,对象将使用 原型链(换句话说,删除只对自己有影响 属性)。
  • 任何使用 var 声明的属性都不能从全局范围中删除 或从函数的作用域。
  • 因此,delete 无法删除全局范围内的任何函数(无论这是函数定义的一部分还是函数(表达式)的一部分)。
  • 作为对象一部分的函数(
    全局作用域除外)可以通过 delete 删除。
  • 使用 let 或 const 声明的任何属性都不能从定义它们的作用域中删除。无法删除不可配置的属性。这包括内置对象(如 Math、Array、Object)的属性,以及使用 Object.defineProperty() 等方法创建为不可配置的属性。

以下代码片段提供了另一个简单示例:

var Employee = {
  age: 28,
  name: 'Alireza',
  designation: 'developer'
}

console.log(delete Employee.name);   // returns true
console.log(delete Employee.age);    // returns true

// When trying to delete a property that does 
// not exist, true is returned 
console.log(delete Employee.salary); // returns true

有关和查看更多示例的更多信息,请访问以下链接:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete

13赞 Chong Lip Phang 7/26/2017 #18

Dan 关于“删除”的断言非常缓慢,他发布的基准测试也受到质疑。所以我自己在Chrome 59中进行了测试。“删除”似乎慢了大约 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

请注意,我特意在一个循环周期中执行了多个“删除”操作,以最大程度地减少其他操作造成的影响。

16赞 johndavedecano 9/14/2017 #19

使用 Lodash

import omit from 'lodash/omit';

const prevObject = {test: false, test2: true};
// Removes test2 key from previous object
const nextObject = omit(prevObject, 'test2');

使用 Ramda

R.omit(['a', 'd'], {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, c: 3}

评论

0赞 ー PupSoZeyDe ー 11/13/2021
奇怪。你的代码对我不起作用,但确实有效。_.omit(['a', 'd'], {a: 1, b: 2, c: 3, d: 4});_.omit({a: 1, b: 2, c: 3, d: 4}, ['a', 'd']);
13赞 user8629798 9/19/2017 #20

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"];
        }
    }
);

10赞 BEJGAM SHIVA PRASAD 9/29/2017 #21

我也使用 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"));

12赞 james_womack 12/14/2017 #22

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

基于 rest 的字符串属性省略

此类别用于在需要非可变方法且不需要考虑符号键时,在较新的 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 :(

可变对象属性删除,安全

此类别用于在希望保留/继续使用原始引用同时防止在不可配置的属性上引发异常时对对象文本或对象实例进行操作:

'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

此外,虽然就地更改对象不是无状态的,但您可以使用 to do 的函数性质执行部分应用程序和其他语句无法实现的功能技术。Reflect.deletePropertydelete

基于语法的字符串属性省略

此类别用于在需要非可变方法且不需要考虑符号键时,在较新的 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"
11赞 hygull 5/25/2018 #23

@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 }

268赞 Lior Elrom 9/13/2018 #24

Spread 语法 (ES6)

为了完成 Koen 的回答,如果你想使用扩展语法删除动态变量,你可以这样做:

const key = 'a';

const { [key]: foo, ...rest } = { a: 1, b: 2, c: 3 };

console.log(foo);  // 1
console.log(rest); // { b: 2, c: 3 }

* foo 将是一个值为 a(即 1)的新变量。

扩展答案 😇

有几种常用方法可以从对象中删除属性。
每个都有自己的优点和缺点(查看此性能比较):

删除运算符

它可读且简短,但是,如果您要对大量对象进行操作,它可能不是最佳选择,因为它的性能没有得到优化。

delete obj[key];

调动

它比 快两倍以上,但是该属性不会被删除,并且可以迭代。delete

obj[key] = null;
obj[key] = false;
obj[key] = undefined;

点差运算符

这个运算符允许我们返回一个全新的对象,不包括任何属性,而不改变现有对象。缺点是它的性能在上述属性中较差,当您需要一次删除许多属性时,不建议使用。ES6

{ [key]: val, ...rest } = obj;

评论

5赞 RobG 10/30/2020
这不是删除属性,而是创建浅拷贝,而不是跨指定的键和值进行复制。这是一个非常大的区别。
0赞 jdmneon 2/15/2023
这是一个很好的答案,但最后一个例子是荒谬主义。有人问如何摆脱他们办公桌上的空瓶可口可乐,我的回答是订购一张全新的桌子,然后将旧桌子上的每一件物品都移到新桌子上,除了可口可乐的空瓶子。你正在创造一套全新的东西,以便摆脱这些东西的子集。
123赞 YairTawil 5/8/2019 #25

要克隆没有属性的对象,请执行以下操作:

例如:

let object = { a: 1, b: 2, c: 3 };

我们需要删除.a

  1. 使用显式 prop 键

    const { a, ...rest } = object;
    object = rest;
    
  2. 使用可变道具键

    const propKey = 'a';
    const { [propKey]: propValue, ...rest } = object;
    object = rest;
    
  3. 一个很酷的箭头功能😎:

    const removeProperty = (propKey, { [propKey]: propValue, ...rest }) => rest;
    
    object = removeProperty('a', object);
    
  4. 对于多个属性

    const removeProperties = (object, ...keys) => (keys.length ? removeProperties(removeProperty(keys.pop(), object), ...keys) : object);
    

用法

object = removeProperties(object, 'a', 'b') // result => { c: 3 }

const propsToRemove = ['a', 'b']
object = removeProperties(object, ...propsToRemove) // result => { c: 3 }

评论

1赞 A-S 2/9/2023
若要避免以下警告:,请添加如下所示的类型:Parameter 'propKey' implicitly has an 'any' type. ts(7006)propKeyconst removeProperty = (propKey: string | number, { [propKey]: propValue, ...rest }) => rest
11赞 ANIK ISLAM SHOJIB 9/18/2019 #26

您可以使用如下所示的过滤器

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)

评论

0赞 ANIK ISLAM SHOJIB 9/16/2020
但是 filter() 方法创建一个数组,其中包含所有通过测试的数组元素,因此过滤器的唯一目的是减少和创建一个新数组
0赞 B''H Bi'ezras -- Boruch Hashem 9/16/2020
是的,它确实如此,但这仅在您通过将过滤器的返回值重新签名给原始变量或其他变量来使用它时才有用,并且它仅在函数中作为参数传递给它的函数中给定返回值时才有效,但如果这些事情在这里完成,则没有,所以它的唯一目的是迭代数组元素, 这就是forEach的用途
2赞 B''H Bi'ezras -- Boruch Hashem 9/16/2020
你可以这样做let filter = Object.fromEntries(Object.entries(myObject).filter(d => d !== 'regex' ))
5赞 B''H Bi'ezras -- Boruch Hashem 9/16/2020 #27

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


obj = Object.fromEntries(
    Object.entries(myObject).filter(function (m){
        return m[0] != "regex"/*or whatever key to delete*/
    }
))

console.log(obj)

您也可以使用 像对待数组一样对待对象,并使用拼接来删除元素,就像在普通数组中一样,或者像处理数组一样简单地过滤对象,然后将重建的对象分配回原始变量a2dObject.entries

5赞 akhtarvahid 11/17/2020 #28

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

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

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

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

12赞 John Doe 1/18/2021 #29

以下是轻松删除条目的 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" }

2赞 Rashid Iqbal 2/22/2021 #30

删除对象的两种方法

  1. 用于 ...

     function deleteUser(key) {
    
         const newUsers = {};
         for (const uid in users) {
             if (uid !== key) {
                 newUsers[uid] = users[uid];
             }
    
         return newUsers
     }
    

delete users[key]

评论

1赞 mickmackusa 6/7/2021
因此,建议删除一个属性,应将整个对象复制到没有目标属性的新对象中?!?
1赞 Peter Mortensen 6/24/2021
这是有效的代码吗?似乎缺少 A。您可以编辑您的答案 - 但没有“编辑:”、“更新:”或类似内容 - 答案应该看起来像今天写的一样。}
35赞 Ran Turner 12/19/2021 #31

有几种方法可以从对象中删除属性:

1) 使用 dot 属性访问器删除(可变)

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

delete myObject.regex;
console.log(myObject);

2. 删除使用方括号属性访问器(可变)

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

delete myObject['regex'];
console.log(myObject);
// or
const name = 'ircEvent';
delete myObject[name];
console.log(myObject);

3) 通过使用对象解构和 rest 语法(不可变),可以在不更改原始对象的情况下删除

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

const { regex, ...myObjectRest} = myObject;
console.log(myObjectRest); 

2赞 Sahil Thummar 3/3/2022 #32

我们可以使用删除

  1. 使用 Delete Object.Property
  2. 使用 delete 对象['property']
  3. 使用 REST,删除多个属性

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

delete myObject.regex; // using delete object.property

// Or 

delete myObject['regex1']; // using delete object['property']

const { regex2, regex3, regex4, ...newMyObject } = myObject;

console.log(newMyObject);

1赞 Sana 4/30/2022 #33

您可以使用以下命令从对象中删除属性 删除属性[key]

1赞 rohithpoya 6/25/2022 #34

在 JavaScript 中,有两种常见的方法可以从对象中删除属性。

第一种可变方法是使用运算符。delete object.property

第二种方法是不可变的,因为它不修改原始对象,是调用对象解构和传播语法:const {property, ...rest} = object

1赞 Yusuf Ganiyu 9/1/2022 #35

简答

var obj = {
  data: 1,
  anotherData: 'sample'    
}
delete obj.data //this removes data from the obj

你只剩下

var obj = {
  anotherData: 'sample'    
}
3赞 Amarkant Kumar 12/27/2022 #36

我们可以通过使用 delete 运算符轻松删除对象的任何属性。

const object = {
  prop1: 10,
  prop2: 20,
  prop3: 30,
  "test prop": "This is test props"
}
console.log(object); // will print all 4 props

delete object.prop1;
delete object["test prop"];

console.log(object); // it will print only prop2 and prop3

查看文档:MDN

评论

0赞 Donald Duck 12/28/2022
虽然此代码可以回答问题,但提供有关此代码为何和/或如何回答问题的其他上下文可以提高其长期价值。
5赞 underflow 2/4/2023 #37

直道

截至 2023 年,您只需一行即可完成:

delete myObject.regex;

delete myObject["regex"];

(例如,如果你有一个对象,其属性名为 ,你不能做,所以这里来了)。objkey-oneobj.key-oneobj["key-one"]

1赞 Zia 4/18/2023 #38

我就是这样做的。

const obj = {
  name: 'John',
  age: 30,
  gender: 'male'
};

delete obj.age;

console.log(obj); // { name: 'John', gender: 'male' }