Skip to content
Advertisement

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.

Advertisement

Answer

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.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement