4

I've run across some strangeness in JavaScript syntax that I don't understand.

I was trying to use a single anonymous global function for global abatement, like this:

<script type="text/javascript">
  function() {
    alert("all code goes here");
  }();
</script>

Unfortunately, I get a syntax error. This fixes it:

<script type="text/javascript">
  var MAIN = function() {
    alert("all code goes here");
  }();
</script>

But is unsatisfying because there is now a global MAIN object. Then I ran across this:

<script type="text/javascript">
  (function() {
    alert("all code goes here");
  })();
</script>

A colleague of mine saw this, shook his head and said "that's some syntax man".

What is going on with

var x = function() { .. }();

that requires parenthesis without the variable like this

(function() { ... })();

Edit: Identical to another question, with this great answer.

Community
  • 1
  • 1
Rich
  • 10,547
  • 9
  • 55
  • 87
  • 4
    That's not a closure. Closures != anonymous functions. –  Nov 01 '10 at 15:13
  • @delnan Thanks, edited the title. An explanation of what's going on would be helpful. – Rich Nov 01 '10 at 15:22
  • possible duplicate of [Explain JavaScript's encapsulated anonymous function syntax](http://stackoverflow.com/questions/1634268/explain-javascripts-encapsulated-anonymous-function-syntax) – Rich Nov 01 '10 at 16:07

4 Answers4

3

The issue is that function() {}() is being parsed as a function declaration. In a function declaration the function name is mandatory, so since it's missing here you get a syntax error. Placing parentheses around the function() {}() fixes the problem by forcing the code inside to be parsed as an expression instead: the parentheses act as the grouping operator, within which only an expression is valid.

Placing function() {}() on the right hand side of an assignment works for a similar reason: only an expression is valid there, so the function is parsed as an expression.

This is a short explanation. If you want a longer version, I'd suggest reading CMS's excellent explanation in another question.

Community
  • 1
  • 1
Tim Down
  • 292,637
  • 67
  • 429
  • 506
  • Thanks for passing this on. It's too bad that the answer is "because the grammar says so." I would guess that's it's hard to get this stuff right when designing a dynamic language. – Rich Nov 01 '10 at 20:23
1

So the reason is basically to disambiguate between a function declaration and a function expression.

If the extra braces or variable introduction don't sit well with you, there's always an operator you can persuade to do the work for you:

void function() {
    alert('hi');
}();
Ja͢ck
  • 161,074
  • 33
  • 239
  • 294
1

Basically... Javascript requires you to put your function somewhere.

You can do this with the normal named syntax:

function foo(){}

Or with the variable assignment syntax:

var foo = function(){}

The syntax with the () is actually just the second syntax, but you throw away the result instead of storing it somewhere.

This is actually equivalent to the statement above:

var foo = (function(){})

But since you can't have an assignment without assigning it to something it won't work without the ().

Wolph
  • 69,888
  • 9
  • 125
  • 143
  • I think I get it, but let me try to clarify. Essentially `function() {}` all by itself doesn't produce a function value because it is unevaluated. But `var x = function() {}` and `function x() {}` do. That means that `var x = function() {}` really does some converting into the latter form, rather than first evaluating the right hand side and passing the result to x. Does that sound right? – Rich Nov 01 '10 at 15:49
  • 1
    @Rich: that's pretty much how I understand it. `function() {}` is a declaration for a new function object that creates the function when evaluated. When storing it in a variable it will be evaluated or when passes as an argument or when evaluated as an expression. – Wolph Nov 01 '10 at 16:32
0
<script>
var foo = function(){alert("call");}();
var foo2 = function(){alert("call");};
console.log(foo2);
console.log(foo);

//foo(); //<-bad, foo not a function
console.log(function(){return "json";}());
</script>

var foo is undefined cause there is no return value; if we do this:

var foo = function(){return function(){alert("call");};}();
foo(); //works cause a function is assigned to foo
jebberwocky
  • 1,093
  • 2
  • 11
  • 24
  • Right, but that's not what I'm after. Essentially, I'm putting my page's JavaScript code inside the function and want it called once. That way I don't pollute the global namespace with extra variables. In your example, I wouldn't care that `foo` is not a function, but I needed it there to trigger the alert when the page loaded. – Rich Nov 01 '10 at 15:26
  • "Every function in JavaScript is actually a Function object." from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function. if you want to trigger the alert when the page loaded, you might want to use"window.load= function(){...}" – jebberwocky Nov 01 '10 at 15:58
  • Thanks. My question was why the `function() {}();` syntax didn't work. [This](http://stackoverflow.com/questions/1634268/explain-javascripts-encapsulated-anonymous-function-syntax/1634321#1634321) is why. :) – Rich Nov 01 '10 at 16:10