为什么命名的 IIFE 会在其外部导致 ReferenceError?

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

为什么我得到 ReferenceError: Person is not defined” 下面的代码?

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

由于函数Person是运行,它是第一个创建的。但是,我无法解释为什么它没有被识别。我唯一的想法是 IIFE 忽略了他们给出的名字。

命名函数表达式只在它们自己的作用域.

内创建一个与其名称相匹配的变量

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

您需要函数声明才能在当前范围内创建变量。函数声明不能​​是 IIFE。

如果您需要创建一个可以多次调用的函数并且立即调用它,那么您需要分两步完成:

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

你得到错误是因为函数 expression 创建的函数的名称没有添加到表达式所在的范围。(它 在函数体内的范围内,因此名称不仅会被忽略。)函数 声明 在它出现的范围内创建名称,但不是命名函数表达。 JavaScript 就是这样定义的。

如果坚持使用表达式而不是函数声明很重要(例如,因为表达式是在代码的逐步处理中完成的,而声明是在更早的时候完成的),您可以这样做它有一个变量:

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

在 ES6 中,这变得更加简洁,因为在 ES6 中,您可以在不使用命名函数表达式的情况下命名函数:

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

在 ES5 中,该函数没有名称(但许多 JavaScript 引擎无论如何都给了它一个名称)。在 ES6 中,该函数 确实 有一个名称,该名称取自变量。

语言设计者不一定需要 "why" 来做出不将名称放入范围之类的决定,但当您考虑这样做时,这样做是有道理的:

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

上述将 x 添加到范围可能是有道理的,但不包括 foobarbaz