我如何从JavaScript对象中移除一个属性?
假设我创建一个对象如下:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
如何删除属性regex
最终以new myObject
结束的最佳方式如下?
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI"
};
喜欢这个:
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);
操作员delete
出乎意料地慢!
看看基准 。
删除是删除对象的属性没有任何剩菜剩下的唯一真正的方法,但它的工作速度比其“替代”,设置object[key] = undefined
慢100倍 。
这个选择不是这个问题的正确答案! 但是,如果你小心使用它,你可以大大加快一些算法。 如果您在循环中使用delete
,并且在性能方面存在问题,请阅读详细解释。
什么时候应该使用delete
,何时将value设置为undefined
?
一个对象可能被看作是一组键值对。 我称之为'价值'是一个原始的或对其他对象的引用,连接到'钥匙'。
当你将结果对象传递给你没有控制权的代码时(或者当你不确定你的团队或你自己时) ,使用delete
。
它从哈希映射中删除密钥 。
var obj = {
field: 1
};
delete obj.field;
如果您关心性能,请使用设置为undefined
。 它可以大大提高你的代码。
关键在于它在hashmap中的位置 ,只有值被替换为undefined
。 明白, for..in
循环仍然会迭代该键。
var obj = {
field: 1
};
obj.field = undefined;
使用这种方法,并不是所有确定财产存在的方式都能按预期工作。
但是,这个代码:
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]
从obj
删除prop
并从内存中删除它,而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;
将导致大量的内存泄漏,因为每个动画帧。 每个帧中,所有65536个DOM元素将占用另外65536个单独的插槽,但之前的65536个插槽仅设置为未定义,这会使它们挂在内存中。 继续,尝试在控制台上运行上面的代码并亲自查看。 在强制出现内存不足错误之后,尝试再次运行它,除非使用以下版本的使用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 );
});
如上面的代码片段所示,对于delete
操作符有一些罕见的合适用例。 但是,不要太担心这个问题。 这只会成为长寿命对象的问题,这些对象会不断添加新键。 在任何其他情况下(这几乎是现实世界编程中的每种情况),使用obj[prop] = undefined
是最合适的。 本节的主要目的只是为了引起您的注意,以至于在您的代码中这确实成为问题的罕见机会,那么您可以更轻松地理解问题,因此不必浪费时间解析代码以定位并理解这个问题。
不要总是设置为undefined
重要的是要考虑Javascript的一个方面是多态性。 多态性是指定相同变量/槽中对象的不同类型,如下所示。
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
但是,多态数组有两个主要的不可修复问题:
人们可以将多态性比喻为吸毒成瘾。 乍一看,它看起来非常有利可图:漂亮的漂亮蓬松的代码。 然后,编码人员将他们的数组引入多态性药物。 瞬间,多态阵列变得效率较低,并且因为它被麻醉,它永远不会像以前那样高效。 为了将这种情况与现实生活联系起来,可卡因上的某个人甚至可能无法操作简单的门把手,更不用说能够计算出PI的数字。 同样,多态性药物的阵列不可能像单形阵列一样有效。
但是,药物旅行类似于delete
操作如何? 答案包含了上面代码片段中的最后一行代码。 因此,让它重新审视,这次是一个转折。
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
观察。 bar[1] = ""
不强制多态,而bar[1] = undefined
。 因此,应尽可能使用相应类型的对象,以免意外引起多态性。 一个这样的人可以使用下面的列表作为通用参考来让他们走。 但是,请不要明确地使用下面的想法。 相反,请使用适合您的代码的任何方法。
false
或undefined
作为空值。 虽然避免不必要的多态性是好事,但重写所有代码以显式禁止它可能会导致性能下降。 使用常见的判断! 0
作为空值。 请注意,内部有两种类型的数字:快速整数(包括2147483647到-2147483648)和慢浮点双精度(包括NaN
和Infinity
在内的任何其他类型)。 当一个整数降级到double时,它不能被提升回一个整数。 ""
作为空值。 null
。 但是,请注意! 现在不要突然开始使用所有现有的代码,因为它可能会破坏以前存在的代码和/或引入奇怪的错误。 相反,从一开始就需要实施这样一种有效的做法,并且在转换已有的代码时,建议您将与之相关的所有行都加倍,三倍,四倍检查,因为试图将旧代码升级到这种新的做法可能是因为它是有价值的。
var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
delete myJSONObject.regex;
console.log ( myJSONObject.regex); // logs: undefined
链接地址: http://www.djcxy.com/p/27221.html