【问题标题】:IIFE and parameterIIFE 和参数
【发布时间】:2015-02-14 17:18:53
【问题描述】:

这是代码

(function(x){
    // Some code here
})(1);

上面的代码是 IIFE,所以这意味着它只会被执行一次。 问题:为什么有人需要将参数传递给这个函数(在下面的例子中是 1)?

我可以在函数内部创建变量,如下所示

(function(){
    var x = 1;
    // Some code here
})();

这个问题不是关于闭包是如何工作的,而是关于为什么以及何时使用第一个 Code Pattern 以及何时使用第二个。

【问题讨论】:

  • 请看javascript-closure-inside-loops-simple-practical-example。 Bjorn Tipling 的答案包含带有传递参数的“有用的 IIFE”。
  • 显而易见的原因是因为他们希望能够改变 x 的值。
  • 你完全正确。唯一需要此构造的情况是,当您想要传递一个变量值并且该标识符将被函数中的某些本地对象遮蔽时。
  • @Andreas 好吧,显然不是。这个问题不是关于闭包是如何工作的,而是关于为什么以及何时使用第一个代码示例以及何时使用第二个。
  • @Teemu 感谢您的回复。刚刚看了你引用的例子,想说不使用参数和使用局部变量也可以得到同样的效果。所以两种变体都可以使用。var fs = [];变量 i, j; for (i=0; i

标签: javascript function syntax iife


【解决方案1】:

一方面,它可以被认为是风格问题。我更喜欢

(function (x, y, z) { … })(1, 2, 3);

结束

(function () { var x = 1; var y = 2; var z = 3; … })();

如果xyz 是我通常会作为参数而不是局部变量传递的(所以我声明它的位置取决于它们所持有的信息)。

但是,对于 jQuery 和其他代码,您基本上可以做的是别名某些名称:

(function (window, undefined) {
    // …
})(window);

这个 sn-p 做了两件事:

  • 它将全局window 重命名为本地window。在编写代码时,这绝对没有效果。但是当代码被缩小时,缩小器可以将 IIFE 的参数重命名为w——以及它在函数中的所有用法。这样,window 只需写出一次,这可能会节省相当多的字节。
  • 它声明了参数undefined,但没有传递任何东西给它。这会导致名为undefined 的参数保存值undefined。现在它不再那么重要了,但是旧版浏览器允许重新定义 undefined 的值,通过这样做,您可以确保没有其他代码会通过覆盖该值来干扰您的值(当然,这很糟糕要做的事情)。

【讨论】:

  • 第二点,我不会基于陈旧的编码约定进行编码,因为这会导致开发人员混淆。我们不会检查以确保有人没有将Array 变成鸭子。正如您所说,较新的浏览器将其定义为关键字。无论哪种方式,请使用thing == null(双等于,而不是三重)或'propertyName' in thing 检查未定义。这是我的惯例,因为我的代码中任何新手无法理解的额外位都会降低可读性。
  • @Katana314 我认为使用thing == null 来检查undefined 更糟糕,因为a)没有新手会知道这是检查undefined 和b)它具有检查的副作用null 也是。别介意你到处复制这个。 undefined 参数是一次性的,您已经完成了它。如果您不想处理这个问题,那就根本不要这样做,并假设 undefined 没有被重新定义。
  • 但是你必须在每个文件中复制未定义的东西;其中有组织的代码应该有几个来区分功能。一般来说,我想找到 null 以及 undefined;两者之间的差异对任何程序员都有帮助并不是很常见。
  • 感谢您的回复。这是我第一次听说未定义的重新定义问题——很有趣。关于别名:如果我使用局部变量(var w = window;),可以获得相同的效果。或者这里的想法是在函数内部继续使用窗口变量(而不是其他东西)?
  • @Tigrokonvel 是的,通过使用参数,您可以继续编写window,这样更容易理解。它还将允许缩小的问题与实际编写代码本身分开。这是一个别名,但名称相同。
【解决方案2】:

最可能的用例是 jQuery。

(function($) {
    console.log($);
})(jQuery);

这样,无论您加载何种其他库(如 Prototype 或 Mootools),您的代码在 IIFE 中始终是安全的。您还可以使用此模式传递其他库,例如 Prototype 和 Mootools。

(function($, P, Moo) {
    console.log($);
    console.log(P);
    console.log(Moo);
})(jQuery, $, $$);

希望这会有所帮助!

【讨论】:

  • @Tigrokonvel 例如库名没有冲突 :-)
  • @Grundy 仍然失明)您能否提供可能发生的冲突示例。
  • @Tigrokonvel 类似这样的:jQuery & Prototype Conflict
【解决方案3】:

考虑这两个事件处理程序的行为差异:

var tags = document.getElementsByTagName("a");
for (var i=0, t; t = tags[i]; i++) {
  t.addEventListener("click",
    (function (index) { 
      return function () { 
        console.log("iife - " + index); 
      };
    })(i)
  );
  t.addEventListener("click",
    function () { 
      var index = i;
      console.log("non iife - " + index); 
    }
  );    
}

demo

【讨论】:

  • 感谢您的回复。但是如果我使用局部变量可以得到同样的效果: t.addEventListener("click", (function () { var index = i; return function () { console.log("iife - " + index); }; })());
猜你喜欢
  • 1970-01-01
  • 2019-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多