立即调用 IIFE 如何防止它污染全局范围?

How does an IIFE's being called immediately prevent it from polluting global scope?

在关于立即调用函数表达式的 Udacity 课程中(关于提供的代码片段)它说:

The function that is being returned closes over (i.e., captures) the hi variable. This allows myFunction to maintain a private, mutable state that cannot be accessed outside the function! What's more: because the function expressed is called immediately, the IIFE wraps up the code nicely so that we don't pollute the global scope.

我正在努力理解立即调用匿名函数与防止变量 hi 来自 "polluting the global scope," 有什么关系,并且由于 hi 已经在函数中定义,是不是它已经在 local/private 范围内了吗?

const myFunction = (
  function () {
    const hi = 'Hi!';
    return function () {
      console.log(hi);
    }
  }
)();

How does an IIFE's being called immediately prevent it from polluting global scope?

没有。

作为函数会阻止它污染全局范围。

函数内声明的变量仅存在于该函数内

在现代 JavaScript 中,你有 let 和块作用域(我很确定 const 也有块作用域),所以你可以这样做:

let myFunction;
{
    let hi = 'Hi!';
    myFunction = function () {
        console.log(hi);
    };
}

这会创建 myFunction 而不会泄漏 hi 到周围的范围。

在传统的 JavaScript 中,您只有 var 和函数作用域,您可以这样做:

var myFunction;
function a_private_scope() {
    var hi = 'Hi!';
    myFunction = function () {
        console.log(hi);
    };
}
a_private_scope();

a_private_scope 限制了 hi 的范围,但是(它是一个函数声明)它需要显式调用,我们仍然向周围的范围泄漏一个名称(这次是 a_private_scope, 作为作用域的函数的名称).

通过使用函数 expression 并立即调用它,我们避免了这个名字污染:

var myFunction;
(function () {
    var hi = 'Hi!';
    myFunction = function () {
        console.log(hi);
    };
})();

现在在外部作用域中唯一定义的是myFunction。作为 hi 作用域的匿名函数没有名称,它可能会污染周围的作用域。

最后我们可以使用 return 值稍微清理一下,所以我们不必两次提到 myFunction:

var myFunction = function () {
    var hi = 'Hi!';
    return function () {
        console.log(hi);
    };
}();

(这也为我们节省了一对 ( ) 因为 function 关键字不再出现在语句的开头。)