使用需要参数的非匿名函数的setInterval必须在匿名函数内.为什么?

cod*_*ppy 8 javascript jquery

好的,我已经在jquery/javascript中查看了有关setInterval的几个帖子和其他地方关于答案的烦人的事情是我不知道为什么解决方案有效.

请考虑:

使用匿名函数,我们可以设置警报,重复输出"兔子":

setInterval(function(){
  alert("bunnies")
},3000);
Run Code Online (Sandbox Code Playgroud)

但是如果我们想要使用非匿名函数,我们必须编写代码

的setInterval(跳,3000);

功能:

function hop(){
    alert("bunnies");
}
Run Code Online (Sandbox Code Playgroud)

如果我们尝试编码:

setInterval(hop(),3000);
Run Code Online (Sandbox Code Playgroud)

跳执行但只执行一次.我不明白为什么会这样.我已经阅读了各种SO,这意味着我们需要传递对setInterval的引用.这是否意味着第一个形式setInterval(hop,3000); 通过引用传递.如果是这样可以解释一下吗?

因此我们有一个问题.显然,希望能够将参数传递给函数跳像.....

setInterval(hop("bunnies"),3000);
Run Code Online (Sandbox Code Playgroud)

功能:

function hop(msg){
    alert(msg);
}
Run Code Online (Sandbox Code Playgroud)

这确实会导致调用hop并输出"bunnies",但同样只调用一次该函数.

因此,只要我能解决将参数传递给由setInterval控制的函数的唯一方法是将其合并到匿名函数中:

setInterval(function(){
 hop("bunnies")
},3000);
Run Code Online (Sandbox Code Playgroud)

这传递了参数并重复执行跳跃,每隔3秒警告我们一个兔子(非常重要的是要警告兔子).

因此问题:

  1. 这是唯一允许您传入参数的语法.
  2. 为什么setInterval(hop("bunnies"),3000); 不行.

tec*_*bar 13

setInterval期望函数作为第一个参数.当你尝试:

setInterval(function() {...}, 100);
Run Code Online (Sandbox Code Playgroud)

要么

setInterval(funcName, 100);
Run Code Online (Sandbox Code Playgroud)

你正确传递一个函数.

然而,当您尝试时setInterval(funcName(), 100);,您实际上正在调用该函数并将其返回值传递给setInterval不正确的值.

  • 我正在写这个确切的事情. (2认同)

Que*_*tin 6

为什么不起作用setInterval(hop("bunnies"),3000);.

setInterval(hop("bunnies"),3000);将hop 立即调用,然后将其返回值(undefined)传递给setInterval(它将被忽略,因为它不是函数或字符串).

这是唯一允许您传入参数的语法.

不,但它是最好的支持.

另一种语法是

 setInterval(hop, 3000, "bunnies")
Run Code Online (Sandbox Code Playgroud)


tst*_*ker 6

1.这是唯一允许您传入参数的语法吗?

是的,这是我能想到的唯一直接的方式......

setInterval(function(){
    hop("bunnies")
},3000);
Run Code Online (Sandbox Code Playgroud)

...但是如果你必须处理很多间隔,你当然可以写一个辅助函数,例如:

function Looper() {
    this.loops = {};
    this.start = function(name, fn, interval, params) {
        this.loops[name] = setInterval(function() {
            fn.apply(null, params);  // maybe bind the function?
        }, interval);
    };
    this.stop = function(name) {
        clearInterval(this.loops[name]);
    };
}
Run Code Online (Sandbox Code Playgroud)

(试试吧:http://jsfiddle.net/ceHMs/)

你会像这样使用它:

function say(name, msg){ console.log(name,':',msg) };
function shout(name, msg){ console.log(name,':',msg.toUpperCase()) };

var looper = new Looper();
looper.start('say', say, 1000, ['clock' 'tick']);
looper.start('shout', shout, 2000, ['clock' 'tack']);
// ... later ...
looper.stop('shout');
Run Code Online (Sandbox Code Playgroud)

但你必须评估这是否真的是必要的.


2.为什么不起作用setInterval(hop("bunnies"),3000);.

这是因为setInterval需要一个对应该每隔几毫秒执行一次的Function的引用.

括号是这里的关键.函数名后跟括号确实执行给定的函数并返回函数的结果,因此您不会传递对setInterval的引用,而是传递函数hop('bunnies')的返回值.函数的引用只是函数的名称.如果要调用引用的函数,只需在引用中附加括号即可.琐碎的例子:

function executeFunction(fn){
    fn();
};
Run Code Online (Sandbox Code Playgroud)

知道了这一点,我们实际上可以修改你的跳跃功能,使其适用于setInterval(hop("bunnies"),3000);:

function hop(msg){
    return function(){ alert(msg) }
}
Run Code Online (Sandbox Code Playgroud)

但这几乎与在setInterval调用中直接使用匿名函数完全相同.现在你只是在调用hop时返回那个匿名函数,这会使你的setIntervall调用更短.

最后,它归结为您的个人偏好和具体用例.大多数情况下,直接在setInterval中使用匿名函数的方法是最明显的方法,也是其他人最容易理解的方法.