一个自执行的匿名函数表达式

13

(function(){ ... })();

我看过了this篇帖子并且有一些理解。但是还有一些疑问,主要是关于它的使用方法。


像静态块一样!

由于它的行为类似于静态块自调用!),因此它可以用于初始化(比如一些虚构的常量)。

但是,它没有可用的getter来从中获取任何内容并在其他地方使用!


return, 必须吗?

解决上述问题的方法是在该函数中加入return,这样我就可以获取它返回的任何内容并使用它。


全局对象的引用?!

(function(window, undefined){})(this);

上述代码的解释在参考post的第二个答案中,我无法理解。如果有人能够更详细地解释(或者对我来说更简单),那将是非常好的。


更新:请查看下面的代码↓

var myElement=document.getElemetById("myElementId");
 (function(myElement){
      /**'this' here is 'myelement'???**/
 }; 
})(this);

1
"可用于初始化" 初始化什么? "以上的解决方案是要有一个return吗?" 什么? "全局对象的引用?!" 在全局范围内,this指的是全局对象。 - Felix Kling
它经常用于保护作用域,从而保持全局环境的清洁和避免命名空间冲突。 - Alex
@FelixKling 初始化变量、常量... 就像这样!有一个 return 语句将允许我从该函数中获取某些东西吗? - user2587132
顺便提一下,不要忘记把“狗球”塞进去:(function(){}()) - zclark
3个回答

15

常用的方法如下(称为命名空间)- 它通过立即执行函数并将所需的关键部分返回到变量中,从而创建了一个封装的作用域:

一个常见的方法是以下方式(称为命名空间)-它通过立即执行函数并将所需的关键部分返回给你的变量,从而创建了一个封装的作用域:

var yourNamespace = (function(window, undefined){ 
                    /* private code:*/
                    var privateVar = "foobar",
                        count = 0;
                    /* the stuff you want to use outside: */
                    return{
                       val: 5,
                       publicVar:privateVar,
                       func:function(){return ++count}
                    }
             })(this);// `this` is a reference to `window` here

这样,您可以通过您的yourNamespace变量访问所需的一切,同时仍然保持隐私并不污染全局对象。它被称为命名空间,并使用闭包范例。 您还可以将函数交给处理私有(对于封闭范围不可见)变量。

将未定义的参数移交的原因之一是,在ES3中,未定义是可写的,而在ES5中则不是这种情况。将this作为参数移交可以通过在范围内创建对全局window对象的直接引用来缩短查找时间。 然而,请非常谨慎 - 在ES5严格模式下,this不再是窗口,而会解析为undefined!! 因此,不再建议这样做!

移交window和undefined的另一个原因是,现在这些都是变量名,缩小器可以将它们压缩为一个字母。

if(myVar == undefined)
// could be compressed to:
if(a==x)

编辑你的问题:

在你的例子中,this 不会改变,你需要以下其中一种解决方案:

(function(myElement){/*your code*/})( document.getElemetById("myElementId") );
// or:
(function(){
    var myElement = document.getElemetById("myElementId");
    /* your code */ 
})();

除了 ES5 严格模式之外 - 是的。然而,this 不能被缩小,因为它是一个关键字,而写 window.something 可以。当您不需要对 window 的引用时,您当然可以省略该参数。 - Christoph
@rps 这里的模式实际上不会影响this的值。当函数执行时,参数名为window的参数被传递了this的值,在这种情况下是对window的引用。在某些情况下,this是一个关键字,也会在您的示例中引用window - robC
@rps 总结一下robC的(对我来说)令人困惑的评论:关键字this始终指向你正在执行的函数的“所有者”(即该函数是方法的对象)。在立即调用的函数表达式的情况下,它始终指向window或在ES5严格模式下指向undefined - Christoph
@Christoph 如果我传递给该函数的不是 window,它还能正常工作吗?(比如说,如果我想获取动态创建的隐藏元素的值并将其保持私有,所以我将其引用传递给自调用函数) - user2587132
@rps 更新了我的答案。不要被参数名字搞混,重要的是你传递给函数的参数。 - Christoph
显示剩余2条评论

2
一个 iife 的主要目的是创建一个封装的作用域。否则,您声明的所有变量都将进入全局作用域。
如果您需要从该作用域内访问某些内容,可以显式地创建一个全局命名空间变量,例如 window.myApp = {} 并将其附加在那里,例如 window.myApp.myMethod = function(){...}
window 传递到 iife 中的原因是它在作用域内创建了一个本地引用。这将缩短查找链以获得更好的性能,并且变量也可以被压缩。
回答您的更新问题:
使用这种模式创建一个本地引用元素的方法是将其作为参数提供给 IIFE:
(function(element){

    element.style.top = "100px";

})(document.getElementById("myId"));

“...但我不确定以这种方式使用模式是否有太多价值? 根据我的评论,this关键字不受影响,并且在此示例中仍将指向window
我认为this关键字让您感到困惑-它不一定与iife模式相关。 这里有一个很好的解释,说明了如何确定其值: http://net.tutsplus.com/tutorials/javascript-ajax/fully-understanding-the-this-keyword/

1
不只是 thisfunction(window) 也让我感到困惑!因为我以为那是用来标识函数“所有者”的,我还以为可以像普通函数一样使用 function(somethingelse) 来更改“所有者”(但这与普通函数的语法不同!)。但现在我完全理解了,谢谢。 - user2587132

2

>它可以用于初始化吗?...没有可用于提取任何内容的getter!

是的,它经常用于初始化,虽然不需要获取任何内容,但可能会有。

>以上问题的解决方法是什么?

不,它不必有返回值,但可能会有。如果有返回值,它将被传递给任何东西...即

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

a将返回任何值或未定义。

(function(window, undefined){})(this);

参数this将成为调用者 - 通常是window,但可能是任何对象。 如果您将此作为参数传递,则可以通过第一个参数(在本例中为window)访问它。

希望解释足够清楚。


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