从对象中删除属性 (JavaScript)
Posted
技术标签:
【中文标题】从对象中删除属性 (JavaScript)【英文标题】:Remove properties from objects (JavaScript) 【发布时间】:2010-09-17 12:15:43 【问题描述】:假设我创建一个对象如下:
let myObject =
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*",
;
我应该如何删除属性regex
以得到新的myObject
,如下所示?
let myObject =
"ircEvent": "PRIVMSG",
"method": "newURI",
;
【问题讨论】:
删除 myObject.regex; // 或者,删除 myObject['regex']; // 或者, var prop = "regex";删除 myObject[prop]; 【参考方案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 在他们的博客 Understanding delete 上写了一篇关于 delete
声明的非常深入的博文。强烈推荐。
如果您想要一个 new 对象,其中包含除一些之外的所有原始键,您可以使用 destructuring。
演示
let myObject =
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
;
const regex, ...newObj = myObject;
console.log(newObj); // has no 'regex' key
console.log(myObject); // remains unchanged
【讨论】:
这是一个很好的方法,但只有当你真的要使用regex
时才好,否则eslint会抱怨一个未使用的变量。
@Loolooii 您可以在解构赋值中重命名变量以满足no-unused-vars
规则中的argsIgnorePattern
。很容易解决的问题。
我用这种方法遇到的问题是,如果破坏是在条件内,它会让 ESlint 变得疯狂。
@nickf 文章是 404 :(
文章不见了——当好的内容消失时很伤心,很高兴我们有回程机器:web.archive.org/web/20210224201033/http://perfectionkills.com/… :)【参考方案2】:
javascript 中的对象可以被认为是键和值之间的映射。 delete
运算符用于删除这些键,通常称为对象属性,一次一个。
var obj =
myProperty: 1
console.log(obj.hasOwnProperty('myProperty')) // true
delete obj.myProperty
console.log(obj.hasOwnProperty('myProperty')) // false
delete
运算符不直接释放内存,它与简单地将 null
或 undefined
的值分配给属性不同,因为属性 本身 从目的。请注意,如果已删除属性的 value 是引用类型(对象),并且程序的另一部分仍然持有对该对象的引用,那么该对象当然不会是垃圾直到所有对它的引用都消失为止。
delete
仅适用于描述符将其标记为可配置的属性。
【讨论】:
【参考方案3】:var myObject = "ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*";
delete myObject.regex;
console.log ( myObject.regex); // logs: undefined
这适用于 Firefox 和 Internet Explorer,我认为它适用于所有其他。
【讨论】:
【参考方案4】:老问题,现代答案。使用对象解构,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);
You can see it in action in the Babel try-out editor.
编辑:
要重新分配给同一个变量,请使用let
:
let myObject = "ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*";
( regex, ...myObject = myObject);
console.log(myObject);
【讨论】:
如果属性名称不同,我如何解构,即如果我将它放在变量中? 请看下面的答案; ***.com/a/52301527【参考方案5】:delete
运算符用于从对象中删除属性。
const obj = foo: "bar"
delete obj.foo
obj.hasOwnProperty("foo") // false
请注意,对于数组,这与删除元素不同。要从数组中删除元素,请使用 Array#splice
或 Array#pop
。例如:
arr // [0, 1, 2, 3, 4]
arr.splice(3,1); // 3
arr // [0, 1, 2, 4]
详情
JavaScript 中的delete
与 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
作为索引处的值。
forEach
、map
和 reduce
将直接跳过缺失的索引。
因此,delete
运算符不应用于从数组中删除元素的常见用例。数组有专门的移除元素和重新分配内存的方法:Array#splice()
和 Array#pop
。
Array#splice(start[, deleteCount[, item1[, item2[, ...]]]])
Array#splice
改变数组,并返回所有删除的索引。 deleteCount
元素从索引start
中删除,item1, item2... itemN
从索引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.prototype
上还有一个名称相似但不同的函数:Array#slice
。
数组#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]
数组#pop
Array#pop
从数组中删除最后一个元素,并返回该元素。这个操作改变了数组的长度。
【讨论】:
【参考方案6】:Spread Syntax (ES6)
要完成Koen's answer,如果您想使用展开语法删除动态变量,您可以这样做:
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)。
扩展答案?
有几种常用的方法可以从对象中删除属性。 每一种都有自己的优缺点 (check this performance comparison):
Delete Operator
它可读且简短,但是,如果您在大量对象上进行操作,它可能不是最佳选择,因为它的性能没有优化。
delete obj[key];
Reassignment
它比delete
快两倍以上,但是该属性没有被删除并且可以迭代。
obj[key] = null;
obj[key] = false;
obj[key] = undefined;
Spread Operator
这个ES6
运算符允许我们返回一个全新的对象,不包括任何属性,而不改变现有对象。缺点是它的性能比上述更差,不建议在需要一次删除许多属性时使用。
[key]: val, ...rest = obj;
【讨论】:
这不是删除属性,而是创建一个浅拷贝,而不是跨指定的键和值进行复制。这是一个非常大的区别。【参考方案7】:另一种选择是使用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()
可以以类似的方式使用。
【讨论】:
【参考方案8】:克隆一个没有属性的对象:
例如:
let object = a: 1, b: 2, c: 3 ;
我们需要删除a
。
使用显式属性键:
const a, ...rest = object;
object = rest;
使用可变道具键:
const propKey = 'a';
const [propKey]: propValue, ...rest = object;
object = rest;
一个很酷的箭头函数?:
const removeProperty = (propKey, [propKey]: propValue, ...rest ) => rest;
object = removeProperty('a', object);
对于多个属性
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
【讨论】:
【参考方案9】:您在问题标题中使用的术语,从 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"];
然后,即使您将其从对象 myJSONObject
中删除,该特定对象也不会从内存中删除,因为 regex
变量和 myOtherObject["regex"]
仍然具有它们的值。那么我们如何才能确定从内存中删除对象呢?
答案是删除代码中所有指向该对象的引用,并且不要使用var
语句来创建对该对象的新引用强>。关于var
语句的最后一点是我们通常面临的最关键问题之一,因为使用var
语句会阻止创建的对象被删除。
这意味着在这种情况下您将无法删除该对象,因为您已通过 var
语句创建了 regex
变量,如果您这样做了:
delete regex; //False
结果将是false
,这意味着您的删除语句没有按预期执行。但是,如果您之前没有创建该变量,并且您只有 myOtherObject["regex"]
作为您的最后一个现有引用,您可以通过删除它来做到这一点:
myOtherObject["regex"] = null;
delete myOtherObject["regex"];
换句话说,只要代码中没有指向该对象的引用,JavaScript 对象就会被终止。
更新:
感谢@AgentME:
在删除之前将属性设置为 null 不会完成 任何东西(除非对象已被 Object.seal 和 删除失败。通常情况并非如此,除非您特别指定 试试)。
如需了解Object.seal
的更多信息:Object.seal()
【讨论】:
【参考方案10】: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 operator)在尝试删除它的任何属性时返回false
。如果属性是可配置的,它返回true
,即使属性不存在。
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
【讨论】:
【参考方案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'];
同样,通过调用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
将删除元素,但不会更新 length
属性的值。使用delete
也会弄乱您的索引。
因此,在从对象中删除值时,请始终首先考虑您是在处理对象属性还是在处理数组值,并据此选择合适的策略。
如果您想对此进行实验,可以使用this Fiddle 作为起点。
【讨论】:
【参考方案12】:我个人使用Underscore.js 或Lodash 进行对象和数组操作:
myObject = _.omit(myObject, 'regex');
【讨论】:
【参考方案13】:使用 delete 方法是最好的方法,根据 MDN 的描述,删除操作符从对象中删除一个属性。所以你可以简单地写:
delete myObject.regex;
// OR
delete myObject['regex'];
delete 运算符从对象中删除给定的属性。在 删除成功返回true,否则返回false。 但是,请务必考虑以下情况:
如果您要删除的属性不存在,请删除 不会有任何效果,会返回true
如果对象的原型上存在同名属性 链,然后,删除后,对象将使用来自 原型链(也就是说,delete 只对自己有影响 属性)。
任何用 var 声明的属性都不能从全局作用域中删除 或来自函数的范围。
因此,delete 不能删除全局范围内的任何函数(无论这是函数定义的一部分还是函数(表达式)的一部分。
作为对象一部分的函数(除了 全局作用域)可以用 delete 删除。
使用 let 或 const 声明的任何属性都不能从定义它们的范围中删除。无法删除不可配置的属性。这包括内置对象(如 Math、Array、Object)的属性以及使用 Object.defineProperty() 等方法创建为不可配置的属性。
下面的sn-p给出了另一个简单的例子:
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
【讨论】:
【参考方案14】:另一种解决方案,使用 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);
【讨论】:
【参考方案15】:这里有很多很好的答案,但我只想指出,在 JavaScript 中使用 delete 删除属性时,首先检查该属性是否存在以防止错误通常是明智之举。
例如
var obj = "property":"value", "property2":"value";
if (obj && obj.hasOwnProperty("property2"))
delete obj.property2;
else
//error handling
由于 JavaScript 的动态特性,经常出现您根本不知道该属性是否存在的情况。在 && 之前检查 obj 是否存在还可以确保您不会因为在未定义的对象上调用 hasOwnProperty() 函数而引发错误。
很抱歉,如果这没有添加到您的特定用例中,但我相信这是一个很好的设计,可以在管理对象及其属性时进行调整。
【讨论】:
【参考方案16】:这篇文章很老了,我觉得它很有帮助,所以我决定分享我写的 unset 函数,以防其他人看到这篇文章并想为什么它不像 php 的 unset 函数那么简单。
编写这个新的unset
函数的原因是为了在这个hash_map 中保留所有其他变量的索引。看下面的例子,看看“test2”的索引在从 hash_map 中删除一个值后是如何变化的。
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"
【讨论】:
【参考方案17】:试试下面的方法。将Object
属性值分配给undefined
。然后stringify
对象和parse
。
var myObject = "ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*";
myObject.regex = undefined;
myObject = JSON.parse(JSON.stringify(myObject));
console.log(myObject);
【讨论】:
【参考方案18】:使用ramda#dissoc你会得到一个没有regex
属性的新对象:
const newObject = R.dissoc('regex', myObject);
// newObject !== myObject
您也可以使用其他函数来达到相同的效果 - 省略、选择、...
【讨论】:
【参考方案19】:如果你想删除一个深深嵌套在对象中的属性,那么你可以使用以下递归函数,并将属性的路径作为第二个参数:
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:
【讨论】:
【参考方案20】:使用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
【讨论】:
很奇怪。您的代码_.omit(['a', 'd'], a: 1, b: 2, c: 3, d: 4);
对我不起作用,但 _.omit(a: 1, b: 2, c: 3, d: 4, ['a', 'd']);
确实起作用。【参考方案21】:
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"];
);
【讨论】:
【参考方案22】:这是一种 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"
【讨论】:
【参考方案23】:JavaScript 中的属性删除
此页面上提供了许多不同的选项,不是因为大多数选项都是错误的——或者因为答案是重复的——而是因为适当的技术取决于你所处的情况以及你和任务的目标/或者你的团队正在努力实现。要明确回答您的问题,您需要知道:
-
您要定位的 ECMAScript 版本
要删除属性的对象类型范围以及需要能够省略的属性名称类型(仅限字符串?符号?从任意对象映射的弱引用?这些都是 JavaScript 中的属性指针类型多年来)
您和您的团队使用的编程精神/模式。您喜欢函数式方法并且在您的团队中禁止使用变异,还是使用狂野西部变异的面向对象技术?
您是希望在纯 JavaScript 中实现这一目标,还是愿意并能够使用第 3 方库?
一旦这四个查询得到回答,为了满足您的目标,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 版本中使用。但是,它是可变的,它违反了一些编程原则并具有性能影响。在 non-configurable properties in strict mode 上使用时也可能导致未捕获的异常。
基于 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
此外,虽然就地改变对象不是无状态的,但您可以使用 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"
【讨论】:
【参考方案24】:Dan's assertion“删除”非常慢,他发布的基准受到质疑。所以我自己在 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
请注意,我特意在一个循环周期中执行了多个“删除”操作,以尽量减少其他操作造成的影响。
【讨论】:
【参考方案25】:@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
【讨论】:
【参考方案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)
【讨论】:
但是 filter() 方法创建了一个数组,其中填充了所有通过测试的数组元素,因此过滤器的唯一目的是减少并创建一个新数组 是的,但这只有在您使用过滤器的返回值时有用in 作为它的参数,但如果这些事情在这里完成,则没有,所以它的唯一目的是迭代数组元素,这就是 forEach 的用途 你可以改为let filter = Object.fromEntries(Object.entries(myObject).filter(d => d !== 'regex' ))
【参考方案27】:
我已经使用Lodash "unset" 使其也适用于嵌套对象...只是这需要编写小逻辑来获取 omit 方法所期望的属性键的路径.
-
以数组形式返回属性路径的方法
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>
-
然后只需使用Lodash unset 方法从对象中删除属性。
var unset = require('lodash.unset');
unset(a, getPathOfKey(a, "price_index.final_price"));
【讨论】:
【参考方案28】: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)
您也可以使用Object.entries
将对象视为a2d
数组,并像在普通数组中一样使用拼接删除元素,或者像数组一样简单地过滤对象,然后分配将重构对象还原为原始变量
【讨论】:
【参考方案29】:如果您不想修改原始对象。
删除属性而不改变对象
如果可变性是一个问题,您可以通过复制旧对象的所有属性来创建一个全新的对象,但要删除的属性除外。
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);
【讨论】:
【参考方案30】:删除对象的两种方法
使用为 ... 在
function deleteUser(key)
const newUsers = ;
for (const uid in users)
if (uid !== key)
newUsers[uid] = users[uid];
return newUsers
或
delete users[key]
【讨论】:
所以你建议删除一个属性,整个对象应该被复制到一个没有目标属性的新对象中?!? 那是有效的代码吗?
似乎不见了。您可以edit your answer - 但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。以上是关于从对象中删除属性 (JavaScript)的主要内容,如果未能解决你的问题,请参考以下文章
从嵌套的 javascript 对象中删除属性的最佳方法是啥?