假设我按如下方式创建了一个对象:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
删除属性regex
以最终获得新myObject
的最佳方法是什么?
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI"
};
答案 0 :(得分:7608)
像这样:
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
声明, Understanding delete < / em>的。强烈推荐。
答案 1 :(得分:818)
delete
出乎意料地慢了!查看 benchmark 。
删除是删除对象属性而没有任何剩余物的唯一真正方法,但它可以 ~100倍慢,
与其替代&#34;相比,设置object[key] = undefined
。
这个替代方案不是这个问题的正确答案!但是,如果你小心使用它,你可以大大加快一些算法。如果您在循环中使用delete
并且遇到性能问题,请阅读详细说明。
delete
并将值设置为undefined
?对象可以被视为一组键值对。我称之为“价值”的东西。是一个原始的或对其他对象的引用,连接到该键&#39;。
将结果对象传递给您无法控制的代码(或者您对自己的团队或自己不确定时),请使用delete
,
从hashmap中删除密钥。
var obj = {
field: 1
};
delete obj.field;
在关注效果时,请将设置设为undefined
,。它可以大大提升您的代码。
键仍保留在hashmap中的位置,只有该值替换为undefined
。明白,for..in
循环仍将遍历该密钥。
var obj = {
field: 1
};
obj.field = undefined;
使用此方法,并非所有ways of determining property existence都能按预期工作。
但是,这段代码:
object.field === undefined
的行为都相同。
总而言之,差异是关于确定属性存在的方式以及关于for..in
循环的所有方法。
console.log('* -> "Takes prototype inheritance into consideration, that means it lookups all over prototype chain too."');
console.log(obj.field === undefined, 'obj.field === undefined', 'You get "undefined" value when querying for "field" in object-hashmap. *');
console.log(obj["field"] === undefined, 'obj["field"] === undefined', 'Just another way to query (equivalent). *');
console.log(typeof obj.field === "undefined", 'typeof obj.field === "undefined"', 'Get the value attached to "field" key, and check it\'s type is "undefined". *');
console.log("field" in obj, '"field" in obj', 'This statement returns true if "field" key exists in the hashmap. False otherwise. *');
console.log(obj.hasOwnProperty("field"), 'obj.hasOwnProperty("field")', 'This statement returns true if \'field\' key exists in the hashmap. The ONLY way NOT to lookup for property in the prototype chain!');
//Object.keys().indexOf() is an overkill that runs much slower :)
var counter = 0,
key;
for (key in obj) {
counter++;
}
console.assert(counter === 0, 'counter === 0', '"field" is not iterated using "for .. in" loop. *');
虽然使用obj[prop] = undefined
比执行delete obj[prop]
更快,但另一个重要的考虑因素是obj[prop] = undefined
可能并不总是合适的。 delete obj[prop]
从prop
移除obj
并从内存中删除obj[prop] = undefined
,而prop
只是将undefined
的值设置为prop
,obj[prop] = undefined
离开"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
nodeRecords[i] = [];
current = theNodeList[i] = document.createElement("div");
current.textContent = i;
document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
var currentTime = Math.round( performance.now()*1000 )
for (i = 0; i !== numberOfNodes; i++) {
if (lastTime !== -1) {
// the previously collected data is no longer in use
/*************************************************/
/****/ nodeRecords[i][lastTime] = undefined; /****/
/*************************************************/
}
nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
}
lastTime = currentTime;
requestAnimationFrame( recordUpdates );
});
仍然在记忆中。因此,在创建和删除许多密钥的情况下,使用nodeRecords[i][lastTime] = undefined;
会强制进行昂贵的内存协调(导致页面冻结)并可能导致内存不足错误。检查以下代码。
delete
在上面的代码中,简单地执行"use strict";
var theNodeList=[], i, current, numberOfNodes=65536, body=document.body, nodeRecords=[];
for (i = 0; i !== numberOfNodes; i++) {
nodeRecords[i] = [];
current = theNodeList[i] = document.createElement("div");
current.textContent = i;
document.body.appendChild( current );
}
var lastTime = -1;
requestAnimationFrame(function recordUpdates(){
var currentTime = Math.round( performance.now()*1000 )
for (i = 0; i !== numberOfNodes; i++) {
if (lastTime !== -1) {
// the previously collected data is no longer in use
/********************************************/
/****/ delete nodeRecords[i][lastTime]; /****/
/********************************************/
}
nodeRecords[i][currentTime] = theNodeList[i].outerHTML;
}
lastTime = currentTime;
requestAnimationFrame( recordUpdates );
});
将导致大量内存泄漏,因为每个动画帧。每个帧,所有65536个DOM元素将占用另外65536个单独的插槽,但之前的65536个插槽只会被设置为未定义,这会使它们挂在内存中。来吧,尝试在控制台中运行上面的代码并亲自查看。在强制出现内存不足错误后,尝试再次运行它,除非使用以下版本的代码使用delete
运算符。
obj[prop] = undefined
如上面的代码段所示,undefined
运算符有一些罕见的适当用例。但是,不要太担心这个问题。这只会成为长寿命对象的问题,这些对象会不断添加新密钥。在任何其他情况下(几乎在实际编程中都是这种情况),最适合使用var foo = "str";
foo = 100; // variable foo is now labeled polymorphic by the browser
var bar = ["Some", "example"];
bar[2] = "text"; // bar is a monomorphic array here because all its entries have the
// same type: string primitive
bar[1] = undefined; // bar is now a polymorphic array
。本节的主要目的只是为了引起您的注意,以便在您的代码中这很可能成为一个问题,那么您可以更轻松地理解问题,从而不必浪费时间来分析您的代码来定位并了解这个问题。
delete
Javascript的一个重要考虑因素是多态性。多态性是指在同一个变量/对象中插入不同的类型,如下所示。
var bar = ["Some", "example"];
bar[2] = "text"; // bar is not a polymorphic array here because all its entries have the
// same type: string primitive
bar[1] = ""; // bar is still a monomorphic array
bar[1] = undefined; // bar is now a polymorphic array
但是,多态数组存在两个主要的无法解决的问题:
有人可能将多态性比作药物成瘾。乍一看,它似乎非常有利可图:漂亮的蓬松代码。然后,编码器将他们的阵列引入多态性药物。即时地,多态数组变得效率较低,并且由于它是药物,它永远不会像以前那样有效。为了将这种情况与现实生活联系起来,可卡因的某些人甚至可能无法操作简单的门把手,更不用说能够计算PI的数字了。同样,多态性药物上的数组也不能像单形数组那样有效。
但是,药物旅行类比如何与bar[1] = ""
操作相关?答案在上面的代码片段中包含了最后一行代码。因此,让它重新审视,这次是扭曲。
bar[1] = undefined
观察。 false
不强制多态,而undefined
则强制执行多态。因此,应该始终尽可能为对象使用相应的类型,以免意外地导致多态性。一个这样的人可以使用以下列表作为一般参考来使他们前进。但是,请不要明确使用以下想法。相反,使用适用于您的代码的任何东西。
0
或NaN
作为空值。虽然避免不必要的多态性是好的,但重写所有代码以明确禁止它可能实际上会导致性能下降。使用共同判断!Infinity
作为空值。请注意,在内部,有两种类型的数字:快速整数(包括2147483647到-2147483648)和慢浮点双精度(除了包括""
和null
之外的任何其他内容)。当一个整数降级为double时,它不能被提升回整数。但是,请注意!现在不要突然开始使用所有预先存在的代码执行此操作,因为它可能会破坏此类预先存在的代码和/或引入奇怪的错误。相反,这种有效的实践需要从一开始就实现,并且在转换预先存在的代码时,建议您对所有与之相关的行进行双倍,三倍,四倍检查,因为尝试将旧代码升级到此新实践可以是有风险,因为它是有益的。
答案 2 :(得分:223)
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
delete myObject.regex;
console.log ( myObject.regex); // logs: undefined
这适用于Firefox和Internet Explorer,我认为它适用于所有其他人。
答案 3 :(得分:177)
更新2018-07-21:很长一段时间,我对这个答案感到尴尬,所以我觉得现在是时候点了一下。只需要一点评论,澄清和格式化,以帮助加快阅读这个答案中不必要的冗长而复杂的部分。
正如其他人所说,你可以使用delete
。
obj // {"foo": "bar"}
delete obj["foo"]
obj // {}
obj["foo"] // undefined
不要从数组中delete
。请改用Array.prototype.splice
。
arr // [1,2,3,4,5]
arr.splice(3,1); // 4
arr // [1,2,3,5]
JavaScript是一种OOP语言,所以一切都是对象,包括数组。因此,我认为有必要指出一个特别的警告。
在数组中,与普通旧对象不同,使用delete
以null
的形式留下垃圾,创建一个&#34;洞&#34;在阵列中。
var array = [1, 2, 3, 4];
delete array[2];
/* Expected result --> [1, 2, 4]
* Actual result --> [1, 2, null, 4]
*/
正如您所看到的,delete
并不像人们预期的那样始终有效。该值被覆盖,但内存未重新分配。也就是说,array[4]
并未重新定位到array[3]
。这与Array.prototype.unshift
相反,后者在数组的开头插入一个元素并将所有内容向上移动(array[0]
变为array[1]
等等。)
老实说,除了设置为null
而不是undefined
- 这是合法的奇怪 - 这种行为不应该是令人惊讶的,因为{{1这是一个一元运算符,如delete
,它很难用于语言,并且不应该关心它所使用的对象的类型,而typeof
是Array
的子类,其方法专门用于使用数组。因此Object
没有充分的理由让一个特殊的案例用于重新转换阵列,因为这会减少不必要的工作。回想起来,我的期望是不现实的。
当然,确实让我感到惊讶。因为我写这篇文章是为了证明我的反对&#34; null垃圾&#34;:
忽略
delete
中固有的危险和问题,以及浪费的空间,如果阵列需要精确,这可能会有问题。
对于摆脱null
s而言,这是一个可怕的理由 - null
只有在使用不当时才会有危险,并且它与&#34; precision&#34;无关。你不应该从数组中null
的真正原因是留下垃圾填充和混乱的数据结构是邋and和容易出错。
以下是一个非常冗长的人为设计方案,因此如果您愿意,可以跳到解决方案部分。我离开这一部分的唯一原因是,我认为有些人可能认为这很有趣,而且我不想成为那个&#34;那个人&#34;谁发布了一个有趣的&#34;回答然后删除所有&#34;搞笑&#34;从以后开始。
......我知道这是愚蠢的。
例如,假设您正在创建一个使用JSON序列化来存储用于&#39;标签的数组的Web应用程序。在一个字符串中(在这种情况下,
delete
)。我们还要说代码使用数组成员的数字索引来标题&#34;标题&#34;绘制到屏幕时它们。你为什么这样做而不仅仅是存储&#34;标题&#34;还有?因为...... 原因。好的,我们只是说,你应该从这个一个用户的请求中节省内存,这个用户从1960年开始运行PDP-11小型机运行UNIX并编写了自己的基于Elinks,符合JavaScript的,行式打印机友好的浏览器,因为X11 是不可能的。
除了越来越愚蠢的边缘情况之外,在所述数组上使用
localStorage
将导致delete
污染数组,并可能导致应用程序中的错误。如果您检查null
,它会直接跳过这些数字,从而导致标签呈现为null
。[1] [2] [4] [5] ...
是的,那绝对不是你想要的。
现在,可以保留第二个迭代器,如
if (array[index] == null) continue; else title = (index + 1).toString(); /* 0 -> "1" * 1 -> "2" * 2 -> (nothing) * 3 -> "4" */
,只有在从数组中读取有效值时才会递增。但这并不能完全解决j
问题,您仍然需要取悦trollPDP-11用户。唉,他的电脑只是没有有足够的内存来容纳最后一个整数(不要问他如何设法处理一个可变宽度的数组...)< /子>所以,他向你发了一封愤怒的电子邮件:
null
现在,您的智慧结束了。这家伙一直抱怨你的应用程序不停,你想告诉他闭嘴,然后去买一台更好的电脑。
Hey, your webapp broke my browser! I checked my localStorage database after your stupid code made my browser segfault, and this is what I found:
>"tabs:['Hello World', 'foo bar baz', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, ... ]"
After clearing my precious data, it segfaulted again, and I did a backtrace, and what do I find? WHAT DO I FIND!? YOU USE TOO MANY VARIABLES!
>var i = index;
>var j = 1;
Grr, I am angry now.
-Troll Davidson
幸运的是,数组 do 有一个专门的方法来删除索引并重新分配内存:Array.prototype.splice
。你可以这样写:
Array.prototype.splice()
就这样,你对PDP-11先生感到高兴。万岁! (我仍然告诉他,不过......)
我觉得指出这两个同名的函数之间的区别非常重要,因为它们都非常有用。
Array.prototype.remove = function(index){
this.splice(index,1);
}
...
array = [1, 2, 3, 4];
array.remove(2);
// Result -> [1, 2, 4]
改变数组,并返回删除的索引。从索引开始切片数组,.splice()
和start
元素被切片。如果未指定n,则n
之后的整个数组将被切除(start
)。
n = array.length - start
let a = [5,4,3,2,1];
let chunk = a.splice(2,2);
// a [5,4,3,2,1]
// start 0 1 2 - -
// n - - 1 2 -
chunk; // [3,2]
a; // [5,4,1]
是非破坏性的,并返回一个新数组,其中包含从.slice()
到start
的指示索引。如果未指定end
,则行为与end
(.splice()
)相同。这种行为有点棘手,因为出于某种原因,end = array.length
索引从1而不是0.我不知道为什么会这样做,但那是怎么回事。此外,如果end
,则结果为空数组。
end <= start
实际上并不是发生了什么,但更容易想到这一点。根据MDN,这是实际发生的事情:
let a = [5,4,3,2,1];
let chunks = [
a.slice(2,0),
a.slice(2,2),
a.slice(2,3),
a.slice(2,5) ];
// a [5,4,3,2,1]
// start 0 1 2 - -
// end, for... - - - - -
// chunks[0] 0 - - - - -
// chunks[1] 1 2 - - -
// chunks[2] 1 2 3 - -
// chunks[3] 1 2 3 4 5
chunks; // [ [], [], [3], [3,2,1] ]
a; // [5,4,3,2,1]
// a [5,4,3,2,1]
// start 0 1 2 - - -
// end, for... - - - - - -
// chunks[0] 0 - - - - -
// chunks[1] 0 1 2 - - -
// chunks[2] 0 1(2)3 - -
// chunks[3] 0 1(2 3 4)5
指定的索引只是从切片中排除。带括号的索引表示切片的内容。无论哪种方式,行为都不直观,并且它必然导致其公平分享一个一个错误,因此您可能会发现使包装函数更接近地模拟{{1}的行为很有用。 }:
end
请注意,包装函数的设计对类型非常严格,如果有任何关闭,它将返回.splice()
。这包括输入像function ez_slice(array, start = 0, n = null){
if(!Array.isArray(array) || !is_number(start))
return null;
if(is_number(n))
return array.slice(start, start + n);
if(n === null)
return array.slice(start);
return null;
}
ez_slice([5,4,3,2,1], 2, 1) // [3]
ez_slice([5,4,3,2,1], 2) // [3,2,1]
/* Fun fact: isNaN is unreliable.
* [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(isNaN)
* [NaN, {}, undefined, "Hi"]
*
* What we want is...
*
* [NaN, [], {}, 0, 1, Infinity, undefined, null, "Hi"].filter(is_nan)
* [NaN]
*/
function is_nan(num){
return typeof num === "number"
&& num !== num;
}
function is_number(num){
return !is_nan(num)
&& typeof num === "number"
&& isFinite(num);
}
这样的字符串。程序员需要勤勉地研究他的类型。这是为了鼓励良好的编程实践。
null
这与此(现已删除)代码段有关:
"3"
事实证明,实际上有一种内置的方法来判断一个数组是否真的是一个数组,而且是is_array()
,在ECMAScript 5(2009年12月)中引入。我找到了这个,同时查看是否有一个问题询问是否从对象告诉数组,看看是否有比我更好的解决方案,或者如果没有,则添加我的。因此,如果您使用的是早于ECMA 5的JavaScript版本,则可以使用您的polyfill。但是,我强烈建议不要使用我的function is_array(array){
return array !== null
&& typeof array === "object"
&& typeof array.length !== "undefined"
&& array.__proto__ === Array.prototype;
}
功能,因为继续支持旧版本的JavaScript意味着继续支持实现它们的旧浏览器,这意味着鼓励使用不安全的软件并使用户面临恶意软件的风险。所以,请使用Array.isArray()
。使用is_array()
和Array.isArray()
。使用添加到该语言的新功能。 Don&#t> 使用供应商前缀。 删除您网站上的IE polyfill废话。删除那个XHTML let
废话 - 我们在2014年转移到HTML5。每个人都越早撤回对那些旧/深奥浏览器的支持,浏览器供应商越早实际遵循Web标准并采用新技术,我们越早可以转向更安全的网络。
答案 4 :(得分:145)
老问题,现代答案。使用对象解构,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);
答案 5 :(得分:87)
另一种方法是使用Underscore.js库。
请注意,_.pick()
和_.omit()
都会返回对象的副本,而不会直接修改原始对象。将结果分配给原始对象应该可以解决问题(未显示)。
参考:link _。选择(对象,*键)
返回对象的副本,过滤到只有值的值 列入白名单的密钥(或有效密钥数组)。
var myJSONObject =
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
_.pick(myJSONObject, "ircEvent", "method");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};
参考:link _。省略(对象,*键)
返回对象的副本,过滤后省略 列入黑名单的密钥(或密钥数组)。
var myJSONObject =
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
_.omit(myJSONObject, "regex");
=> {"ircEvent": "PRIVMSG", "method": "newURI"};
对于数组,_.filter()
和_.reject()
可以以类似的方式使用。
答案 6 :(得分:57)
对需要它的人...
要在此线程中完成@Koen答案,如果您要使用传播语法删除动态变量,可以这样操作:
const key = 'a';
const { [key]: foo, ...rest } = { a: 1, b: 2, c: 3 };
console.log(rest); // { b: 2, c: 3 }
* foo
将是一个新变量,其值为a
(即1)。
更新 :
从对象中删除属性的方法很少。
每个都有其优缺点(check this performance comparison):
Delete Operator
可读且简短,但是,如果您在大量对象上进行操作,则可能不是最佳选择,因为其性能未得到优化。
delete obj[key];
Reassignment
比delete
快2倍多,但是该属性未被删除并且可以迭代。
obj[key] = null;
obj[key] = false;
obj[key] = undefined;
Spread Operator
该ES6
运算符使我们可以返回一个全新的对象(不包括任何属性),而无需更改现有对象。不利的一面是,它的性能比以上更差,因此建议您一次删除许多属性时不建议使用。
{ [key]: val, ...rest } = obj;
答案 7 :(得分:45)
您在问题标题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
,这意味着您的删除语句尚未按预期执行。但是,如果您之前没有创建过该变量,并且只有myOtherObject["regex"]
作为上一个现有参考,那么您可以通过删除它来完成此操作:
myOtherObject["regex"] = null;
delete myOtherObject["regex"];
换句话说,只要代码中没有指向该对象的引用,JavaScript对象就会被终止。
<强>更新强> 感谢@AgentME:
在删除属性之前将属性设置为null无法完成 任何东西(除非对象已被Object.seal和 删除失败。除非你具体,否则通常情况并非如此 尝试)。
要获取有关Object.seal
:Object.seal()
答案 8 :(得分:38)
ECMAScript 2015(或ES6)带有内置的Reflect对象。可以通过使用目标对象和属性键作为参数调用Reflect.deleteProperty()函数来删除对象属性:
Reflect.deleteProperty(myJSONObject, 'regex');
相当于:
delete myJSONObject['regex'];
但是如果对象的属性不可配置,则不能使用deleteProperty函数删除也不能删除操作符:
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
答案 9 :(得分:37)
假设您有一个如下所示的对象:
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作为起点。
答案 10 :(得分:27)
delete operator是最好的方法。
要显示的实例:
function sortFunction(a, b) {
if (a[0] === b[0]) { return 0; }
else {return (a[0] < b[0]) ? -1 : 1;}
}
// cacheData is the original data
cacheDataSorted = cacheData.sort(sortFunction);
答案 11 :(得分:27)
我个人使用Underscore.js或Lodash进行对象和数组操作:
myObject = _.omit(myObject, 'regex');
答案 12 :(得分:22)
使用删除方法是执行此操作的最佳方法,根据MDN说明,删除操作符会从对象中删除属性。所以你可以简单地写一下:
delete myObject.regex;
// OR
delete myObject['regex'];
delete运算符从对象中删除给定属性。上 成功删除,它将返回true,否则将返回false。 但是,考虑以下情况非常重要:
如果您要删除的媒体资源不存在,请删除 没有任何效果,将返回真实
如果对象的原型中存在具有相同名称的属性 链,然后,删除后,对象将使用该属性 原型链(换句话说,删除只对自己产生影响 属性)。
无法从全局范围中删除使用var声明的任何属性 或者从功能的范围。
因此,删除不能删除全局范围内的任何函数(无论这是函数定义还是函数(表达式)的一部分。
作为对象一部分的功能(除了 可以删除全局范围)。
使用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
&#13;
有关更多信息和查看更多示例,请访问以下链接:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
答案 13 :(得分:20)
另一种解决方案,使用 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);
答案 14 :(得分:19)
这篇文章非常陈旧,我发现它非常有用所以我决定分享我写的未设置函数,以防其他人看到这篇文章,并想一想为什么它不像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"}
答案 15 :(得分:18)
这里有很多好的答案,但我只是想说明当使用delete删除JavaScript中的属性时,首先检查该属性是否存在以防止错误通常是明智的。
E.g
var obj = {"property":"value", "property2":"value"};
if (obj && obj.hasOwnProperty("property2")) {
delete obj.property2;
} else {
//error handling
}
由于JavaScript的动态特性,通常情况下您根本不知道该属性是否存在。检查obj是否存在于&amp;&amp;还确保您不会因为在未定义的对象上调用hasOwnProperty()函数而抛出错误。
很抱歉,如果这没有添加到您的特定用例中,但我相信这是一个很好的设计,可以在管理对象及其属性时进行调整。
答案 16 :(得分:14)
使用ramda#dissoc,您将获得一个没有属性regex
的新对象:
const newObject = R.dissoc('regex', myObject);
// newObject !== myObject
您还可以使用其他功能来实现相同的效果 - 省略,选择......
答案 17 :(得分:13)
尝试以下方法。将Object
属性值分配给undefined
。然后stringify
对象和parse
。
var myObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
myObject.regex = undefined;
myObject = JSON.parse(JSON.stringify(myObject));
console.log(myObject);
&#13;
答案 18 :(得分:11)
如果要删除深度嵌套在对象中的属性,则可以使用以下递归函数,并将该属性的路径作为第二个参数:
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 :(得分:11)
使用ES6:
(解构+传播运算符)
const myObject = {
regex: "^http://.*",
b: 2,
c: 3
};
const { regex, ...noRegex } = myObject;
console.log(noRegex); // => { b: 2, c: 3 }
答案 20 :(得分:8)
这是一种轻松删除条目的 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" }
答案 21 :(得分:8)
要克隆不带属性的对象:
例如:
let object = { a: 1, b: 2, c: 3 };
我们需要删除'a'。
1。使用显式prop键:
const { a, ...rest } = object;
object = rest;
2。具有可变的prop键:
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 }
答案 22 :(得分:7)
您只需使用delete
关键字删除对象的任何属性。
例如:
var obj = {key1:"val1",key2:"val2",key3:"val3"}
要删除任何属性,例如key1
,请使用delete
关键字,如下所示:
delete obj.key1
或者您也可以使用类似数组的表示法:
delete obj[key1]
参考:MDN。
答案 23 :(得分:6)
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
请注意,我有意在一个循环周期中执行多个“删除”操作,以最大限度地减少其他操作所造成的影响。
答案 24 :(得分:6)
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"];
}
}
);
&#13;
答案 25 :(得分:6)
考虑创建一个没有"regex"
属性的新对象,因为原始对象总是可以被程序的其他部分引用。因此,你应该避免操纵它。
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
const { regex, ...newMyObject } = myObject;
console.log(newMyObject);
答案 26 :(得分:5)
试试这个
delete myObject['key'];
答案 27 :(得分:5)
您好,您可以尝试这种简单的排序
var obj = [];
obj.key1 = {name: "John", room: 1234};
obj.key2 = {name: "Jim", room: 1234};
delete(obj.key1);
答案 28 :(得分:5)
const myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
const { regex, ...other } = myObject;
console.log(myObject)
console.log(regex)
console.log(other)
&#13;
答案 29 :(得分:4)
使用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}
答案 30 :(得分:4)
此页面上提供了许多不同的选项,不是因为大多数选项都是错误的 - 或者因为答案是重复的 - 而是因为适当的技术取决于您所处的情况以及任务的目标你和/或你的团队正在努力实现。要明确地回答你的问题,需要知道:
一旦回答了这四个问题,基本上有四类&#34;属性删除&#34;在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
此类别是最古老,最直接的&amp;最广泛支持的财产清除类别。它支持Symbol
&amp;除了字符串之外的数组索引,除了第一个版本之外,它们适用于每个版本的JavaScript。然而,它的变异违反了某些编程原则并具有性能影响。在non-configurable properties in strict mode上使用时,它也可能导致未捕获的异常。
当需要非变异方法并且您不需要考虑符号键时,此类别用于在较新的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
的功能性来进行部分应用以及{{1}无法实现的其他功能性技术语句。
当需要非变异方法并且您不需要考虑符号键时,此类别用于在较新的ECMAScript风格中操作普通对象或数组实例:
delete
此类别通常允许更大的功能灵活性,包括符号和符号。在一个陈述中省略多个属性:
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 :(
答案 31 :(得分:3)
@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 }
答案 32 :(得分:3)
您可以将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://.*" }
答案 33 :(得分:3)
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)
您也可以使用a2d
将对象像Object.entries
数组那样对待,并像常规数组一样使用splice删除元素,或者像过滤对象一样简单地过滤对象。数组,然后将重建的对象分配回原始变量
答案 34 :(得分:2)
我们可以使用以下方法从javascript对象中删除任何属性:
示例:
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);
输出:
{ ircEvent: 'PRIVMSG', method: 'newURI', regex: '^http://.*' }
=================
{ ircEvent: 'PRIVMSG', method: 'newURI' }
=================
{ ircEvent: 'PRIVMSG' }
答案 35 :(得分:2)
如果您不想修改原始对象。
删除属性而不更改对象
如果需要考虑可变性,则可以通过复制旧属性(要删除的属性除外)来创建一个全新的对象。
> let mname = "Foo" ;;
val mname : string = "Foo"
> let str = $"Select * FROM User Where name = {mname};" ;;
val str : string = "Select * FROM User Where name = Foo;"
答案 36 :(得分:2)
很简单:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
delete myObject.regex;
答案 37 :(得分:1)
对于
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
删除myObject [“regex”]; 你也知道密钥的索引,例如。你需要删除第二个键(正则表达式) 那么
var key = Object.keys(myObject)[2]
delete myObject[key];
很多时候我们要求在对象中删除基于索引但是对象中的记住键可能是上下位置所以请在使用时小心
答案 38 :(得分:1)
function removeProperty(obj, prop) {
if(prop in obj){
Reflect.deleteProperty(obj, prop);
return true;
} else {
return false;
}
}
答案 39 :(得分:1)
您可以使用delete
运算符,如下所示。
var multiverse = {
earth1: "Silver Age",
earth2: "Golden Age"
};
delete multiverse.earth2;//will return true if it finds
// Outputs: { earth1: "Silver Age" }
console.log(multiverse);
删除操作符也有return value.
如果成功删除属性,它将返回true。如果由于属性不可写而无法删除属性,则它将return false
,或者如果处于严格模式,则会抛出错误。
答案 40 :(得分:1)
正如许多人所说,您可以使用“删除”(javascript属性)或“取消设置”(使用lodash)。
您还可以使用lodash属性“ pick”仅选择必要的对象属性。当您从对象中删除多个属性时,这将很有帮助。
用法如下:
var _ = require("lodash");
var obj = {"a":1, "b":2, "c":3};
obj = _.pick(obj,["a","b"]);
//Now obj contains only 2 props {"a":1, "b":2}
答案 41 :(得分:1)
我已经使用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>
var unset = require('lodash.unset');
unset(a,getPathOfKey(a,"price_index.final_price"));
答案 42 :(得分:1)
您可以使用以下过滤器
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
let filter = {}
Object.keys(myObject).filter(d => {
if(d !== 'regex'){
filter[d] = myObject[d];
}
})
console.log(filter)
答案 43 :(得分:1)
删除对象的两种方式
使用for ... in
function deleteUser(key) {
const newUsers = {};
for (const uid in users) {
if (uid !== key) {
newUsers[uid] = users[uid];
}
return newUsers
}
或
delete users[key]
答案 44 :(得分:1)
让我们保持简单,直截了当:
只需将该特定属性/字段设置为 = undefined
var myObject = {
'i': "How are you?",
'am': "Dear",
'fine': "Hello"
};
myObject.am = undefined;
console.log(myObject);
答案 45 :(得分:0)
您可以使用点符号或括号符号
//Bracket notation
//its direct approach when you know the exact value which you want to remove
delete myObject.regex;
//Dot Notation
//its dynamic approach when you don't know which value you want to remove at the point of code
delete myObject['regex'];