How do I remove a property from a JavaScript object?
Say I create an object as follows:
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
What is the best way to remove the property regex
to end up with new myObject
as follows?
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI"
};
Like this:
delete myObject.regex;
// or,
delete myObject['regex'];
// or,
var prop = "regex";
delete myObject[prop];
Demo
var myObject = {
"ircEvent": "PRIVMSG",
"method": "newURI",
"regex": "^http://.*"
};
delete myObject.regex;
console.log(myObject);
Operator delete
is unexpectedly slow!
Look at the benchmark .
Delete is the only true way to remove object's properties without any leftovers, but it works ~ 100 times slower , compared to its "alternative", setting object[key] = undefined
.
This alternative is not the correct answer to this question! But, if you use it with care, you can dramatically speed up some algorithms. If you are using delete
in loops and you have problems with performance, read the verbose explanation.
When should one use delete
and when set value to undefined
?
An object may be seen as a set of key-value pairs. What I call a 'value' is a primitive or a reference to other object, connected to that 'key'.
Use delete
, when you are passing the result object to the code on which you don't have control (or when you are not sure about your team or yourself).
It deletes the key from the hashmap .
var obj = {
field: 1
};
delete obj.field;
Use setting to undefined
, when you care about performance. It can give a serious boost to your code.
The key remains on its place in the hashmap , only the value is replaced with undefined
. Understand, that for..in
loop will still iterate over that key.
var obj = {
field: 1
};
obj.field = undefined;
Using this method, not all ways of determining property existence will work as expected.
However, this code:
object.field === undefined
will behave equivalently for both methods.
Tests
To summarize, differences are all about ways of determining the property existence, and about for..in
loop.
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. *');
Beware Of Memory Leaks!
While using obj[prop] = undefined
is faster than doing delete obj[prop]
, another important consideration is that obj[prop] = undefined
may not always be appropriate. delete obj[prop]
removes prop
from obj
and erases it from memory whereas obj[prop] = undefined
simply sets the value of prop
to undefined
which leaves prop
still in memory. Therefore, in circumstances where there are many keys being created and deleted, using obj[prop] = undefined
can force expensive memory reconciliation (causing the page to freeze up) and potentially an out-of-memory error. Examine the following code.
"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 );
});
In the code above, simply doing nodeRecords[i][lastTime] = undefined;
will cause a massive memory leak because each animation frame. Each frame, all 65536 DOM elements will take up another 65536 individual slots, but the previous 65536 slots will only be set to undefined which leaves them hanging in the memory. Go ahead, try to run the above code in the console and see for yourself. After forcing an out-of-memory error, attempt to run it again except with the following version of the code that uses the delete
operator instead.
"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 );
});
As seen in the above code snippet, there are some rare appropriate use cases for the delete
operator. However, do not worry about this problem too much. This will only become a problem with long-lifespan objects that get new keys constantly added to them. In any other case (which is almost every case in real-world programming), it is most appropriate to use obj[prop] = undefined
. The main purpose of this section is just to bring this to your attention so that in the rare chance that this does become a problem in your code, then you can more easily understand the problem and thus not have to waste hours dissecting your code to locate and understand this problem.
Do Not Always Set To undefined
One aspect of Javascript that is important to consider is polymorphism. Polymorphism is when assigning the same variable/slot-in-an-object different types as seen below.
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
However, there are two major unfixable problems with polymorphic arrays:
One may liken polymorphism to a drug addiction. At first glance, it seems awesomely lucrative: nice pretty fluffy code. Then, the coder introduces their array to the drug of polymorphism. Instantly, the polymorphic array becomes less efficient, and it can never become as efficient as it was before since it is drugged. To correlate such circumstance to real life, someone on cocaine might not even be capable of operating a simple door handle, much less be able to calculate digits of PI. Likewise, an array on the drug of polymorphism cannot ever be as efficient as a monomorphic array.
But, how does a drug trip analogy relate to the delete
operation? The answer inheres the last line of code in the snippet above. Thus let it be reexamined, this time with a twist.
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
Observe. bar[1] = ""
does not coerce polymorphism whereas bar[1] = undefined
does. Therefore, one should always, whenever possible use the corresponding type for their objects so as to not accidentally cause polymorphism. One such person may use the following list as a general reference to get them going. However, please do not explicitly use the below ideas. Instead, use whatever works well for your code.
false
or undefined
as the empty value. While avoiding unnecessary polymorphism is good, rewriting all your code to explicitly forbid it will likely actually result in a decrease in performance. Use common judgement! 0
as the empty value. Note that internally, there are two types of numbers: fast integers (2147483647 to -2147483648 inclusive) and slow floating point doubles (anything other than that including NaN
and Infinity
). When an integer is demoted to a double, it cannot be promoted back to an integer. ""
as the empty value. null
. However, be mindful! Do not suddenly start doing this with all your preexisting code now as it would likely break such preexisting code and/or introduce strange bugs. Rather, such an efficient practice needs to be implemented from the start, and when converting preexisting code, it is recommended that you double, triple, quadruple check all the lines relating to that as trying to upgrade old code to this new practice can be as risky as it is rewarding.
var myJSONObject = {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};
delete myJSONObject.regex;
console.log ( myJSONObject.regex); // logs: undefined
链接地址: http://www.djcxy.com/p/27222.html
上一篇: 如何取消设置JavaScript变量?