立即调用的函数表达式(IIFE)相较于普通函数的优势

26

我对JavaScript还不是很熟悉,我了解到模块模式可以提供一种命名空间,并且同时拥有私有和公共成员,例如:

var module = (function() {
   var s = "Hello, i'm private and in closure!";
   return {
      myString : s,
      myFunc: function() { alert(s); }
   };
})();

我确实看到了这种方法的好处,因为它给你一些面向对象编程的优势。但是我见过很多没有被分配给变量的IIFE的例子。就我所知,与你调用的普通函数相比,这种方法根本没有任何优势:
(function() {
   var s = "Hello I'm private!";
   $('#myButton').on('click', function() {
      alert(s);
   });
})();

2. 普通函数

function Initialize() {
   var s = "Hello I'm private!";
   $('#myButton').on('click', function() {
      alert(s);
   });
}

Initialize();

他们两个都有私有变量,避免了创建全局变量的需要,而且它们都在不返回任何值给变量的情况下执行。 虽然第二个给你选择一个好名字的选项,这个名字比潜在的大IIFE更能说明问题,让读者自己去发现发生了什么。 答案 我看到 到处都是 "避免命名空间污染",但是这两种方法都可以做到,只是第一种方法稍微难理解一点?

简而言之:

使用IIFE与普通函数相比的好处是什么?我错过了什么吗?为什么要使用它们?

1个回答

24
有时候您需要定义并立即调用一个函数,而且只需要执行一次,这种情况下匿名函数可以帮到您。在这种情况下,给函数命名再去调用就显得多余了。
此外,有时候您想为变量创建一个命名空间,那么匿名函数也会帮到您。例如:
(function($) {
    $.fn.pluginName = function(opt) {
        // implementation goes here...
    }
}(jQuery));
在上述情况下,您可以在代码中安全地使用 $ 作为 jQuery 的代名词。
如果您按如下所示的名称定义函数,则它将创建具有您定义的函数名称的全局变量。
function myFunction() {
    // function code goes here.
}
myFunction();

但如果你没有定义一个名称,它就不会创建任何全局变量,也不会污染你的全局命名空间。

(function myFunction() {
    // function code goes here.
}());

只有在代码中需要从不同的位置调用函数时,具有名称的函数才是有用的。


2
当您使用IIFE时,确实会有一个额外的变量名称可用,但在我看来,选择一个描述函数的良好名称,以便您无需阅读整个函数即可知道其功能,远远超过了该优点。 - Alexander Derck
6
有时,良好命名的函数确实很有用,但当你编写一个许多人将使用的库时,你编写的函数可能会被其他脚本的函数覆盖存在风险。 - Mohammad Usman
好的观点,当有许多不同的脚本加载时,它们肯定会很有益。 - Alexander Derck
@AlexanderDerck,这就是所谓的命名空间污染的问题所在。当谈到模块时,在定义作用域函数时起相同名称可能会带来一些潜在问题。如果包含脚本中存在与作用域函数同名的变量,那么在引入模块时,该变量将被覆盖。由于最好将函数的名称与模块相同,因此无法提供任何信息。 - Rune FS
@RuneFS 我认为它只对大型项目有用,这些项目有很多不同的人在工作。对于小项目(我现在拥有的),我会坚持使用命名函数以保持清晰,因为我只使用jQuery和最多一个文件。感谢您的建议! - Alexander Derck
6
补充一点:即使你使用IIFE,良好的做法也是给它命名,例如: (function foo() { console.log("Hii"); })(); 这将有助于在调试或记录时进行堆栈跟踪。 另一个重要的观点是,IIFE很有用,因为它们仅在需要时被放入堆栈中才被调用。因此,当我们调用IIFE时,它会被加载,其作用域会被创建,并且一旦完成工作,如果没有在IIFE属性上维护闭包,它就会被释放。在后一种情况下,即非IIFE方法,首先会被提升,然后被加载,并且会一直保留在内存中,直到关闭标签页。 - user2485435

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