Unknown developer
Unknown developer

Reputation: 5930

Why does a named IIFE result in a ReferenceError outiside of it?

Why did I get ReferenceError: Person is not defined” for the following code?

(function Person() {
  console.log('Hi');
}());
console.log(Person);

Since function Person is run, it is first created. However, I cannot explain why it is not then recognized. My only thought is that IIFE ignores the name they are given.

Upvotes: 1

Views: 314

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074495

You get the error because the name of a function created by a function expression is not added to the scope the expression is in. (It is in-scope within the function body, so the name isn't just ignored.) A function declaration creates the name in the scope where it appears, but not a named function expression. That's just how JavaScript is defined.

If it's important that you stick to using an expression rather than a function declaration (for instance, because expressions are done in the step-by-step processing of the code, whereas declarations are done earlier), you can do it with a variable:

var Person = function Person() {
    console.log('Hi');
};
Person();
console.log(Person);

And that gets more concise with ES6, because in ES6 you can name a function without using a named function expression:

var Person = function() {
    console.log('Hi');
};
Person();
console.log(Person);

In ES5, that function wouldn't have a name (except many JavaScript engines gave it one anyway). In ES6, that function does have a name, which is taken from the variable.

Language designers don't necessarily need a "why" for decisions like not putting the name in scope, but it makes sense when you think of doing things like this:

// ES5 and earlier
var x = {
    foo: function foo() { /* ... */ },
    bar: function bar() { /* ... */ },
    baz: function baz() { /* ... */ }
};

It probably makes sense that the above adds x to the scope, but not foo, bar, and baz.

Upvotes: 2

Quentin
Quentin

Reputation: 943605

Named function expressions only create a variable matching their name within their own scope.

(function Person() {
  // Person is in scope here
  console.log(Person);
}());
// Person is out of scope here
console.log(Person);

You need a function declaration to create a variable in the current scope. Function declarations can not be IIFEs.

If you need to create a function which you can call multiple times and call it immediately, then you need to do it in two steps:

function Person() {
  console.log('Hi');
}
Person();

Upvotes: 7

Related Questions