问题 立即调用函数表达式(IIFE)对正常函数的好处


我是javascript的新手,我读到了 模块模式 提供某种命名空间并拥有私有和公共成员,例如:

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

一世  看到它的好处,因为它为您提供了面向对象编程的一些优点。但是我已经看到了许多没有分配给变量的IIFE的例子。与你调用的普通函数相比,这(就我所见)没有任何优势:

1. 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比我缺少的正常功能有什么好处?我为什么要用它们?


7919
2018-05-04 07:37


起源



答案:


有时您需要同时定义和调用函数,只需要一次,因此在这种情况下,匿名函数可以帮助您。在这种情况下,给函数命名然后调用它们就是多余的。

有时你想创建一个 namespace 为你的变量。所以 anonymous 功能也可以帮助你。例如

(function($) {
    $.fn.pluginName = function(opt) {
        // implementation goes here...
    }
}(jQuery));

在上述情况下,您可以安全使用 $ 如 jQuery 代码中的同义词。

如果您使用如下所示的名称定义函数,那么它将创建具有您定义的函数名称的全局变量。

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

但是如果你定义它没有名称,那么它将不会创建任何全局变量,并且你的全局命名空间不会被污染。

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

只有当您需要从代码中的不同位置调用时,带名称的函数才有用。


9
2018-05-04 07:55



当你使用IIFE时,你有一个额外的变量名称,但在我看来,能够选择一个好的名字,描述这个功能让你知道它的功能而不读取整个东西,远远超过了这个好处。 - Alexander Derck
是的,具有良好名称的函数有时是有用的,但是当您编写许多人将使用的库时,总是存在一个风险,即您编写的函数可能会被其他脚本中的函数覆盖。 - Mohammad Usman
好的一点是,当加载了很多不同的脚本时,它们肯定是有益的 - Alexander Derck
@AlexanderDerck这就是命名空间污染论点的全部内容。在谈论模块时,命名范围函数是一个潜在的坏事。如果包含脚本中的变量与您的作用域函数具有相同的名称,那么如果您的模块被包含在内,那么它将被覆盖,因为函数的最佳名称可能与它提供任何信息的模块相同。 - Rune FS
只是补充一下:即使你正在使用IIFE,良好的做法也是命名,即(function foo(){console.log(“Hii”);})();这将在调试或记录时帮助您进行堆栈跟踪。另一个重要的一点是IIFE很有用,因为只有在调用它们时才按需将它们放入堆栈。因此,当我们调用IIFE时,它被加载,其范围被创建,一旦完成工作,如果在IIFE的任何属性上保持No Closure,它就会被释放。在后一种情况下,即不是IIFE方法首先它将被提升然后加载并将保留在存储器中直到标签关闭 - user2485435


答案:


有时您需要同时定义和调用函数,只需要一次,因此在这种情况下,匿名函数可以帮助您。在这种情况下,给函数命名然后调用它们就是多余的。

有时你想创建一个 namespace 为你的变量。所以 anonymous 功能也可以帮助你。例如

(function($) {
    $.fn.pluginName = function(opt) {
        // implementation goes here...
    }
}(jQuery));

在上述情况下,您可以安全使用 $ 如 jQuery 代码中的同义词。

如果您使用如下所示的名称定义函数,那么它将创建具有您定义的函数名称的全局变量。

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

但是如果你定义它没有名称,那么它将不会创建任何全局变量,并且你的全局命名空间不会被污染。

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

只有当您需要从代码中的不同位置调用时,带名称的函数才有用。


9
2018-05-04 07:55



当你使用IIFE时,你有一个额外的变量名称,但在我看来,能够选择一个好的名字,描述这个功能让你知道它的功能而不读取整个东西,远远超过了这个好处。 - Alexander Derck
是的,具有良好名称的函数有时是有用的,但是当您编写许多人将使用的库时,总是存在一个风险,即您编写的函数可能会被其他脚本中的函数覆盖。 - Mohammad Usman
好的一点是,当加载了很多不同的脚本时,它们肯定是有益的 - Alexander Derck
@AlexanderDerck这就是命名空间污染论点的全部内容。在谈论模块时,命名范围函数是一个潜在的坏事。如果包含脚本中的变量与您的作用域函数具有相同的名称,那么如果您的模块被包含在内,那么它将被覆盖,因为函数的最佳名称可能与它提供任何信息的模块相同。 - Rune FS
只是补充一下:即使你正在使用IIFE,良好的做法也是命名,即(function foo(){console.log(“Hii”);})();这将在调试或记录时帮助您进行堆栈跟踪。另一个重要的一点是IIFE很有用,因为只有在调用它们时才按需将它们放入堆栈。因此,当我们调用IIFE时,它被加载,其范围被创建,一旦完成工作,如果在IIFE的任何属性上保持No Closure,它就会被释放。在后一种情况下,即不是IIFE方法首先它将被提升然后加载并将保留在存储器中直到标签关闭 - user2485435