Javascript自执行函数“is not a function”

23

我有:

var Init = (function() {
   my js goes here
})();

当页面加载时,我的 JavaScript 代码可以正确执行。此外,我还有:

$('form :checkbox').change(function() {
   Init();
});

但是firebug说Init不是一个函数。

6个回答

57

这不是一个函数。

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

评估匿名函数然后。在这种情况下,评估的结果显然不会返回一个函数对象 :-)

考虑:

f = (function() {
   return "not a function :("
})()
alert(f())

f = (function() {
   return function () { return "Yay!" }
})()
alert(f())

编程愉快 :)


这里有一个函数,它将“执行某些操作一次”然后“返回该操作以便稍后执行”。(请参见Slaks的回答中的“您可以分配函数或调用函数;不能同时进行...”)。但是,我不会这样做。
Init = (function () {
  function Init () {
    alert("whee!")
  }
  Init()
  return Init
})()
Init()

这里有另一个解决方案(更短/更简洁),来自CD Sanchez(请参见评论),它利用了赋值运算符的求值结果是被赋值的值的事实:
var Init; (Init = function Init () {
  alert ("wee");
})()

7
最后两个代码片段可以简化为:var Init; (Init = function () { alert("wee"); })() - Cristian Sanchez
@CD Sanchez 非常好。我之前一直陷入了嵌套函数的困境,完全忽略了这种方法。答案已被更新以反映这一点。 - user166390
我现在正在使用 var Init = (function() { return function() {...} })(); 并且它正如我所希望的那样工作。现在,无论这是否是正确的模式,我都不知道。 - Phillip Senn
5
为什么不直接写 function Init(){} Init();?这样更清楚表达意图。 - Zecc
@Zecc 确实,那就是我会做的。把自己限制在问题中了。 - user166390
由于自执行函数是最新的热门事物。 - Phillip Senn

2
为了使Init作为一个函数执行,你的自执行函数内部的代码必须返回一个函数。唯一需要这样做的原因是如果你需要根据某些数据状态动态构建特定的函数。
var Init = (function() {

    // some code

    return function () {
        // some dynamic code dependent upon your previous code
    };

}());

2

Init不是一个函数,而是调用该函数的结果。

你可以创建一个函数或者调用它,但不能同时进行。

从技术上讲,你可以通过添加 return arguments.callee; 来返回该函数的调用,但这是一个愚蠢的想法。

你可能不应该调用该函数,而是需要理解你想让你的代码做什么。


1
你不能同时做两件事 - 是可以的:(function Init(){ /.../ })(); - dev-null-dweller
@dev:错误。那是一个命名表达式,而不是声明。http://kangax.github.com/nfe/#named-expr - SLaks
2
我认为也许“你可以分配一个函数或调用它;你不能两者兼而有之…”可能更能表达重点。 - user113716
2
赋值是一个有效的表达式,它返回分配给变量的对象的“值”。有了这个想法,您可以将赋值表达式括在括号中,并使用函数调用语法在分配后立即调用该函数:var Init; (Init = function () { ... })(); 请注意,(var Init = ...)() 不是有效的,因为 var 语句不是表达式。 - Cristian Sanchez
@CD Sanchez:赋值运算符从右向左工作。函数将首先被调用,然后其返回值将被分配给“Init”。这就是问题所在。你评论中的代码中括号是不必要的。 - user113716
显示剩余2条评论

1

快速解决方案 尝试像这样替换

var Init = function() {
   my js goes here
});

在加载时调用Init函数


我希望它是一个自执行函数,但也可以稍后调用它。 - Phillip Senn

1

你可以像上面那样做,但也可以这样做

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

你完全可以使用自命名的自执行函数。

如果你想避免使用名为Init的函数,你可以像CD Sanchez建议的那样在执行中进行赋值。

在函数末尾加上();就可以使其自执行。将函数用括号包裹起来可以使其匿名。但是似乎你不想让它匿名。


0
您可以尝试这样声明它:
(function Init(){ 
    /*...*/ 
})();

但是这将把这个函数的使用减少到它的主体中。

另一种方法是将声明与执行分开:

var Init = function(){
    /*...*/
    },
    initResult = (function(){ return Init(); })();

4
错了。那是一个命名表达式,而不是声明。它在函数外面是不可见的。http://kangax.github.com/nfe/#named-expr - SLaks
3
请不吝指正我,但我认为Init不会在封闭的作用域中被定义。也许您的意思是:var Init; (Init = function() { ... })(); - Cristian Sanchez
是的,抱歉,但这不正确。除了IE实现错误外,“Init”将不会像OP想要的那样在封闭范围内可用。 - user113716
@CD Sanchez:如果你不从Init返回一个函数,那么它实际上会与问题中的代码有相同的问题。 - user113716
1
@patrick dw:我不这么认为——它会将函数存储在Init中,然后执行赋值表达式的结果(这将是function() {}部分)。我过去使用过这个方法,效果非常好。但我也不是万无一失的——如果您发现我的推理有缺陷,请告诉我。 - Cristian Sanchez
显示剩余2条评论

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