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
.