69

NOTE: As per ECMAScript5.1, section 15.1.1.3, window.undefined is read-only.

  • Modern browsers implement this correctly. for example: Safari 5.1, Firefox 7, Chrome 20, etc.
  • Undefined is still changeable in: Chrome 14, ...

When I recently integrated Facebook Connect with Tersus, I initially received the error messages Invalid Enumeration Value and Handler already exists when trying to call Facebook API functions.

It turned out that the cause of the problem was

object.x === undefined

returning false when there is no property 'x' in 'object'.

I worked around the problem by replacing strict equality with regular equality in two Facebook functions:

FB.Sys.isUndefined = function(o) { return o == undefined;};
FB.Sys.containsKey = function(d, key) { return d[key] != undefined;};

This made things work for me, but seems to hint at some sort of collision between Facebook's JavaScript code and my own.

What could cause this?

Hint: It is well documented that undefined == null while undefined !== null. This is not the issue here. The question is how comes we get undefined !== undefined.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Youval Bronicki
  • 1,922
  • 2
  • 18
  • 18
  • 5
    Interesting, I just tried in my console. `var a = {}; a.b === undefined //true`. Are you sure your `object.x === undefined` returning false was because there was no field x in object? – Grace Huang Sep 26 '11 at 21:00
  • 1
    " As per ECMAScript5.1, section 15.1.1.3, window.undefined is read-only." - Horray, because in previous version someone could overwrite `undefined` globally, and everything would break :( – Dan Jun 04 '13 at 09:01
  • Prior to `window.undefined` being read-only, `void(0)` was considered the standard extra-safe way to get your hands on the undefined value if you didn't want to trust you're environment's `undefined` variable. [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void) – snarf Jan 03 '20 at 03:21

7 Answers7

92

The problem is that undefined compared to null using == gives true. The common check for undefined is therefore done like this:

typeof x == "undefined"

this ensures the type of the variable is really undefined.

Wolfram Kriesing
  • 1,527
  • 10
  • 7
  • 61
    The biggest misconception in many of the answers here is that 'undefined' is a Javascript keyword. It's not a keyword at all, but a variable that (most of the time) happens to be undefined. So the only time "somevar === undefined" works is when the 'undefined' variable really hasn't been defined. I've seen code (jcanvas) where the class-wrapping function includes a last argument named 'undefined' (which is never used) just to ensure there will be an undefined variable named 'undefined' within the function scope. Apart from special situations like that, using 'typeof' is the only "right" way. – Scott Lahteine May 28 '11 at 06:03
  • 2
    Does it mean, that in place of undefined I could also use garglblarg as long as it never gets defined? – Dercsár Jun 10 '11 at 13:02
  • 1
    @Dercsár: Yes, `var foo; foo === undefined // true`. – pimvdb Aug 15 '11 at 09:44
  • 3
    Actually, that's not true. `undefined` is not a keyword, but it's a built-in in JavaScript. Referencing something that's actually undefined raises a `ReferenceError: whatever is not defined`. – fletom Feb 22 '12 at 06:19
  • @nomulous: Sorry for nitpicking but that's for *undeclared* variables. `var foo;` is declared but left undefined - which does not cause a `ReferenceError`. – pimvdb Jul 07 '12 at 19:44
  • Yes, by "undefined" I mean also undeclared. Thanks for the clarification. – fletom Jul 24 '12 at 16:35
  • 1
    Could someone explain why myVar === undefined raises ReferenceError, and this.myVar === undefined doesn't (simply returns true)? P. S. myVar has never been defined. – MaksymB Jan 22 '13 at 11:39
  • @Maxym You can see the ECMAScript definition for why [here](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6.2). As for the reason why they would do it this way, because doing so otherwise in a weakly typed language makes it rather difficult to work with objects without explicitly following their type everywhere. – Chris Hayes Jan 06 '14 at 20:55
  • 1
    I prefered `typeof x === "undefined"` if you compare as string EXACTLY match, because `==` can thrown error or not parse on some browser due compare of type variable `x`. – Marin Sagovac Jul 30 '14 at 09:18
64

It turns out that you can set window.undefined to whatever you want, and so get object.x !== undefined when object.x is the real undefined. In my case I inadvertently set undefined to null.

The easiest way to see this happen is:

window.undefined = null;
alert(window.xyzw === undefined); // shows false

Of course, this is not likely to happen. In my case the bug was a little more subtle, and was equivalent to the following scenario.

var n = window.someName; // someName expected to be set but is actually undefined
window[n]=null; // I thought I was clearing the old value but was actually changing window.undefined to null
alert(window.xyzw === undefined); // shows false
Youval Bronicki
  • 1,922
  • 2
  • 18
  • 18
  • 18
    Ah ha! And *this* is the major reason why I'm against using the undefined property (as opposed to using typeof). Congrats on working through the bug. +1 – annakata Apr 26 '09 at 19:29
  • 2
    Another reason to always namespace your objects... var n = blah.someName; blah[n]=null; would have kept you from ever getting that error... – cmcculloh Feb 24 '11 at 15:43
  • 2
    It could not be overwritten in modern browsers though – Memke Apr 08 '17 at 08:53
19

I'd like to post some important information about undefined, which beginners might not know.

Look at the following code:

 /* 
  * Consider there is no code above. 
  * The browser runs these lines only.
  */

   // var a;  
   // --- commented out to point that we've forgotten to declare `a` variable 

   if ( a === undefined ) {
       alert('Not defined');
   } else {
       alert('Defined: ' + a);
   }

   alert('Doing important job below');

If you run this code, where variable a HAS NEVER BEEN DECLARED using var, you will get an ERROR EXCEPTION and surprisingly see no alerts at all.

Instead of 'Doing important job below', your script will TERMINATE UNEXPECTEDLY, throwing unhandled exception on the very first line.


Here is the only bulletproof way to check for undefined using typeof keyword, which was designed just for such purpose:

   /* 
    * Correct and safe way of checking for `undefined`: 
    */

   if ( typeof a === 'undefined' ) {
       alert(
           'The variable is not declared in this scope, \n' +
           'or you are pointing to unexisting property, \n' +
           'or no value has been set yet to the variable, \n' + 
           'or the value set was `undefined`. \n' +
           '(two last cases are equivalent, don\'t worry if it blows out your mind.'
           );
   }

   /* 
    *  Use `typeof` for checking things like that
    */

This method works in all possible cases.

The last argument to use it is that undefined can be potentially overwritten in earlier versions of Javascript:

     /* @ Trollface @ */
        undefined = 2;
     /* Happy debuging! */  

Hope I was clear enough.

Dan
  • 55,715
  • 40
  • 116
  • 154
  • `function xx(a) { if(a === undefined)a='default'; } xx()` - this is a good way for arranging default arguments in javascript – Dan Jul 02 '11 at 17:47
14

That's a bad practice to use the == equality operator instead of ===.

undefined === undefined // true
null == undefined // true
null === undefined // false

The object.x === undefined should return true if x is unknown property.

In chapter Bad Parts of JavaScript: The Good Parts, Crockford writes the following:

If you attempt to extract a value from an object, and if the object does not have a member with that name, it returns the undefined value instead.

In addition to undefined, JavaScript has a similar value called null. They are so similar that == thinks they are equal. That confuses some programmers into thinking that they are interchangeable, leading to code like

value = myObject[name];
if (value == null) {
    alert(name + ' not found.');
}

It is comparing the wrong value with the wrong operator. This code works because it contains two errors that cancel each other out. That is a crazy way to program. It is better written like this:

value = myObject[name];
if (value === undefined) {
    alert(name + ' not found.');
}
Jason Whitehorn
  • 13,585
  • 9
  • 54
  • 68
viam0Zah
  • 25,949
  • 8
  • 77
  • 100
  • Have you EVER read this wonderful piece: http://webreflection.blogspot.ie/2010/10/javascript-coercion-demystified.html? – op1ekun Oct 27 '13 at 10:37
  • 1
    `(value == null)` can often be a perfectly sane and valid comparison. How often do you actually *want* to differentiate between what's not defined and what's explicitly null? It rarely matters *why* there is no value. – snarf Jan 03 '20 at 03:53
11

From - JQuery_Core_Style_Guidelines

  • Global Variables:
    typeof variable === "undefined"

  • Local Variables:
    variable === undefined

  • Properties:
    object.prop === undefined

Dinuka Thilanga
  • 4,220
  • 10
  • 56
  • 93
  • 1
    Just a note - if a variable does not exist at all, then it is not local nor global. What's not so intuitive is that we should check those potentially non-existent variables the same way as we check global variables, as Dan showed us in his example. – JustAMartin Jan 20 '14 at 12:11
4
var a;

typeof a === 'undefined'; // true
a === undefined; // true
typeof a === typeof undefined; // true
typeof a === typeof sdfuwehflj; // true
jbyrd
  • 5,287
  • 7
  • 52
  • 86
2

A). I never have and never will trust any tool which purports to produce code without the user coding, which goes double where it's a graphical tool.

B). I've never had any problem with this with Facebook Connect. It's all still plain old JavaScript code running in a browser and undefined===undefined wherever you are.

In short, you need to provide evidence that your object.x really really was undefined and not null or otherwise, because I believe it is impossible for what you're describing to actually be the case - no offence :) - I'd put money on the problem existing in the Tersus code.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
annakata
  • 74,572
  • 17
  • 113
  • 180