JavaScript上这两种类型的自执行函数之间的差异

JavaScript上这两种类型的自执行函数之间的差异,javascript,Javascript,我总是使用以下自执行函数,以避免在JavaScript中将代码暴露于全局范围: (function() { //Code comes here })(); 我相信这也被称为自动执行匿名函数。有时,我也会看到以下代码用于相同的目的: (function(d){ //Code comes here })(document.documentElement); 我不确定这里有什么不同,所以我要问这个问题 JavaScript上这两种类型的自动执行函数之间有什么区别(或区别?下面的代

我总是使用以下自执行函数,以避免在JavaScript中将代码暴露于全局范围:

(function() { 
    //Code comes here
})();
我相信这也被称为自动执行匿名函数。有时,我也会看到以下代码用于相同的目的:

(function(d){
    //Code comes here
})(document.documentElement);
我不确定这里有什么不同,所以我要问这个问题


JavaScript上这两种类型的自动执行函数之间有什么区别(或区别?

下面的代码演示了正在发生的事情。实际上,
foo
bar
变量不存在,函数是匿名的

var foo = function() {}
foo();

var bar = function(d){}
bar(document.documentElement);
(函数(d){})(d)
方法称为闭包。它用于传递可能发生更改的变量值,例如在循环中

请看一个实例:

for(var i=0; i<10; i++) {
    document.links[i].onclick = function(){
        alert(i); //Will always alert 9
    }
}

for(var i=0;i第一个函数不带参数。第二个函数带单个参数。在函数内部,参数是
d
d
在调用函数时设置为
document.documentElement

请记住,函数参数和变量在本质上是一样的

第二个例子(基本上)只是

因为它避免了对
var
=
的需要

此模式有一些常见用途:

  • 创建词汇范围的变量(在看到Rob的答案后才想起这一点…)

  • 未传递的参数被设置为
    undefined
    。这很有用,因为通常
    undefined
    只是一个全局变量,可以设置为不同的值(如果您正在编写需要使用任意第三方脚本的库,这一点特别重要)


  • 第二个代码的作者似乎希望使用
    d
    作为在函数内部编写
    document.documentElement
    的较短方法。

    使用第二个表单和参数的一个原因是将您的代码与稍后加载到页面上的其他js代码(例如其他库或框架代码)隔离开来这可能会重新定义作为参数传入的变量

    一个常见的例子是,如果自执行匿名函数中的代码依赖于jQuery,并且希望使用$variable

    其他js框架也定义了$variable。如果将函数编码为:

    (function($){
    
        //Code comes here
    
    })(jQuery);
    
    然后,即使加载了定义$的其他库,也可以安全地将$用于jQuery

    我见过人们在他们的块中传递他们所需的所有“全局”变量时使用这种方法,例如窗口、文档、jQuery/$等

    安全总比抱歉好,特别是如果你使用了大量的第三方小部件和插件

    更新:
    正如其他人指出的那样,函数周围的括号集是一个闭包。在使用此模式的很多情况下,它们并不是严格必需的(@Rob W给出了一个很好的示例,其中它们是必需的)但是假设你有一个很长的函数体…外圆括号告诉其他阅读代码的人函数可能是自动执行的

    我在保罗·爱尔兰的视频中看到了对这种模式的最好解释:大约从1:30开始


    这个SO问题还有一些信息性的答案:

    如果要将参数传递给自动执行的匿名函数,请使用第二个。如果要在函数中使用与全局范围中其他函数同名的变量,这可能很有用:

    var a = "I'm outside the function scope",
        b = 13;
    alert(a);
    alert(b);
    (function(a,b){
         // a is different from the initial a
         alert(a);
         // same goes for b
         alert(b);
    })("I'm inside the function scope",Math.PI);
    
    使用以下内容也很有用:

    var a;
    console.log(a === undefined); // true
    undefined = true;
    console.log(a === undefined); // false
    (function(undefined){
        console.log(a === undefined); // true, no matter what value the variable "undefined" has assigned in the global scope
    })();
    
    当试图实现

    如果您担心效率,您可能会使用以下内容:

    var a = 2;
    (function(window){
        alert(a);
        // accessing a from the global scope gets translated 
        // to something like window.a, which is faster in this particular case
        // because we have the window object in the function scope
    })(window);
    

    第一个函数不接受任何参数,而第二个函数接受任何参数。好吧,我想但是
    document.documentElement
    也可以在函数内部使用。为什么要这样使用它?Javascript中的函数从来都不是“自执行”的,无论它们是否匿名。如果它们执行,总是会在某个地方调用函数。您的调用就在分号之前。@GregHewgill-hmm,那么我使用的术语是错误的吗?我总是听到这个术语,但我想在这种情况下它是隐喻性的。而且,这段代码与我上面引用的第一段代码相同:
    (function(w){}(window);
    这个术语是错误的,但是现在大多数JS程序员都理解为上面的例子。有很多人支持立即调用函数表达式(IIFE,发音为“iffy”)这个术语我认为这更有意义。谢谢。您的示例非常有趣和有用。我仍在试图弄清楚为什么第二个示例中总是提醒9:)@tugberk,因为循环从0移动到9,在每次枚举时更新变量
    i
    。当用户单击链接时,将显示
    i
    变量-这等于上次更新时的
    9
    。最后一个问题。这两个变量在DOM中使用时是否相同:
    (function(){}();
    (函数(w){})(窗口);
    1.为什么在这里使用函数表达式而不是函数声明?2.您调用的“闭包”不是闭包。只有在第一个函数中定义了变量
    w
    (function(undefined){
       //...
    }())
    
    (function($){
    
        //Code comes here
    
    })(jQuery);
    
    var a = "I'm outside the function scope",
        b = 13;
    alert(a);
    alert(b);
    (function(a,b){
         // a is different from the initial a
         alert(a);
         // same goes for b
         alert(b);
    })("I'm inside the function scope",Math.PI);
    
    var a;
    console.log(a === undefined); // true
    undefined = true;
    console.log(a === undefined); // false
    (function(undefined){
        console.log(a === undefined); // true, no matter what value the variable "undefined" has assigned in the global scope
    })();
    
    var a = 2;
    (function(window){
        alert(a);
        // accessing a from the global scope gets translated 
        // to something like window.a, which is faster in this particular case
        // because we have the window object in the function scope
    })(window);