1

I was reading through this SO question. I sort of understand what's going on, but I'm confused why

!function foo() {
  console.log(true) ;
}()

doesn't return false.

!function () {}() This will also return the boolean opposite of the return value of the function, in this case true, because !undefined is true. If you want the actual return value to be the result of the call, then try doing it this way:

"will also return the boolean opposite" makes me think that false should be returned. Why isn't it. alert(!true); //false

Community
  • 1
  • 1
1252748
  • 14,597
  • 32
  • 109
  • 229
  • 3
    because since the function doesnt return a value, `undefined` is returned, which is a falsy value, and the opposite of that is `true` – Patrick Evans Aug 30 '14 at 18:14
  • 1
    You already included the answer in your question: *"This will also return the boolean opposite of the return value of the function, **in this case true, because !undefined is true**."* The return value of the function is `undefined` because you don't return anything. – Felix Kling Aug 30 '14 at 18:26
  • How does `!true` relate to `!function foo() {}()`? Were you thinking that the function itself was being negated instead of its return value after being invoked? Give it different return values and you'll see the difference. `return false` ... `return true` ... `return 0` ... etc. – cookie monster Aug 30 '14 at 18:37

2 Answers2

6

Without a return statement the function returns undefined. When you apply ! to undefined you get true.

Try

console.log(!function() { return true; }());

Note that the idiomatic use of ! before an IIFE is just that — an idiom. The fact that the ! operator has an effect on the return value almost always doesn't matter, because the return value is being completely ignored by the calling environment. Thus

+function() {
  // whatever
}();

is effectively exactly the same, even though the + unary operator is different from the ! unary operator.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Yeah, that's exactly what I mean. I understand from the question I linked that this syntax saves a byte, but why would you want to reverse the opposite value that is being returned? Doesn't `console.log(!!function() { return true; }());` make more sense? – 1252748 Aug 30 '14 at 18:22
  • I have reread a few more times. Are you saying that this syntax only makes sense when a function doesn't return anything? – 1252748 Aug 30 '14 at 18:23
  • From the answer I linked: _"Sometimes we want to call a function right as we create it. You might be tempted to try this: `function () {}()` but it results in a SyntaxError."_ Why does that result in a syntax error. I don't understand why it does not work. Thanks. – 1252748 Aug 30 '14 at 18:25
  • 1
    @thomas: Because the engine interprets `function () {}` as a function *declaration* and declarations need a name. The `!` in front of the function makes the engine interpret it as a function *expression*, which don't need names. That's the only purpose of the `!` in this situation. You could use any other unary operator to achieve the same effect (such as `+`, `void` or `-`). – Felix Kling Aug 30 '14 at 18:27
  • @FelixKling +1, getting there..bear with me. Just to be clear, the `!` has nothing to do with the return value—it only ensures that the function is immediately expressed, ie. invoked, yes? – 1252748 Aug 30 '14 at 18:40
  • @thomas it's **both** - by forcing the parser to interpret the function as a function instantiation expression instead of a function declaration statement, it allows the immediate invocation. However, a `!` is a `!`, so it **also** inverts the logical sense of the return value. When this idiom is used, the return value is *almost never* of any concern to the greater code context. The `+` or `-` or `~` unary operators are almost always just as good at this job. – Pointy Aug 30 '14 at 18:53
2

Functions that have either an empty return statement or a non-existent one return the value undefined upon their invocation. Applying ! to "falsy" values such as 0, null, undefined return true.

David G
  • 94,763
  • 41
  • 167
  • 253