Ionică Bizău
Ionică Bizău

Reputation: 113365

Why function statement doesn't create a function when using setting it as a method?

I encountered the following behavior:

> foo = {};
{}
> foo.bar = function bar() { return arguments; }
[Function: bar]
> bar()
ReferenceError: bar is not defined
    at repl:1:2
    at REPLServer.self.eval (repl.js:110:21)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)
    at Interface._ttyWrite (readline.js:760:14)
    at ReadStream.onkeypress (readline.js:99:10)
    at ReadStream.emit (events.js:98:17)
    at emitKey (readline.js:1095:12)

Isn't bar supposed to be a function in the current scope?

Adding [var] bar = solves the problem:

> bar = foo.bar = function bar() { return arguments; }
[Function: bar]
> bar(1)
{ '0': 1 }

But why doesn't it work without assignment to bar?

Upvotes: 0

Views: 63

Answers (3)

Siddharth
Siddharth

Reputation: 1166

You are essentially creating what is a named function expression. And hence it is not in the current scope but is assigned to the property of the object foo as a method instead.

When using the function keyword in an expression (as opposed to a declaration) when no name is given, you create an anonymous function as you are already aware, I'm sure.

When a name is added between the function keyword and the () in the context of an expression, you are created a named function expression.

The scope of the name of the function is within the function itself, so inside the function, you may recursively call itself using bar() but outside, it does not exist and gives you the ReferenceError that you are encountering.

Upvotes: 1

Jon
Jon

Reputation: 437376

When you are using a function declaration of that type in that context, you are creating a named function expression (NFE). Contrast this with simply declaring a named function, when you have a function declaration.

The spec says that the name of an NFE shall only be accessible inside the function itself. Here's how to see the difference:

var x = function() { console.log(foo); }      // (anonymous) function expression
x(); // ReferenceError: foo is undefined

var y = function foo() { console.log(foo); }  // NFE
y(); // function foo()...

Upvotes: 1

Quentin
Quentin

Reputation: 943556

The context you are using the function keyword in (on the RHS of an assignment) makes it a function expression, not a function declaration.

Putting a name between function and () makes it a named function, but since it is not a function declaration it doesn't create a variable in the current scope.

Note that named function expressions have memory leak issues in old-IE.

Upvotes: 3

Related Questions