Reputation: 48476
Is there any substantial difference in doing either of these?
delete a.x;
vs
a.x = undefined;
where
a = {
x: 'boo'
};
could it be said that they are equivalent?
(I'm not taking into account stuff like "V8 likes not using delete
better")
Upvotes: 207
Views: 34848
Reputation: 92274
They are not equivalent. The main difference is that setting
a.x = undefined
means that a.hasOwnProperty("x")
will still return true, and therefore, it will still show up in a for in
loop, and in Object.keys()
. Whereas
delete a.x
means that a.hasOwnProperty("x")
will return false
You can't tell if a property exists by testing
if (a.x === undefined)
If you are trying to determine if a property exists, you should always use
// If you want inherited properties
if ('x' in a)
// If you don't want inherited properties
if (a.hasOwnProperty('x'))
Following the prototype chain (mentioned by zzzzBov) Calling delete
will allow it to go up the prototype chain, whereas setting the value to undefined will not look for the property in the chained prototypes
var obj = {
x: "fromPrototype"
};
var extended = Object.create(obj);
extended.x = "overriding";
console.log(extended.x); // overriding
extended.x = undefined;
console.log(extended.x); // undefined
delete extended.x;
console.log(extended.x); // fromPrototype
Deleting Inherited Properties If the property you are trying to delete is inherited, delete
will not affect it. That is, delete
only deletes properties from the object itself, not inherited properties.
var obj = {x: "fromPrototype"};
var extended = Object.create(obj);
delete extended.x;
console.log(extended.x); // Still fromPrototype
Therefore, if you need to make sure an object's value will be undefined, delete
will not work when the property is inherited, you will have to set (override) it to undefined
in that case. Unless the place that is checking for it will use hasOwnProperty
, but it likely wouldn't be safe to assume that everywhere that checks it will use hasOwnProperty
Upvotes: 243
Reputation: 11364
Using an array, instead of an object, I can showcase that delete uses less heap memory than undefined.
For example, this code will not finish:
let y = 1;
let ary = [];
console.log("Fatal Error Coming Soon");
while (y < 4294967295)
{
ary.push(y);
ary[y] = undefined;
y += 1;
}
console(ary.length);
It produces this error:
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory.
So, as you can see undefined
actually takes up heap memory.
However, if you also delete
the ary-item (instead of just setting it to undefined
), the code will slowly finish:
let x = 1;
let ary = [];
console.log("This will take a while, but it will eventually finish successfully.");
while (x < 4294967295)
{
ary.push(x);
ary[x] = undefined;
delete ary[x];
x += 1;
}
console.log(`Success, array-length: ${ary.length}.`);
These are extreme examples, but they make a point about delete
that I haven't seen anyone mention anywhere.
Upvotes: 4
Reputation: 1288
If a.x
is a setter function, a.x = undefined
will call the function whereas delete a.x
will not call the function.
Upvotes: 8
Reputation: 7688
Object is simply a tree representation, that means, in memory the root points to various memory locations where keys of that object are stored. and that location points to another location where the actual value of that key is stored, or locations where the child keys are stored or locations where the array values are stored.
When you delete any key from an object using delete, actually it deletes link between that key and its parent object and the memory locations of key and its value are freed up to store another information.
When you try to delete any key by setting undefined as its value, then you are just setting its value, not deleting that key. That means that keys memory location is still linked with its parent object and the value if key is undefined.
Using undefined instead of using delete keyword is a bad practice, as it doesn't release memory location of that key.
Even if the key is not present, and you set it as undefined, then that key will get created with value undefined
.
e.g.
var a = {};
a.d = undefined;
console.log(a); // this will print { d: undefined }
delete can't be worked with inherited properties because that property is not the part of that child object.
Upvotes: 1
Reputation: 8767
I'm sure you can see the difference between var o1 = {p:undefined};
and var o2 = {};
.
In both cases, o.p
will be undefined
but in the first case, it's because that's the value and in the second case because there is no value.
delete
is the operator that lets you get from o1
(or another object that has a value assigned to its p
property) to o2
that way: delete o1.p;
.
The reverse operation is made by simply assigning a value (undefined
in this example but it could be something else) to the property o1.p = undefined;
.
So no, they are not equivalent.
delete o.p;
will
remove the property p
from the object if it has one
do nothing otherwise
o.p = undefined;
will
add a property p
to the object if it doesn't have one yet and set its value to undefined
simply change the value of the property if the object already has it
From a performance perspective, delete
is bad because it modifies the structure of the object (just like adding a new property if you haven't initialized it in the constructor).
Whereas setting the value to undefined
releases the content as well but without forcing to modify the structure.
Upvotes: 1
Reputation:
Yes there is a difference.
If you use delete a.x
the x isn't any more a property of a, but if you use a.x=undefined
it is a property but its value is undefined.
Upvotes: 3
Reputation: 179046
To paraphrase the question:
Are
delete a.x
anda.x = undefined
equivalent?
The former removes the key from the variable, the later sets the key with a value of undefined
. This makes a difference when iterating over properties of objects, and when hasOwnProperty
is used.
a = {
x: true
};
a.x = undefined;
a.hasOwnProperty('x'); //true
delete a.x;
a.hasOwnProperty('x'); //false
Additionally, this will make a significant difference when the prototype chain is involved.
function Foo() {
this.x = 'instance';
}
Foo.prototype = {
x: 'prototype'
};
a = new Foo();
console.log(a.x); //'instance'
a.x = undefined;
console.log(a.x); //undefined
delete a.x;
console.log(a.x); //'prototype'
Upvotes: 38
Reputation: 298146
The names are a little confusing. a.x = undefined
just sets the property to undefined
, but the property is still there:
> var a = {x: 3};
> a.x = undefined;
> a.constructor.keys(a)
["x"]
delete
actually deletes it:
> var a = {x: 3};
> delete a.x;
> a.constructor.keys(a)
[]
Upvotes: 2
Reputation: 77089
This REPL from node should illustrate the difference.
> a={ x: 'foo' };
{ x: 'foo' }
> for (var i in a) { console.log(i); };
x
undefined
> a.x=undefined;
undefined
> for (var i in a) { console.log(i); };
x
undefined
> delete a.x;
true
> for (var i in a) { console.log(i); };
undefined
Upvotes: 1