立即调用函数表达式(IIFE)是如何立即调用防止其污染全局作用域的?

5
在Udacity的一堂关于立即调用函数表达式的课程中(涉及到提供的代码片段),它说:
被返回的函数闭包了(即捕获)hi变量。这使得myFunction能够维护一个私有的、可变的状态,该状态无法在函数外部访问!更重要的是:由于立即调用的函数表达式被调用,IIFE很好地封装了代码,以便我们不会污染全局作用域。
我很难理解为什么立即调用匿名函数与防止变量hi“污染全局作用域”有关,而且既然hi已经在函数中定义,那它不就已经在本地/私有范围内了吗?
const myFunction = (
  function () {
    const hi = 'Hi!';
    return function () {
      console.log(hi);
    }
  }
)();

重点是避免让 hi 在全局范围内可访问,并创建另一个不会与之冲突的名称。 - Patrick Roberts
1
如果您不立即调用它,您将不得不为其命名,从而污染外部范围。 - melpomene
基本上 myFunction = function () { console.log(hi) } 是IIFE的结果,但如果您不使用IIFE,则必须在外部作用域中声明hi。 如果您在最高作用域中执行此操作,则最终将在您的window对象或global对象(取决于您有什么)中具有hi,从而会污染它。 - apokryfos
只要变量在块内(对于let或const)或函数内(对于car), 它就不会污染全局作用域。 - nCardot
2个回答

4

在现代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,作为作用域的函数的名称)。

通过使用一个函数表达式并立即调用它,我们避免了第二个名称污染:

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

现在,仅在外部作用域中定义了myFunction。作为hi作用域的匿名函数没有名称可以污染周围的作用域。

最后,我们可以通过使用返回值来对其进行简化,这样我们就不必两次提到myFunction

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

这还可以省去一对括号(),因为function关键字不再出现在语句的开头。


0
立即调用函数表达式(IIFE)如何防止其污染全局作用域?
实际上并不能。函数本身的特性可以避免它污染全局作用域。
在函数内部声明的变量仅存在于该函数内部,不会影响到全局作用域。

1
为什么需要IIFE?我们不能只使用普通函数吗?为什么说IIFE可以防止全局作用域污染? - Kumar Manish
你不需要使用IIFE。你可以使用普通函数(但是你必须在某个时候调用它,为什么不立即呢?)。再次查看答案的最后两句话。 - Quentin
每个人都知道这个!关键不是那个!关键是IIFE的优点之一是它们不会污染全局作用域!你们怎么看不出区别呢!为什么他们在普通函数中也会发生这种情况! - Kumar Manish
唯一的区别是,你不再写"function funcName() { whatever; } funcName();",而是写成"(function () { whatever; })();",这样可以避免留下funcName。虽然微小,但在一个有很多一次性函数的大型项目中,它可能会保护你免受意外的函数名称重用。 - Foo Bar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接