2

I was reading some code for a js library and I saw this:

// make sure undefined is undefined
var undefined;

I have looked up the proper way to check for undefined things in javascript a few times before and found posts such as:

Is that piece of code a good thing to add on or is it unnecessary or something in the middle?

Community
  • 1
  • 1
gloomy.penguin
  • 5,833
  • 6
  • 33
  • 59
  • No, this piece of code is not good, it's actually pretty _horrible_. No one really ever overrides the value of `undefined` to something else. You don't have to chase your own tail like this. – Benjamin Gruenbaum Aug 27 '13 at 20:57
  • okay. why _horrible_ and not just unnecessary? (ohh, you edited and kinda answered that already) – gloomy.penguin Aug 27 '13 at 20:59
  • For the same reason we don't check if anything else has been changed (Like `Function.prototype.call` or `Array.prototype.push`) – Benjamin Gruenbaum Aug 27 '13 at 21:01

3 Answers3

3

In javascript, undefined is a valid variable name.

In libraries, it is common to see authors redefine undefined to undefined to make sure they don't break. But the risk is pretty slight, few people overwrite undefined for obvious reasons!

The rationnale behind this is:

var a;
console.log( a === undefined );

Usually, you'll see this form way more frequently:

(function( undefined ) {

}());
Simon Boudrias
  • 42,953
  • 16
  • 99
  • 134
  • More fun testing: `var a; console.log(a === window.undefined, typeof a === "undefined");` – Fabrício Matté Aug 27 '13 at 21:00
  • 2
    @gloomy.penguin You _really don't have to actually do this_ in real code. I've not seen a single code base where someone, even by accident redefined the global property `undefined`. Even in the most horrible code bases I've seen. – Benjamin Gruenbaum Aug 27 '13 at 21:05
  • I agree with @BenjaminGruenbaum here. – Simon Boudrias Aug 27 '13 at 21:06
  • Okay. I have never seen it before and just instantly thought "oh, well that's an interesting way of doing things..." and then since I saw it in a library (and I always assume authors of widely used libraries n such are geniuses), I figured I should ask SO about it. It made sense but I didn't think anyone would actually use `undefined` as anything but what it should be used as... Thanks for the info. – gloomy.penguin Aug 27 '13 at 21:12
1

That doesn't help at all. If undefined has been assigned a different value (which is only possible in older versions of Javascript), then that line won't change that fact. You could use this:

var a;

;(function(undefined){

   // Here undefined is definitely undefined, 
   // so it is safe to test for undefined using ===:
   if(a === undefined){
     console.log('a is undefined!');
   }

})();
Paul
  • 139,544
  • 27
  • 275
  • 264
  • You're mixing the _value_ undefined which is a primitive value in the JS language and the _property_ undefined of the global host object (most commonly `window`). You can't (and never could) override the _value_ type undefined (just like you can't override the number 3) – Benjamin Gruenbaum Aug 27 '13 at 21:00
  • @BenjaminGruenbaum In older browsers, you could. It's ES5 that says `undefined` is not writable; in ES3, it was possible to override the global value. – bfavaretto Aug 27 '13 at 21:00
  • @BenjaminGruenbaum You could override the property of window though, which would break comparisons to it. That's why you see so much `typeof x == 'undefined'` in older code. – Paul Aug 27 '13 at 21:02
  • @bfavaretto no you couldn't, the value and the property are two different things. The property is just a property of the host object containing the value (Like window.NaN or window.Infinity) – Benjamin Gruenbaum Aug 27 '13 at 21:02
  • @Paulpro No. You see so much of `typeof x === "undefined"` because of how the reference resolution algorithm works. If you type `x === undefined` in your console you'll get a reference error, `typeof` is an operator and does not raise a reference error when called on an undefined reference. – Benjamin Gruenbaum Aug 27 '13 at 21:03
  • @BenjaminGruenbaum I never said you could override the value of `undefined` itself, just the property. – Paul Aug 27 '13 at 21:05
  • @BenjaminGruenbaum As long as the var has been declared you can compare it to undefined: `(function(a,b,c){ return c === undefined; })(1,2);` – Paul Aug 27 '13 at 21:06
  • @BenjaminGruenbaum AFAIK, the value is never available directly, so when you do `something == undefined`, you're comparing to the value in the global property. And that could be overwritten. See http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.1 – bfavaretto Aug 27 '13 at 21:07
  • @Paulpro C is not an undefined reference here, it's an argument without a passed value, that's a completely different section in the spec. As for the value, you did say it but you've edited your answer later on. – Benjamin Gruenbaum Aug 27 '13 at 21:07
  • @BenjaminGruenbaum No I haven't, the only edit I've made was to add `var a;` to make it more clear that `a` must be declared. I never modified my wording. – Paul Aug 27 '13 at 21:08
  • @bfavaretto The value is not available directly, but the global property's value can also not be overwritten as it is not writable - while we're into specs (ftw! :)) http://es5.github.io/#x15.1.1.3 – Benjamin Gruenbaum Aug 27 '13 at 21:09
  • @BenjaminGruenbaum The global property *was* writable in ES3, which lead to people abusing that, and other people creating guards against that (as we see in this question and answers), until ES5 finally ended the insanity with `[[Writable]]: false`. That's my point here. – bfavaretto Aug 27 '13 at 21:12
1

The bad thing about JS is that you can actually declare a variable named 'undefined'.

If you want to be extra safe and be 100% sure undefined is actually what you expect, you can always check for undefined in a different way - by using void (here is a MDN doc):

// if a is undefined
if (a === void 1) {
}

// where: void 1 === *real* undefined
kamituel
  • 34,606
  • 6
  • 81
  • 98
  • 1
    No, you can't override the value of `undefined` in modern versions of JavaScript, that's stated perfectly fine in the language specification. – Benjamin Gruenbaum Aug 27 '13 at 21:01
  • @BenjaminGruenbaum - what I meant is declaring a variable named `undefined`. Like this: `var undefined = 'some non-undefined value'; var a; console.log(a=== undefined);` prints false. – kamituel Aug 27 '13 at 21:04
  • That's not overriding the value of undefined, that's hiding the global property undefined. It _is_ strange that it's not a literal like `null`. – Benjamin Gruenbaum Aug 27 '13 at 21:04
  • @kamituel That does not work in the global scope though (as said in Benjamin's 1st comment), where most libraries are run. – Fabrício Matté Aug 27 '13 at 21:05
  • 1
    @BenjaminGruenbaum - true, I've clarified my answer to avoid confusion. Thanks! – kamituel Aug 27 '13 at 21:06
  • @FabrícioMatté - if you mean the code I posted in the comment wont work in global scope, I think it would - at least in node.js/v8. – kamituel Aug 27 '13 at 21:07
  • @kamituel Node is a different case I believe, as each file has its own scope. Chrome/V8 and Firefox does return `true` for your posted code when executed in the global scope. (`undefined` is still `undefined`) – Fabrício Matté Aug 27 '13 at 21:09
  • 1
    @FabrícioMatté - I just checked, indeed you're right ;) I wasn't aware of that difference. Thanks! – kamituel Aug 27 '13 at 21:11