7

In John Resig's slideshow on how he was building jQuery 1.4, he mentioned a point where he added an undefined variable to the jQuery closure because "we can re-use (the variable)".

undefined is not an ordinary variable:

> var undefined = 4
  undefined
> undefined
  undefined

Therefore, we know that undefined is not a variable. So why would an undefined be re-undefined in the jQuery source?

Slide 31

Brian
  • 7,394
  • 3
  • 25
  • 46

2 Answers2

10

Because in some JavaScript engines it's possible to set undefined to a value. This is to make sure undefined is really undefined.

gen_Eric
  • 223,194
  • 41
  • 299
  • 337
  • 4
    I'd suggest against protecting like that. It's just dumb. If people are stupid enough to redefine `undefined`, they deserve what'll happen. – Ven Jul 25 '13 at 14:27
  • 2
    @user1737909: Fair enough, but what if it was a malicious script :O – gen_Eric Jul 25 '13 at 14:28
  • 1
    @user1737909 there are contexts involving scripts from multiple sources (think about a "magazine" ad-supported site), and so one may want to protect one's own code from other people's stupidity (or malice). – Pointy Jul 25 '13 at 14:28
  • 3
    Doesn't matter. What if somebody redefined `prototype`? You'd be doomed the same way, and you can't protect against everything. Just protecting against undefined will at most make you feel safer. – Ven Jul 25 '13 at 14:28
  • 2
    @user1737909 Although I agree, I don't think you could build a javascript library and not add in some fail safes to protect against unwanted errors, however dumb they may be. – Mark Walters Jul 25 '13 at 14:31
  • Yeah, in the case of jQuery, it's probably better anyway for minifiers (even if you should gzip). I'm just adding a general note because I don't think most of us will deal with problems jQuery has to deal with. (then we talk about null, "is a javascript value a `Maybe Maybe T`?"; etc) – Ven Jul 25 '13 at 14:33
  • Worth mentioning. JS engines that make it possible to set `undefined` are non conformant to the ES5 specification. – Benjamin Gruenbaum Jul 25 '13 at 14:42
  • @BenjaminGruenbaum: It's only [old browsers](http://kangax.github.io/es5-compat-table/#Immutable%20undefined) where this is a concern. Remember that ES5 wasn't published until Dec 2009; the only browsers where you can assign to `undefined` were released before ES5 existed. – josh3736 Jul 25 '13 at 14:53
5

Additionally to +Rocket Hazmat's answer, you can reduce the file size after compression a bit, when your code uses undefined frequently. That's because a local variable undefined may have its name mangled by the compressor, while the global undefined may not:

foo === undefined;
//      ^----- don't touch this, put "undefined" in the compressed result

(function (undefined) {
    foo === undefined;
})();
// may however be mangled to
(function(u){foo===u})();
Boldewyn
  • 81,211
  • 44
  • 156
  • 212
  • @user1737909: `void 0` cannot be reduced from 6 characters. `undefined` can be reduced to 1. – josh3736 Jul 25 '13 at 14:32
  • Are you talking about gzip compression or minification? – Ian Jul 25 '13 at 14:33
  • @josh3736 Well then I hope the minifier doesn't touch `undefined`, because it should know it's technically a reserved word. In which case, `void 0` is shorter. gzipping it could have the effect you're talking about – Ian Jul 25 '13 at 14:35
  • I don't know if `undefined` as a parameter is faster than `void 0`. Probably doesn't matter tho. `(function (u) { })()` is a 1-string `undefined`, what I wonder is whether the JITs are able to statically optimize it (probably) – Ven Jul 25 '13 at 14:38
  • @Ian what can be wrong with a local variable name minified? – A. Wolff Jul 25 '13 at 14:41
  • @roasted I don't think I realized we were talking about the local variable `undefined` instead of the global reserved `undefined`. I guess I didn't read this answer correctly. As long as the `undefined` is a local variable, then josh3736 was right and it can be minified properly – Ian Jul 25 '13 at 14:43
  • @Ian: Yep; `undefined` is only a reserved word in strict mode. In normal JS, it is either completely normal (in old engines) or a non-writable variable (in new engines). – josh3736 Jul 25 '13 at 14:45
  • @josh3736 This has nothing to do with strict mode or engines. You were talking about minification. My point was that a minifier **wouldn't** minify `undefined` because it should know that it's a global reserved word. I didn't think about redeclaring it locally (whether as a parameter or with `var`), in which case the minifier shouldn't treat it the same and should minify it properly. I was wrong in questioning you, but only because you were talking about a local `undefined` variable (not the global one) – Ian Jul 25 '13 at 14:48
  • @Ian: What I was saying is that there's absolutely nothing special about the global `undefined` either (it's not a "reserved word") *unless* you've opted in to strict mode. It's a completely pedantic point, and you're right that a minifier usually won't touch global variables in general. – josh3736 Jul 25 '13 at 15:03
  • 1
    @josh3736 You can call it (or not call it) whatever you want, but it's a "reserved word" in the sense that it's a feature of the language and shouldn't be modified. By "a minifier usually won't touch global variables in general", I hope you mean they **don't**. If a minifier minifies a global variable, you shouldn't be using it. And yes, there's something special about the global `undefined` as of ES5, not strict mode...it's unwritable: http://es5.github.io/#x15.1.1.3 – Ian Jul 25 '13 at 15:11
  • @Ian, I was specifically thinking about Closure Compiler's [advanced optimizations option](https://developers.google.com/closure/compiler/docs/compilation_levels), which does rename globals when enabled. Regarding `undefined`, remember that ES5 wasn't published until Dec 2009. In ES3/old browsers, there is nothing at all special about `undefined`. In ES5, the property `undefined` of the global object is read-only, but that still doesn't make it a [reserved word](http://es5.github.io/#x7.6.1). Again, this is completely pedantic, but **`undefined` is not specified as a reserved word**. – josh3736 Jul 25 '13 at 15:53
  • @josh3736 Good point about the Closure Compiler - didn't realize it had an **option** to rename globals instead of automatically always doing it. And sorry I didn't make it clear, I understand it's not a **reserved word**, that's why I surrounded it with `"`. I guess a better describer would be "read-only" like you've mentioned. And you're obviously right about pre-ES5 not defining `undefined` as read-only, but my other point was that the target is ES5, not strict mode. And it's not pedantic; I'd rather that I and others understand the correct thing, so I like to flesh it out like we are – Ian Jul 25 '13 at 16:00