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


6138

说我创建一个对象,如下所示:

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

删除该属性regex以产生myObject如下所示的新属性的最佳方法是什么?

let myObject = {
    "ircEvent": "PRIVMSG",
    "method": "newURI"
};


@EscapeNetscape这是有关行为的问题,因此基准测试描绘了错误的画面。当然,delete这是最慢的选择,因为它是实际操作,而不是其他两个简单的任务。但是问题的症结在于,将属性分配给对象nullundefined实际上并未从对象中删除该属性,而是将该属性设置为等于特定的常数值。(以下答案给出了为什么会有如此显着差异的原因。)
Abion47

Answers:


8295

像这样:

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涉及其博客上的声明“ 了解删除”。强烈建议。


47
选中后,它还可以与“ delete myJSONObject ['regex'];”一起使用。请参阅:developer.mozilla.org/en/Core_JavaScript_1.5_Reference/…–
johnstok,

109
上面“理解删除”链接上的观察结果之一是,由于您不一定要删除变量,而只能删除对象属性,因此不能“通过引用”删除对象属性-var value = obj [ '支柱']; 删除值//不起作用
Dexygen

27
所以它实际上并没有删除它?它只是变得未定义,但是键仍然存在吗?我想念什么吗?
Doug Molineux

151
@Pete不,它确实将其删除。鉴于:var x = {a : 'A', b : 'B'};比较:delete x.a; typeof x.a; /* "undefined" */ x.hasOwnProperty('a'); /* false */x.b = undefined; typeof x.b; /* "undefined" */; x.hasOwnProperty('b'); /* true */
nickf

16
@ChristopherPfohl为我工作。就像我说的那样,它实际上是非常深入的,因此很难概括。上面答案中的基本回答几乎可以满足所有情况,博客涉及更多边缘情况以及这些情况存在的原因。
尼克

952

JavaScript中的对象可以视为键和值之间的映射。的delete操作者被用来去除这些键,更通常被称为对象属性,一次一个。

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

delete操作者不直接自由存储器,并且它简单地从分配的值不同nullundefined到的属性,在该属性本身从对象中删除。注意,如果已删除属性是引用类型(一个对象),而程序的另一部分仍保留对该对象的引用,那么在该对象的所有引用都包含之前,该对象当然不会被垃圾回收。不见了

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


43
分配给未定义的属性仍然是对象的属性,因此不会被GC删除,除非误读了您的最后一段。
Lance

8
我在这里碰到GC的主题是错误的。两种方法对GC的结果相同:它们删除链接到键的值。如果该值是对其他对象的最后引用,则该对象将被清除。
2014年

15
分配给未定义的属性仍然是对象的属性,因此 GC不会删除该属性GC不管理有关属性的任何内容。它收集并删除值。只要不再有任何引用值(对象,字符串等),GC便会将其从内存中删除。
meandre 2014年

8
顺便说一句,这是检查Javascript对象上是否存在属性的双重问题。使用in运算符可靠但缓慢。检查属性是否未定义 “不是正确的答案”,但这是一种更快的方法。检查
rdllopes,2014年

8
这个答案仍然有意义吗?jsperf目前下跌,但这个基准测试似乎表明,对速度差异只有25%,这是无处接近“慢〜100倍”这个答案。
Cerbrus '16

248

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

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

这适用于Firefox和Internet Explorer,我认为它适用于所有其他产品。


216

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

const obj = { foo: "bar" }
delete obj.foo
obj.hasOwnProperty("foo") // false

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

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

细节

deleteJavaScript中的JavaScript与C和C ++中的关键字具有不同的功能:它不直接释放内存。相反,其唯一目的是从对象中删除属性。

对于数组,删除与索引相对应的属性会创建一个稀疏数组(即,其中带有“洞”的数组)。大多数浏览器将这些缺少的数组索引表示为“空”。

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

请注意,delete不会重新定位array[3]array[2]

JavaScript中不同的内置函数对稀疏数组的处理方式不同。

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

  • 传统for循环将返回undefined索引处的值。

  • 任何使用方法Symbol.iterator都会返回undefined索引处的值。

  • forEachmap并且reduce只会跳过缺少的索引。

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

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

Array#splice更改数组,并返回所有删除的索引。deleteCount从index中删除元素start,并item1, item2... itemN从index中将其插入数组start。如果deleteCount省略,则将startIndex中的元素删除到数组的末尾。

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

Array#slice([[begin [,end]])

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

Array#pop

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


12
这种方法不会修改可能在其他地方仍然引用的原始对象。取决于使用方式,这可能是问题,也可能不是问题,但请牢记。
Tamas Czinege 2012年

19
@ B1KMusic这是从数组中删除元素的方法:拼接
wulftone 2013年

3
@wulftone nope,它拆分数组,不执行任何删除值的操作。我确实认为,从需要删除特定值的数组中删除的最佳方法是使用delete垃圾回收功能并对其进行清理。
Braden Best

5
splice在您的编辑中看不到,但remove应该是Array.prototype.remove = function(index) { this.splice(index, 1); };
Ry-

1
本文充满了公牛1。它没有解决问题!2.这是对语言的一种示例性滥用,并且抱怨“它不起作用!”。3.不要将Crockford的空数组索引为null的特殊错误归咎于JavaScript delete运算符。他不了解null的含义-他认为这是一个错误。错误是他自己的错误,是单独的错误-给定数组索引的已删除值中没有null。数组中没有“洞”-这是一个空索引。绝对合法和预期。
Bekim Bacaj

195

老问题,现代答案。使用对象分解(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);

6
也许是因为目标是从对象中删除一个属性,而不是创建一个没有该属性的新对象……尽管,您的解决方案是我的最爱,因为我更喜欢不可变的方式。
Vingt_centimes

8
问题表明“以新的 myObject 结尾”。
科恩

1
添加Underscore删除属性会乱丢您的项目:)regex您可以将其分配给任何其他变量,而不是将其分配给其他任何变量,例如_,在Go之类的语言中使用的是丢弃结果:const { regex: _, ...newObject } = myObject;
科恩

2
@PranayKumar我希望这种语法能起作用;const { [key], ...newObject } = myObject;但事实并非如此,因此我认为解构是不可能的。
科恩

2
对于freeze()'d和seal()'d对象,您不能只是delete一个属性。因此,这是一个极好的选择。尽管在大多数情况下,从冻结/密封的对象中删除属性可能都没有意义,考虑到整个重点是对数据结构做出某些保证,而这种模式会破坏这种保证。对于那些需要非破坏性地复制对象但没有某些属性的情况,这是完美的选择
Braden Best,

118

传播语法(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];


重新分配的
速度比快2倍以上delete,但是不会删除该属性,并且可以对其进行迭代。

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


Spread运算符
ES6运算符使我们可以返回一个全新的对象(不包括任何属性),而无需更改现有对象。不利的一面是,它的性能比上述更差,因此当您需要一次删除许多属性时,建议不要使用它。

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

2
我认为对象文字的扩展/其余语法仅包含在ES2018(ES9)中,而不包含在ES6中,即使一些JS引擎已经实现了它。
特里科特

2
@trincot它于2014年首次推出(github.com/tc39/proposal-object-rest-spread),它是ES6(ECMAScript 2015,又名ECMAScript 6th Edition)功能。但是,即使我错了,我也不认为这对答案的上下文有所影响。
Lior Elrom '18

2
该链接指向ES6,在该链接中确实为数组引入了扩展语法,但随后它继续为对象文字提供类似的建议。如果我没有记错的话,第二部分仅包含在ES9中。
特里科特

98

另一种选择是使用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()可以以类似的方式使用。


4
请记住,如果对象的键是数字,则可能需要_.omit(collection, key.toString())
Jordan Arseno 2014年

嗯...下划线比慢100倍,下划线比delete obj[prop]慢100倍obj[prop] = undefined
Jack Giffin '18

52

您在问题标题中使用的术语Remove a property from a JavaScript object可以用不同的方式解释。一种是将其整个内存和对象键列表删除,另一种只是将其从对象中删除。正如在其他一些答案中提到的那样,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"];

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

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

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

delete regex; //False

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

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

换句话说,只要您的代码中没有指向该对象的引用,JavaScript对象就会被杀死。


更新: 感谢@AgentME:

在删除属性之前将属性设置为null不会完成任何操作(除非该对象已被Object.seal密封并且删除失败。除非您特别尝试,否则通常情况并非如此)。

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


您错了-JavaScript中只有对象是通过引用传递的,因此,如果myJSONObject.regex的值是一个字符串,并将其分配给其他某个对象,则另一个对象将具有此值的副本。
米哈尔Perłakowski

您是对的,这是一句名言:“要注意您对同一对象的其他引用。”
Mehran Hatami

43

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()使对象的所有属性均不可配置(除其他因素外)。deleteProperty函数(以及delete运算符false在尝试删除其任何属性时返回。如果属性是可配置的,则返回true,即使property不存在,也会。

delete和之间的区别deleteProperty是使用严格模式时:

"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

1
@Gothdo有更多好处,尤其是当您需要执行一些功能性工作时。例如,你可以指定函数变量,作为参数传递和使用applycallbind功能...
madox2

41

假设您有一个看起来像这样的对象:

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'];

同样,要删除整个学生数组,可以通过调用delete Hogwarts.students;delete Hogwarts['students'];

删除数组索引

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

如果您知道工作人员的索引,则只需执行以下操作:

Hogwarts.staff.splice(3, 1);

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

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

注意

从技术上讲,您可以使用delete数组,但Hogwarts.staff.length稍后调用时,使用它会导致获得错误的结果。换句话说,delete将删除元素,但不会更新lengthproperty 的值。使用delete也会使您的索引混乱。

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

如果要尝试此操作,可以使用此Fiddle作为起点。


我认为您应该始终使用splice数组而不是delete
Joel Trauger

@JoelTrauger:这就是我的意思;-)
John Slegers

是。我的评论是,这delete甚至都不是问题。这splice就是OP寻找的东西。
Joel Trauger

1
@JoelTrauger:正如我试图解释的那样,delete应用于对象属性和splice数组元素。
John Slegers '16

接合真的很慢。尽管应该使用它而不是delete在数组上使用它,但最好不要创建以它为中心的代码。
杰克·吉芬

39

使用ES6:

(解构+传播运算符)

const myObject = {
    regex: "^http://.*",
    b: 2,
    c: 3
};
const { regex, ...noRegex } = myObject;
console.log(noRegex); // => { b: 2, c: 3 }

我不认为这是ES6的功能,而是仅包含在ES9中的功能。
特里科特

因此,实际上,您编写的不是ES6,而是ES9 ... ;-)
trincot

2
这不是从对象中删除属性,而是创建没有该属性的新对象。
Jordi Nebot



29

克隆没有属性的对象:

例如:

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

而且我们需要删除“ a”。

1.带有明确的道具键:

const { a, ...rest } = object;
object = rest;

2.带可变道具键:

const propKey = 'a';
const { [propKey]: propValue, ...rest } = object;
object = rest;

3.酷箭头功能😎:

const removePropery = (propKey, { [propKey]: propValue, ...rest }) => rest;

object = removePropery('a', object);

4.对于多个属性

const removeProperties = (object, ...keys) => Object.entries(object).reduce((prev, [key, value]) => ({...prev, ...(!keys.includes(key) && { [key]: value }) }), {})

用法

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

要么

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

1
圆滑的箭头功能!
JSilv19年

27

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

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

delete运算符从对象中删除给定的属性。成功删除后,它将返回true,否则将返回false。但是,重要的是要考虑以下情形:

  • 如果您要删除的属性不存在,则删除将没有任何效果,并且将返回true

  • 如果对象的原型链上存在相同名称的属性,则删除后,该对象将使用原型链中的属性(换句话说,删除仅会对自己的属性产生影响)。

  • 用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/zh-CN/docs/Web/JavaScript/Reference/Operators/delete


22

另一种解决方案,使用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);


21

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

编写此新unset函数的原因是将所有其他变量的索引保留在此hash_map中。查看下面的示例,看看从hash_map删除值后,“ test2”的索引如何保持不变。

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

20

这里有很多很好的答案,但我只是想提醒一下,在使用delete删除JavaScript中的属性时,通常最好先检查该属性是否存在以防止错误。

例如

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

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

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

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


2
即使bar不存在,删除foo.bar也可以工作,所以恕我直言,您的测试有点过多。
PhiLho 2015年

@PhiLho,取决于您在哪里运行JavaScript。我相信在Node.js中,这会导致服务器崩溃。
威廉(Willem)2015年

2
delete foo.bar;仅在foo为假或您处于严格模式下且foo是具有不可配置的bar属性的对象时,才会引发异常。
Macil

我不记得确切的问题了,但是我认为当foo本身不存在并且您尝试删除它的属性时,可能会出现问题。
威廉

是的,您必须测试foo是否存在,否则foo.bar将引发异常,但是您无需在删除bar之前检查bar的存在。那是我评论的“太多”部分。:-)
PhiLho 2015年

16

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

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

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


15

请尝试以下方法。将Object属性值分配给undefined。然后stringify是对象和parse

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

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

console.log(myObject);


1
另外JSON.parse(JSON.stringify({ ...myObject, regex: undefined }))
noisypixy

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: {}}}

这个函数就像一个符咒,但是为什么我们需要返回true和false?我的代码版本: codepen.io/anon/pen/rwbppY。我的版本在任何情况下都会失败吗?
通常为'17

@ witty2017它不会失败。我使用该函数的地方还需要检查该属性是否已经存在。如果该属性不存在,它将返回false。如果找到该属性并将其删除,它将返回true。
ayushgp

8

您可以简单地使用delete关键字删除对象的任何属性。

例如:

var obj = {key1:"val1",key2:"val2",key3:"val3"}

要删除任何属性,请说key1,使用如下delete关键字:

delete obj.key1

或者,您也可以使用类似数组的符号:

delete obj[key1]

参考:MDN


8

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


7

丹的断言“删除”非常缓慢,他发布的基准测试受到质疑。因此,我自己在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

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


7

考虑创建不带该"regex"属性的新对象,因为原始对象始终可以被程序的其他部分引用。因此,您应该避免对其进行操作。

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

const { regex, ...newMyObject } = myObject;

console.log(newMyObject);


SyntaxError: Unexpected token '...'. Expected a property name.
Krzysztof Przygoda

可以在Firefox,Chromium或Safari等现代浏览器上进行尝试。我希望它也可以与Edge一起使用。
ideaboxer

或者,如果您的客户强迫您支持过时的浏览器,则可以考虑使用TypeScript,它将您的代码转换为旧语法(+为您提供静态类型安全性的好处)。
ideaboxer

7

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

此类别是属性删除的最古老,最直接和最广泛支持的类别。Symbol除了字符串之外,它还支持&数组索引,并且在第一个JavaScript版本中均可使用,除了第一个发行版。但是,它是变异的,违反了一些编程原则,并且对性能有影响。在严格模式下不可配置的属性使用时,也会导致未捕获的异常

基于休息的字符串属性遗漏

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

此外,尽管就地改变对象不是无状态的,但您可以使用的功能性质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"

var keyname =“ KeyName”; 删除myObject [keyname];
维卡什·乔汉

7

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

const { regex, ...other } = myObject;

console.log(myObject)
console.log(regex)
console.log(other)


@CoddWrench抱歉,我没有注意看到该答案。我看到后马上回答delete myObject.regex;

7

您可以将ES6解构与rest运算符一起使用。

可以结合使用销毁和删除属性 rest运算符。在您的示例中,正则表达式被解构(忽略),其余属性作为其余部分返回。

const noRegex = ({ regex, ...rest }) => rest;
const myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};

console.log(noRegex(myObjext)) //=> {  "ircEvent": "PRIVMSG","method": "newURI" }

或者,您可以动态排除此类属性,

const myObject = {
  "ircEvent": "PRIVMSG",
  "method": "newURI",
  "regex": "^http://.*"
};
const removeProperty = prop => ({ [prop]: _, ...rest }) => rest

const removeRegex = removeProperty('regex') //=> {  "ircEvent": "PRIVMSG","method":"newURI" }
const removeMethod = removeProperty('method') //=> {  "ircEvent": "PRIVMSG", "regex":"^http://.*" }

7

我们可以使用以下方法从javascript对象中删除任何属性:

  1. 删除object.property
  2. 删除对象['属性']

例:

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

console.log(myObject);

delete myObject.regex;
console.log('=================');
console.log(myObject);
delete myObject['method'];
console.log('=================');
console.log(myObject);


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.