2

I have came across !function() {}(); statement in an on-line test. By changing it to !function() { return true; }(); I figured out that the function calls before !. I assumed that an anonymous function declaration becomes a function expression first, then it invokes, finally a result is logically negated. Is my assumption correct, why does the statement evaluate in this order?

Andriy Simonov
  • 1,276
  • 1
  • 11
  • 19
  • `!` is an operator and putting that in front of a function or variable will use the value of the rhs and negate it. So the execution happens from the expressed function as soon as (); this is invoked and the value is negated. so if you had `console.log(function(){return true;}())` would log `false` and `console.log(function(){return false;}())` would log `true` and `console.log(function(){}())` would log `true` – Nilesh Mar 13 '17 at 21:08
  • 1
    What other order could make sense? – Oliver Charlesworth Mar 13 '17 at 21:14
  • @Nilesh The initial statement is not inside the console.log() function, it makes a difference. If I put it in a browser console it returns _true_, on the other hand `function(){return true;}()` complains about SyntaxError. Could you explain why is it so? – Andriy Simonov Mar 13 '17 at 21:27
  • I don't get where your assumption and the observed behaviour deviate? Both are correct: the function is called before the result is negated. – Bergi Mar 13 '17 at 21:31
  • @Bergi I can not understand why `function() {}();` invokes a function. Does it become a function expression, how does it deffer from '(function() {})();`? – Andriy Simonov Mar 13 '17 at 21:42
  • You appear to be confusing parser rules and operator precedence with evaluation order. They're completely orthogonal. – Alnitak Mar 13 '17 at 21:50
  • @AndriySimonov `function(){}` is a function and `()` is an invocation. Why it becomes a function expression, instead of a declaration followed by a syntax error, depends on the parser grammar and has nothing to do with the evaluation. – Bergi Mar 13 '17 at 21:52
  • 1
    possible duplicate of [javascript function leading bang ! syntax](http://stackoverflow.com/q/5827290/1048572) (I'd have closed it but already have voted as unclear) – Bergi Mar 13 '17 at 21:55
  • @Bergi The question really seems to be confusing. What would be a correct question to ask? Should I delete this one? – Andriy Simonov Mar 13 '17 at 22:08
  • I guess if your confusion is gone now, it would be best to delete it. If there's still something unclear, you might want to ask something like "*Why do `!function(){}()` and `(function(){})()` invoke a function while `function(){}()` is a syntax error?*"; However I guess that would quickly get closed as a duplicate of the question I linked (or one of the many similar ones) – Bergi Mar 13 '17 at 22:14

1 Answers1

1

To negate some x you need to know what this x is. you can't negate an expression, only the result of that expression.

In other words: you can't say "give me the negative of 'set x to the value of y'" !(x = y) (well, you can write this in JS, but that's a different expression), but you can say "give me the negative of the result of 'does x equal y?'" !(x == y).

The same thing happens with the method. because you call it (using the parentheses), it has to first check what that results in, before beeing able to negate it

edit:

As this seems to confuse people: using parentheses tells JavaScript to invoke that function, when they are after the function-definition. try this: var test = function(){return 'hello';} test will now be the function itself, and running test() will return hello (a.k.a parentheses make JS call the function)

when you write var test = function(){return 'hello';}() instead, you now tell JS to instantly call that function, and whatever that function results in should be the value of test. running this will make test have the value 'hello'

Neutrosider
  • 562
  • 3
  • 12
  • Thank you for your answer. Your explanation about negation makes perfect sense to me, but still it is not clear why `function() {}();` invokes. As far as I understand it is a function declaration with parenthesis as opposed to `(function() {})();` where we have a function expression. – Andriy Simonov Mar 13 '17 at 21:37
  • No, the `function() {}` is a function declaration. the `()` behind that tell Javascript to call that function – Neutrosider Mar 13 '17 at 21:39
  • What is the difference between `function() {}()` and `(function() {})()` then? The former throws a SyntaxError in a console. – Andriy Simonov Mar 13 '17 at 21:46
  • see my updated comment. you can't really use the former one on it's own, because it's not valid JS. you CAN however write `(function (){})();` because you then force JS to evaluate `function (){}` first (which is a valid function) before calling it – Neutrosider Mar 13 '17 at 21:51
  • I would assume that JS just doesn't know what to do if you just throw it a function-definition without any context. But if you give it an expression (like: call that function, or make test the result of that function), it can work with that – Neutrosider Mar 13 '17 at 21:56
  • The point is that `function(){}` can be both an expression or a declaration. Only the context in which it is parsed decides what it is. – Bergi Mar 13 '17 at 22:04