0

Why this piece of code returns 0

 a=!!function(){console.log(!0)}()+!!function(){console.log(!0)}()

and this one returns 2

 a=!!function(){}+!!function(){}

Whats the magic behind it?

Edit: This is what I would expect:
function(){console.log(!0)}() should return true because it was successful and it contains body. So when it is casted to boolean and then int it should be 1

function(){} this should be false, since it is neither called nor contains function body. Same confusion with !![] and !!""

Dharman
  • 30,962
  • 25
  • 85
  • 135

3 Answers3

1
  • 1: function(){}() returns a falsy value.
    Then, !!, a double bitwise not, casts that to false.
    Result: false + false === 0.

  • 2: function(){} is a truthy value.
    Then, !!, a double bitwise not, casts that to true.
    Result: true + true === 2.

The content of those functions are irrelevant in this question. The first line contains IIFE's that return nothing, which is falsy.
The second line simply casts the 2 functions to booleans.

Now, when those booleans are converted to numbers (Due to the + operator), this is the result:

Number(true)  // 1
Number(false) // 0
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
  • So if an empty anonymous function is cast to boolean it will always be true and when a function without return statement is invoked(successfully) will return false? Who designed it this way? – Dharman May 28 '14 at 10:18
  • @Dharman: Yea, that's pretty much how it works. As for who designed it, it's a bit of a history lesson. The [wiki](http://en.wikipedia.org/wiki/JavaScript) has some more info – Cerbrus May 28 '14 at 11:03
  • I would like some more explanation on why is that `falsy` and `truthy`. – Dharman May 28 '14 at 11:10
  • 2
    @Dharman: The first function doesn't have a `return` statement, so returns `undefined`, which is, as to be expected, `falsy`. The second statement tries to cast a function to a boolean value. Since a function is not part of the [list of "things" defined to be `falsy`](http://www.sitepoint.com/javascript-truthy-falsy/), it's cast to `true`. – Cerbrus May 28 '14 at 11:15
-1

Both function are assigning to a the following value

 a=!!function(){console.log(!0)}()+!!function(){console.log(!0)}()

!!function(){console.log(!0)}()

  • function(){console.log(!0)}() => function statement requires a name
  • !function(){console.log(!0)}() => return true (previously it was false)
  • !!function(){console.log(!0)}() => return false

In javascript

false + false = 0

Regarding the second function

 a=!!function(){}+!!function(){}

!!function(){}

  • function(){} => function statement requires a name
  • !function(){} => false
  • !! function(){} = true

In javascript

 true + true = 2

That's why you get 2

Dimitri
  • 304
  • 3
  • 16
  • _"function statement requires a name"_: Nope, IIFE's don't. Nor do anonymous functions passed as parameters, for example. Also, you're not explaining _why_ those functions are `true` or `false`. – Cerbrus May 28 '14 at 09:58
  • Arguably this is a better structured answer than the other- but it's factually wrong, and doesn't actually answer the (dubious) question. -1. – AD7six May 28 '14 at 10:03
  • @AD7six Why is it wrong ? I just forgot to talk about this let you cast your function to do some tests – Dimitri May 28 '14 at 10:05
  • I know you cant assign a function to a var, or create anonymouse function used massivly for callback or stacking, but this express ''function(){}'' executed behind a braquet expression return the following error, it is not a definition – Dimitri May 28 '14 at 14:13
  • You _can_ assign a function to a variable (e.g. jQuery makes $ _a function_). You _can_ create anonymightymouse functions (very common). Im not sure what the last part of the above comment means - perhaps find some docs on immediately-invoked-function-expressions. – AD7six May 28 '14 at 14:35
-1

The "magic" is that you apply the functions in the first case, and you don't apply them in the second case (that's the extra pair of () ).

So

var x = function(){console.log(!0)}
x;     // => function (){console.log(!0)}
x();   // => false
!!x(); // => false
!!x()+!!x() // => false + false => 0

whereas

var y = function(){};
y;       // => function () {};
!!y;     // => true
!!y+!!y; // => true + true => 2

note that if you dont call the function in the first case, you get the same thing:

var x = function(){console.log(!0)}
x;      // => function (){console.log(!0)}
!!x;    // => true
!!x+!!x // => true + true => 0

Now, of course, the reason behind the conversions (why is !!x - "the opposite of the opposite of a function" - "false", rather than "true", or 42, or NaN, or NotABoolean, or FileNotFound) falls into the "Wat ??" category that is very common in Javascript.

Please never write this kind of code in real code that I'm ever likely to read, edit, or use.

Community
  • 1
  • 1
phtrivier
  • 13,047
  • 6
  • 48
  • 79