40

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).

nicael
  • 18,550
  • 13
  • 57
  • 90
Claudiu
  • 224,032
  • 165
  • 485
  • 680

7 Answers7

70

A slightly simpler way than your method is to use the Javascript in operator

alert('x' in o); // true
alert('x' in t); // false
Greg
  • 316,276
  • 54
  • 369
  • 333
  • 2
    Is the `in` keyword in an ECMAScript standard? It's implemented in Gecko and Webkit, but I don't know whether one can always rely on it being present. – kpozin Jan 14 '11 at 20:43
  • 1
    @kpozin You can safely use `in`. See this question: http://stackoverflow.com/questions/2920765/javascript-in-operator-compatibility – chiborg Mar 13 '12 at 10:11
8

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.

Community
  • 1
  • 1
some
  • 48,070
  • 14
  • 77
  • 93
4

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;

annakata
  • 74,572
  • 17
  • 113
  • 180
  • 1
    ah, very intersting. one note, however - setting it to "UnDeFiNed" will cause a compile-time error, as that variable is not defined. setting it to "Object.randomStringinserthereplease" acts the way you say it will. – Claudiu Dec 22 '08 at 11:30
  • 1
    you mean run-time, no such thing as compile with JS - but you're right, my description assumes scope. The problem arises because undefined can be treated as a constant in many situations and has been supported by some browsers, but it's *not* a constant and it isn't safe – annakata Dec 22 '08 at 11:47
  • If you want to know if something is undefined regardless of someone has changed the value of undefined: typeof x === "undefined" – some Dec 22 '08 at 16:14
  • 2
    @annakata: undefined is a primitive value, see section 4.3.9 of the ECMAScript specification. You are wrong when you say "you are assigning it the value of the symbol undefined which you haven't defined" (cont) – some Dec 22 '08 at 16:57
  • 3
    @annakata: However, you are right that it isn't a constant and that it will give unexpected behavior if undefined is defined to something else. So will this: eval=function(){alert("eval not supported anymore");} – some Dec 22 '08 at 16:59
  • ^^ don't hire any dev that writes "var undefined = true" in their javascript. – Josh Mc Feb 17 '15 at 02:00
1

Something like this?

function isDefined(var){
   return (typeof(window[var]) == 'undefined') ? false : true;
}

or..

function isDefined(var){
   return (window.var === undefined) ? false : true;
}
adam
  • 22,404
  • 20
  • 87
  • 119
1

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
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
  • Setting it to the primitive value undefined don't delete the property, but you loose the reference to whatever the property contained. It has nothing to do with garbage collection not taken effect. – some Dec 22 '08 at 11:20
0

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?

Claudiu
  • 224,032
  • 165
  • 485
  • 680
  • 1
    "contains" ? Thats not ECMAScript. Even if it was, your solution is way to slow and uses more resources than needed. Use "x in y" like it says in the other answers. – some Dec 22 '08 at 16:07
  • i know, i forgot ECMAScript had an 'in' operator =P. – Claudiu Dec 22 '08 at 19:41
0

You could try putting a watch on One.x but that would only tell you at the time it gets undefined.

nickf
  • 537,072
  • 198
  • 649
  • 721