4

When answering another question, I was using this pattern to call a function recursively:

(function() {
    // ...
    if(should_call_again) arguments.callee();
})();

which worked. I got feedback that naming the function also worked:

(function func() {
    // ...
    if(should_call_again) func();
})();

However, with this technique, window.func is undefined, which came as a surprise to me.

If I put it simply, my question is: why is the following true?

function a() {}
typeof window.a; // "function"

(function b() {})
typeof window.b; // "undefined"

b is still be accessible inside b itself. So it seems like the ( ) create another scope, but that cannot be the case because only functions create another scope, and I'm just wrapping it inside ( ).

So why does wrapping a function inside ( ) not put the function into the global object?

Community
  • 1
  • 1
pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • 3
    I don't know why the function is accessible by its name, but wrapping the definition in `()` makes it a function expression and even if they have a name, it does not create a symbol in the current scope. – Felix Kling Aug 15 '11 at 12:45
  • It's probably evaluated and since it is not assigned to a variable, it doesn't appear in that scope. – Aram Kocharyan Aug 15 '11 at 12:46
  • Maybe the activation object created on function invokation has a reference to the function itself by its name. Even if you assign the function to a variable, it will be accessible by its name from inside the function. – Felix Kling Aug 15 '11 at 12:54
  • 2
    For an explanation why the function is accessible by its name inside the function, see this answer: http://stackoverflow.com/questions/7065120/using-functions-regardless-of-assigned-variable-names/7065175#7065175 – Felix Kling Aug 15 '11 at 13:06
  • @Felix Kling: I think that answers my question. `... the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.` – pimvdb Aug 15 '11 at 13:14

2 Answers2

5

Because you're not writing a function declaration, but a function expression.

Functions defined in function expressions only get stored someplace when you assign them to a variable; you did not do that; you just called it immediately.


In a [very loose!] sense, you could think of function declarations as a special form of function expression assignment:

function a() {}
// vs:
var a = function() {};

This is still not a strictly accurate comparison, but it may help in understanding that a function declaration is kind of a special thing.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

There is a subtle difference that you appear to have overlooked, instead of defining the function as:

(function b () { });

It is actually written out as: (note the extra set of parenthases on the end)

(function b () { }());

When you write a function like this, it is immediately invoked and yet still carries its own scope.

JonnyReeves
  • 6,119
  • 2
  • 26
  • 28
  • Thanks. I'm not sure if I understand you correctly, though. `(function b (){ console.log(1) });` does not log anything. – pimvdb Aug 15 '11 at 12:53