关于javascript:(function(){/ * … * /})()之间的区别是什么? 和(function($){/ * … * /})(jQuery);

What is the difference between (function(){/*…*/})(); and (function($){/*…*/})(jQuery);

有什么区别:

1
2
3
(function() {
     /*..........*/
})();

并且:

1
2
3
(function($) {
     /*..........*/
})(jQuery);


其他人解释了不同之处,但不是为什么你使用后者。

$变量最常用于jQuery。如果你有一个加载jQuery的脚本标签和另一个加载你的代码的脚本标签,那就完全没问题了。现在将prototype.js投入混合。如果你加载prototype.js然后加载jQuery,$仍然是jQuery。反过来,现在$是prototype.js。

如果您尝试在此类页面上使用$,则可能会出现错误或奇怪的行为。

StackOverflow上有很多关于这个问题的问题。插件不应该对它们加载的页面有很多假设,所以他们在防御中使用这种模式。


i am asking if there is difference between (function(){/…/})(); and (function($){/…/})(jQuery);

有点不同。如果(function($){/*…*/})(jQuery);并且缺少jQuery,您将在页面加载后立即收到错误消息。当jQuery之前包含基于jquery的代码时,检测jquery absense或脚本包含的顺序不正确更简单。

(function(){/*…*/})();的情况下,当此构造中的代码实际调用jQuery方法之一时,您将收到错误消息。检测此错误更难,但另一方面,您可以在jquery之前包含基于jquery的脚本。

我更喜欢第一种情况。


其他答案相当分散,所以我想对这个问题给出更详细的答案。

如果您了解,主要问题可以自行回答。

(function(argument){ /*...*/ })(value);是什么意思?

这是一个快速手版:

1
2
3
4
var tempFunction = function(argument){
  /* ... */
}
tempFunction(value);

无需经历为一个功能创造一个新的可怕名称的麻烦,你只会打电话一次而忘记。这些函数称为anonymous function,因为它们没有给出名称。

所以(function(){/*...*/})()创建一个不接受任何参数的函数并立即执行它,而(function($){/*...*/})(jQuery)创建一个接受一个名为$的参数的函数,并赋予它jQuery的值。

既然我们知道这个表达意味着什么,那么我们首先想到的就是

"为什么?"。是不是$ jQuery了?

好吧,不完全是。我们永远无法 $jQuery的别名,但其他库也可以使用相同的别名。正如用户@FakeRainBrigand在他的回答中已经指出的那样,prototype.js也使用$作为别名。在这种情况下,无论哪个库将其值分配给$,都会胜出。

(function($){...})(jQuery)的做法与其他编程语言中的别名导入非常相似。您明确告诉系统您的功能:

  • 需要名为jQuery的对象/库,以及
  • 在您的函数中,$表示jQuery
  • 因此,即使有人在以后覆盖新库以覆盖全局级别的别名$,您的插件/框架仍可按预期工作。

    因为javascript在变量赋值中是"灵活的",所以有些人(包括我)就像做事一样

    1
    var myApplication = (function($, undefined){ ... })(jQuery);

    应用相同的理解,很容易将第二个参数部分解释为:不为变量undefined赋值。所以我们可以肯定,即使有些白痴稍后将值赋给undefined,我们的if(checkVariable === undefined){}也不会破坏。 (这不是一个神话,人们真的会为undefined分配值)

    什么时候在javascript中常用?

    这种匿名函数实践最常见于为插件/库提供封装的过程中。

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    var jQuery = (function(){
      var publicFunction = function(){ /* ... */}
      var privateFunction = function(){ /* ... */}

      return {
        publicFunction : publicFunction
      }
    })();

    这样,只有jQuery.publicFunction()在全局范围内公开,privateFunction()保持私有。

    但是,当然,只要您想创建一个函数,立即调用它并将其丢弃,它也会被使用。 (例如,作为异步函数的回调)

    对于奖金问题

    why they used (function(){}() twice in the below code?

    好吧,很可能是因为他们不知道自己在做什么。我想不出任何理由将嵌套函数放入其中。一个都没有。


    第二种形式(function($){/*…*/})(jQuery);在您没有(或不能)严格执行您的网站上的代码的环境中工作时可能会稍微安全一些。

    我曾经在一个包含大量第三方广告的大型网站上工作。这些广告通常会不安全地注入自己的jQuery版本,偶尔也会覆盖jQuery的全局$对象。因此,根据我们编写代码的方式,我们可能会调用不再存在的方法或者与我们预期的方式略有不同的方法。这可能无法调试,因为某些广告永远不会出现在我们的区域或被排除在我们的环境之外。这意味着我们必须极其保护范围,在任何广告代码有机会加载之前注入我们的依赖关系,命名必须是全局的任何东西,并且不要与我们混淆。


    它们都是Immediately Invoked Function Expression的例子。从这个意义上说,(function(){/*…*/})();(function($){/*…*/})(jQuery);之间没有区别。因此,在(function(){/*…*/})();中包含(function($){/*…*/})(jQuery);不会带来任何好处

    执行函数时会创建新的执行上下文。因此,当执行(function(){/*…*/})();时,会创建一个上下文。再次执行(function($){/*…*/})(jQuery);时,会创建另一个上下文。由于没有使用第一个上下文(即没有在其中声明变量),我看不到包装带来的任何好处。

    1
    2
    3
    4
    5
    6
    (function() { // <-- execution context which is not used
      (function($) { // <-- another execution context
       "use strict";
         /*..........*/
      })(jQuery);
    })();

    使用此(function(){/*…*/})();,您不会将任何参数传递给内部函数,而使用此(function($){/*…*/})(jQuery);,您将jQuery作为参数传递给内部函数并期望其值为$(这意味着,您将是能够在内部函数中使用jQuery

    例如:

    1
    2
    3
    4
    5
    (function($){
      $(document).ready(function() {
        console.log('all resources loaded');
      })
    })(jQuery);


    它们都是封闭的。第一个是一个匿名函数,它将触发立即内部的任何格式良好的代码。第二个是jQuery闭包。这是jQuery库如何启动它将其代码包装在JQuery对象中并公开它不是$符号。

    1
    2
    3
    (function(){}()) // this is a closure

    (function($){}(jQuery)) // is a closure that wraps the executed code inside of the jQuery returned object and exposes it via the $.


    (function(){/*...*/})();未将$设置为IIFE内jQuery的引用,(function($){/*...*/})(jQuery);设置$或其他参数名称;例如。; (function(Z){/*...* Z("body") where Z : jQuery*/})(jQuery);作为IIFE内jQuery的参考