JavaScript - Identify whether a property is defined and set to 'undefined', or undefined
-
23-08-2019 - |
Question
Say I have the following code:
function One() {}
One.prototype.x = undefined;
function Two() {}
var o = new One();
var t = new Two();
o.x
and t.x
will both evaluate to undefined
. o.hasOwnProperty('x')
and t.hasOwnProperty('x')
will both return false; the same goes for propertyIsEnumerable
. Two questions:
- Is there any way to tell that o.x is defined and set to
undefined
? - Is there ever any reason to? (should the two be semantically equivalent?)
A small caveat: doing (for propName in o) loop will yield 'x' as one of the strings, while doing it in t will not - so there IS a difference in how they're represented internally (at least in Chrome).
Solution
A slightly simpler way than your method is to use the Javascript in operator
alert('x' in o); // true
alert('x' in t); // false
OTHER TIPS
object.hasOwnProperty(name) only returns true for objects that are in the same object, and false for everything else, including properties in the prototype.
function x() {
this.another=undefined;
};
x.prototype.something=1;
x.prototype.nothing=undefined;
y = new x;
y.hasOwnProperty("something"); //false
y.hasOwnProperty("nothing"); //false
y.hasOwnProperty("another"); //true
"someting" in y; //true
"another" in y; //true
Additionally the only way do delete a property is to use delete. Setting it to undefined do NOT delete it.
The proper way to do it is to use in like roborg said.
Update: undefined is a primitive value, see ECMAScript Language Specification section 4.3.2 and 4.3.9.
Ach, one for the anti-patterns thread there.
undefined
is not a keyword.
When you assign write var foo = undefined;
you are assigning it the value of the symbol undefined
which you haven't defined and hence the value you'll get is "undefined"
. You would produce exactly the same result if you had assigned it UnDeFiNeD
or NotFineAtAll
or _qwertyuiop
Why is this so terrible? Well apart from the fact that it leads to a false understanding of what's going on, what happens if you happen to load a library or hire a dev who writes var undefined = true;
Something like this?
function isDefined(var){
return (typeof(window[var]) == 'undefined') ? false : true;
}
or..
function isDefined(var){
return (window.var === undefined) ? false : true;
}
No. I don't think a variable equal to undefined
should be recognized as "defined".
Setting it equal to undefined
directly is just a lazy way of deleting it -- as apposed to using the delete
keyword. I believe this just means that garbage collection hasn't taken affect on the variable/property.
[EDIT]
Regarding your comment about hasOwnProperty
and propertyIsEnumerable
, prototype methods/properties are neither the object's own nor enumerable.
Object.prototype.foo = 'something';
var o = {bar: 'anything'};
o.hasOwnProperty('foo'); //=> false
o.hasOwnProperty('bar'); //=> true
Object.prototype.hasOwnProperty('foo'); //=> true
One way to do it is this:
var definedProperties = [];
for (var prop in o) definedProperties.push(prop);
if (o.x === undefined && contains(prop, 'x')) {
//x is defined, but set to undefined
}
where contains
just checks whether any element in the array is 'x'
. Is this the only way?
You could try putting a watch on One.x but that would only tell you at the time it gets undefined.