19

I was looking at the output of some stuff from UglifyJS and happened across some code like the following:

var a = 0;
var b = function () {
    return function () {
        a++;
    }(), 'Hello, World'
}();

After running that code a is 1 and b is the string Hello, World!.

At first glance it appears that b will be undefined since it looks like the result of a function with no return value is being returned, but that is followed by a comma and a string literal.

Why does this work?
And why doesn't UglifyJS just execute the anonymous function and then return Hello, World! as the next statement?

Andreas Louv
  • 46,145
  • 13
  • 104
  • 123
knpwrs
  • 15,691
  • 12
  • 62
  • 103
  • 5
    A better question might be why are you (or whoever) writing javascript this way? Code should be unambiguous. – Corey Ogburn Oct 26 '12 at 16:06
  • 5
    @CoreyOgburn it isn't ambiguous if you know what the comma operator does. – AD7six Oct 26 '12 at 16:09
  • `var a = ("rofl", "but its lol!");` – jAndy Oct 26 '12 at 16:10
  • 6
    Code that depends on understanding an obscure operator that has no practical value in this instance *is* (while not technically ambiguous) non-obvious, which is the next worst thing. – Quentin Oct 26 '12 at 16:10
  • 9
    Let me make it clear that I have no intention of writing code like this. I just saw some output from UglifyJS which looked like that and I went, "dafuq?" – knpwrs Oct 26 '12 at 16:15
  • Possible duplicate of [What does the comma operator (expression, expression) means in Javascript when doing condition evaluation?](http://stackoverflow.com/questions/41891262/what-does-the-comma-operator-expression-expression-means-in-javascript-when-d) – Heretic Monkey Jan 27 '17 at 15:45

4 Answers4

25

It works due to the comma operator. From the MDN specs:

The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.

Both functions are IFFYs, they are inmediately executed.

Wouter J
  • 41,455
  • 15
  • 107
  • 112
  • 4
    @j08691: I think he means "IIFE" or "Immediately-Invoked Function Expression". That's when you make a function and immediately call it, like `function(){}()`. Not *all* functions are "IIFE"s, though. – gen_Eric Oct 26 '12 at 16:13
  • 3
    @Rocket, I guess Wouter means *both* functions on the example code are IIFEs. – bfavaretto Oct 26 '12 at 16:44
  • 1
    I really feel like I learned something today with this answer – Jay Oct 26 '12 at 18:01
  • @bfavaretto & j08691 thank you. My english isn't that good and I needed to write that message fast, so I had maked some mistakes. It is called an IIFE, but the founder of that method says *"The pronunciation “iffy” was suggested to me, and I like it, so let’s go with that."* ([source](http://benalman.com/news/2010/11/immediately-invoked-function-expression/)). – Wouter J Oct 26 '12 at 19:10
6

The result of an expression using the comma operator is the right hand side of the comma operator.

You have:

return a_function_call(), a_string

… so you get a_string assigned.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
3

First of all let me cite MDN on the comma operator:

The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.

With that being said, it is clear, how your code evaluates:

Inside the immediately executed function you return 2 values separated by a comma:

function () { a++; }()

and

'Hello World'

So both operands are evaluated. This increments your variable a and leads to the following expression for the return value of the function to create b:

undefined, 'Hello World'

Finally the right operand is returned as a value for the outer function, thus giving b the value 'Hello World'.

Sirko
  • 72,589
  • 19
  • 149
  • 183
0

Check out the comma operator in JavaScript.

The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.

Jarrett Meyer
  • 19,333
  • 6
  • 58
  • 52