2

I'm having some trouble understanding how both of these two lines are inter-changeable.

( function() { return console.log("anon inner 1"); } ) ();
//                                                     ^^ invoke

( function() { return console.log("anon inner 2"); } () );
//                                                   ^^ invoke

In the first line, we have an anonymous inner function that is wrapped in parenthesis, and then immediately invoked. The second line, we have an anonymous inner function that is invoked and then wrapped in parentheses.

I guess my question is, what does the wrapping in parenthesis do? Does it objectify stuff, that is, turn things into object?

weisjohn
  • 793
  • 5
  • 9

2 Answers2

3

JavaScript has a function statement, which is the "standard" way to declare a function, with the syntax:

function name([param1, 2...]) {
   statements
}

And there is a function operator, which looks the same as the function statement except that the name is optional and it is used not as a statement on its own but where an expression is expected as in the following two examples:

// declare variable name that references a function created by expression
var name = function([param1, 2...]) { statements };
// call someOtherFunction that expects a function as a parameter
someOtherFunction(function() { });

(There are plenty of other ways to use function expressions.)

If you try to have an anonymous function on a line by itself without wrapping it in parentheses it will taken to be a function statement and thus be a syntax error because there's no name. Wrapping it in parentheses means it'll be treated as an expression inside the parens and not as a statement so then name is optional. If you assign the result of the function expression to a variable or use it in some other way (like in my examples above) then you don't need the parentheses.

So getting (at last) to the syntax mentioned in the question: once you have the parens and your function is treated as an expression you can use either of the two syntaxes you posted to invoke it. The first, invoke "outside" the parens means the first set of parens will evaluate as having the value of the expression inside, which happens to be a function that you can then invoke. The second, invoke "inside" means function expression will be invoked and then the surrounding parens will evaluate to whatever the function returns.

Either way, the return value of the function is thrown away because you don't assign it to anything.

(Final note: a function expression can have a name so that the function can call itself recursively.)

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
1

When you have a regular annon function like:

function() { alert('testing'); }

it's a function expression. Any other vairiation is called a function declaration, like the following:

function a() { alert('testing'); }
!function() { alert('testing'); }
var a = function { alert('testing'); }
(function() { alert('testing'); })

Now a function expression can't be invoked as it's not returning a value, but a declaration can. So all you need to do is somehow switch it to a declaration to immediately invoke, which is what the parens do, whether they wrap the invoking parens or not. This is because once the js parser sees a open parens it makes it into a declaration.

Disclaimer: I may have mixed up the terminology of declaration and expression

qwertymk
  • 34,200
  • 28
  • 121
  • 184
  • 2
    More: https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope Also, beware that the form `function a() { }` elevates itself to the top of the scope where it is defined and will overwrite any variables, e.g. `var a = 0`. Example: http://jsfiddle.net/G8ydD/ console should display a `TypeError` because it tries to invoke the number 0 as a function. – Joseph Yaduvanshi Sep 08 '11 at 02:51
  • thanks, Jim! Just took a look at that jsfiddle and indeed, it threw that error. I actually just learned that concept tonight, as I'm watching Crockford on JavaScript Part 3 [link](http://yuilibrary.com/theater/douglas-crockford/crockonjs-3/) and he covered that at the beginning. One of his examples actually led me to post the quesiton. Thanks! – weisjohn Sep 08 '11 at 03:01
  • 2
    As you said in your disclaimer, your use of "declaration" and "expression" is a bit mixed up. Your last two function "declarations" are really expressions. The `var a = ...` syntax means "declare variable `a` and assign it to reference the function expression on the right". I'm not sure about the not (!) syntax. – nnnnnn Sep 08 '11 at 03:03