6

I have found this piece of code in jQuery Migrate v1.1.1

jQuery.migrateMute===void 0&&(jQuery.migrateMute=!0),function(e,t,n){/* anything */}

And I really wonder about 2 things:

1) What does ===void 0 mean?

2) Why these conditions are followed by a comma? My tests showed me it will always get executed.

Its just not I really need to know,but i am really interested, because I thought I knew everything about JS. ;)

Akshita
  • 849
  • 8
  • 15
s0urce
  • 81
  • 8
  • 1
    Check this thread: http://stackoverflow.com/questions/4806286/difference-between-void-0-and-undefined – Vadim Landa Apr 20 '15 at 06:44
  • See the minimizer that was used for this code, uglify2. https://github.com/mishoo/UglifyJS2#the-unsafe-option Search for "void 0" on that page. – Mörre Apr 20 '15 at 06:55

2 Answers2

4

void 0 will yield undefined, as will void X for any X; it is shorter, and cannot get redefined like undefined can. So ===void 0 compares jQuery.migrateMute with undefined.

!0 is true.

Thus, the "translation" of jQuery.migrateMute===void 0&&(jQuery.migrateMute=!0) is:

if (jQuery.migrateMute === undefined) {
  jQuery.migrateMute = true;
}

Then the stuff after the comma executes, independently from this.

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • Which can easily be seen by looking at the source. https://github.com/jquery/jquery-migrate/blob/master/src/migratemute.js You forgot a `typeof`. It was apaprent that OPs code is the minimized version, so his question really is "what does a minimizer do with JS code"... – Mörre Apr 20 '15 at 06:48
  • @MörreNoseshine: Didn't forget `typeof` - I didn't look at the source (but good point, I should have), and `x === undefined` is equivalent to `typeof(x) === "undefined"` as long as no-one did something stupid like `undefined = 13`. – Amadan Apr 20 '15 at 06:50
  • I know it's equivalent, I was referring solely to what's really happening here given the source. And see https://github.com/mishoo/UglifyJS2#the-unsafe-option (that was minified using uglify2) – Mörre Apr 20 '15 at 06:51
  • Amadan, what did you mean by [`void X`] cannot get redefined like undefined – Alexander Suraphel Apr 20 '15 at 06:56
  • 1
    @AlexanderSuraphel Try redefining "undefined" e.g. by `undefined=42` in JS. Works. Try with `void` - does not work. See https://github.com/mishoo/UglifyJS2#the-unsafe-option, this is why the minimizer uses this conversion of `undefined` to `void 0`. – Mörre Apr 20 '15 at 06:58
  • 1
    @AlexanderSuraphel: I mean, as I said in my previous comment, that `undefined = "defined"` is valid JavaScript that will break a lot of code. If you do `undefined = true` and then `if (foo === undefined)`, weirdness ensues. If you do `if (foo === void 8)`, it is foolproof - it will always test against the *value* `undefined`, and not the *global variable* `undefined`. – Amadan Apr 20 '15 at 06:58
  • `if (xxfoobarxx === void 0) { console.log('a'); }` ReferenceError: xxfoobarxx is not defined `if (xxfoobarxx === undefined) { console.log('b'); }` ReferenceError: xxfoobarxx is not defined `if (typeof(xxfoobarxx) === 'undefined') { console.log('c'); }` c Looks like, nothing works beside the solution I already knew. But it's logic, how to proof a variable which not exists? Makes no sense. And btw. any other idea about this ´cond&&cond,func()´ contruct? Ty for all comments so far! – s0urce Apr 20 '15 at 08:34
  • @s0urce: Right, there's also the assumption that the variable exists. And you should know that a variable exists since it is statically analysable from the source. The error only shows up when you mention an identifier that did not get its `var` or `function` declaration. I did write about the construct - `a() && b(), c()` is functionally equivalent to `if (a()) { b(); }; c();` due to the semantics of the operators: `&&` as the short-circuit AND, and `,` as the sequencing operator. – Amadan Apr 20 '15 at 08:41
  • @Amadan: Why do I need to proof a variable for undefined, if I already know it is? And thx for the construct hint. Did already know about the start, but was wondering if this comma is part of it. Seems like they just used comma instead of semi-colon... – s0urce Apr 20 '15 at 08:45
  • 1
    @s0urce: For variables, because the variable can be declared and left undefined (`var foo`), or *assigned* to be undefined (`var foo = 5; foo = undefined`). And also, you might be testing properties, that never raise this error: `if (xxobjectxx.xxfoobarxx === undefined)...` will always work without raising an error. – Amadan Apr 20 '15 at 08:50
  • Edit: Just figured it out my self. If you proof for properties of Objects, then it will work like this, thx anyway - cheers. ;) – s0urce Apr 20 '15 at 08:52
  • @MörreNoseshine `undefined` is actually _non-writable_ and _non-configurable_ in the _Global Namespace_, `undefined=42; undefined; // undefined` which makes it safer to use than something like `Array`, `RegExp`, `console`, `atob`, `btoa`, etc. This means the only way your code can end up with a wrong _undefined_ is if it's interpreted under a closure which has re-defined it, shadowing the global namespace (although you could still go via `window.undefined`). – Paul S. Apr 21 '15 at 03:42
  • 1
    @PaulS.: You are correct, `undefined` is immutable since ES5. However, a compiler won't necessarily know that its compiled code will execute in a compliant environment. Good point about all the rest of globals being dangerous. E.g. you could still redefine `undefined` in IE8. – Amadan Apr 21 '15 at 03:47
  • @Amadan It's good to know about `void` and there are cases to use it, but the when I see people give this as a reason it irritates me as a hangover from years ago D: and if you really wanted to code golf it down it's shorter to do a lookup to a non-existant property, e.g. `0..u; // undefined`. Surely the best way is to fix code that does a silly thing rather than try to protect against every possible silly thing. – Paul S. Apr 21 '15 at 03:52
  • @PaulS.: For handwritten code in a code base whose structure and deployment parameters I control, you are completely right. But a compiler/minifier/uglifier needs to be as defensive as is possible, which is likely why it was done. – Amadan Apr 21 '15 at 03:54
  • @PaulS. (and all) Good point - there is a reason this code is found in a MINIFIER. You are absolutely correct that it should not make normal code unreadable - this is a perfect example for letting a machine take care of such issues. Same reason why you don't try to optimize the hell out of your C or C++ or whatever code but let the compiler take care of it, so that people can concentrate on writing **human-readable** code first of all. Which is why I think it's vital to add this to the explanation for OP and everyone who's going to find this, to prevent everyone from writing code like this. – Mörre Apr 21 '15 at 09:36
0

To summarize all the comments and answers...

  1. void 0 or void(0) is just the value of undefined by default. That's why you can use it instead of undefined, to be sure it's not overwritten by someone. here the source

  2. And about this construct, this means the same as:

    if(x){y=z};function(){/*...*/};
    
Matt
  • 74,352
  • 26
  • 153
  • 180
s0urce
  • 81
  • 8