如何在JavaScript中调用自执行函数?

如何在JavaScript中调用自执行函数?,javascript,Javascript,当我有一些代码时,我需要不止一次地执行它,我把它包装在一个函数中,这样我就不必重复我自己。此外,有时还需要在页面加载时执行此代码。现在我这样做: function foo() { alert('hello'); } foo(); (function foo() { alert('hello'); })(); 我宁愿这样做: function foo() { alert('hello'); } foo(); (function foo() { alert('hel

当我有一些代码时,我需要不止一次地执行它,我把它包装在一个函数中,这样我就不必重复我自己。此外,有时还需要在页面加载时执行此代码。现在我这样做:

function foo() {
   alert('hello');
}

foo();
(function foo() {
   alert('hello');
})();
我宁愿这样做:

function foo() {
   alert('hello');
}

foo();
(function foo() {
   alert('hello');
})();
问题是,这只会在页面加载时执行,但如果我尝试在以后使用
foo()
调用它,它将不起作用


我猜这是一个范围问题,但是有没有办法让自执行函数在以后被调用时工作?

如果函数不依赖返回值,您可以这样做

var foo = (function bar() {
   alert('hello');
   return bar;
})();   // hello

foo();  // hello
这将使用命名函数表达式中的本地引用
bar
,将函数返回到外部
foo
变量


或者,即使有,您也可以将返回值设置为有条件的

var foo = (function bar() {
   alert('hello');
   return foo ? "some other value" : bar;
})();   // hello

alert( foo() );  // hello --- some other value
或者只是手动分配给变量,而不是返回

var foo; 
(function bar() {
   alert('hello');
   foo = bar;
})();   // hello

foo();  // hello

如所述,IE的某些版本会将标识符泄漏到封闭的变量范围中。该标识符将引用您创建的函数的副本。为了使您的NFE IE安全(r),您可以取消该引用

bar = null;

请注意,标识符仍然会在作用域链上隐藏具有相同名称的标识符。空值化无助于此,并且无法删除局部变量,因此请明智地选择NFE名称。

要从外部调用,函数必须从外部可见。理想情况下,您应该让自执行函数将其注入一些传入的上下文中(在本例中,是引用全局上下文的
this
):

​ 可以找到更有趣的模式。

如果
foo()
是一个全局函数,即
窗口的属性,则可以执行以下操作:

(window.foo = function() {
   alert('hello');
})();

// at some later time
foo();
第一组括号中的表达式执行赋值以创建
foo
,但也计算为函数,因此您可以在末尾使用
()
立即调用它


即使函数应该返回一个值,此模式也可以工作。

第二个函数
foo
是函数定义表达式

在函数定义表达式中,根据“Javascript最终指南”,只能使用函数本身中的名称调用函数:

对于函数定义表达式,名称是可选的:如果存在,则名称仅指函数体中的函数对象

它可以在递归函数定义表达式中使用

例如:

var f = function factorial(n) {
    if (n == 0 || n == 1)
        return 1;
    else
        return n * factorial(n-1);
}

我不确定这是不是最好的方法。我想过一段时间这会变得非常混乱。可能的重复。也可能重复(哪个答案更好,IMHO,但问题的措辞不太准确。)@apsillers这个问题是重复的,但1的答案只是说做我已经在做的事。@Jake True;这就是我发布第二个链接的原因。命名函数表达式应该非常有用,但大多数人都不推荐它们。e、 g.在上面的
typeof bar中
显示“函数”,即使是放在生命之前。@RobG:True,但这通常是一个无害的问题。
bar
泄漏,甚至创建了一个重复的函数,这一事实可能只有在使用封闭作用域中的标识符引用作用域链上的变量时才会起作用。这不是一个问题,但通常函数表达式的目的是使函数保持“私有”。允许它成为一个全局函数可能会产生意想不到的后果,尤其是在更大的项目中。@RobG:这是一个很好的观点。我将添加一个关于取消IE8和更低版本的泄漏标识符的注释。(如果我没记错的话,IE9压扁了这个。)-不幸的是,超过一半的IE web访问者(大约10%的访问者)使用8或更低。通过
这个
会更有意义,因为它保证在全局代码中引用全局对象,
窗口
不保证引用任何东西,或者甚至被定义。@RobG:是的,它会:-)我只是提供了一个例子,我已经在上下文中明确提到了一些传递的。由OP决定哪个上下文对他最合适,所以你有好(坏?)的同伴。:-)+1没有理由对当地人也不能这样做<代码>var foo;(foo=func…})(
谢谢@amnotiam。关于当地人,你当然是对的。出于某种原因,当我写下这个答案时,我试图把它作为一个单独的语句来保存,并避免使用var语句——我现在甚至不记得为什么了。