【问题标题】:Why can I not pass a function call (rather than a function reference or an anonymous function) to setTimeout()?为什么我不能将函数调用(而不是函数引用或匿名函数)传递给 setTimeout()?
【发布时间】:2017-04-10 07:29:56
【问题描述】:

请忽略此代码一无所获的事实,并为可能是一个愚蠢的问题道歉!

我知道我不能将函数调用作为第一个参数传递给setTimeout(),但是为什么我不能这样做?

let names = ['Andy', 'Ross', 'David'];

function printer (name) {
 console.log(name);
}

names.forEach(name => setTimeout(printer(name), 1000);

结果:

Andy
timers.js:327
    throw new TypeError('"callback" argument must be a function');
    ^

我可以通过使用对printer 的引用并使用bind()name 连同它一起发送来解决问题,但是为什么我必须采取这些额外的步骤?

let names = ['Andy', 'Ross', 'David'];

function printer (name) {
  console.log(name);
}

names.forEach(name => setTimeout(printer.bind(null, name), 1000));

结果:

Andy
Ross
David

【问题讨论】:

  • 因为 setTimeout 应该收到一个稍后应该调用的回调

标签: javascript functional-programming


【解决方案1】:

这是因为执行顺序。如果您将函数调用传递给 setTimeout,则该函数将立即执行,即该函数立即放入 javascript 的执行堆栈中。

如果您传递函数名称,即对函数的引用,则该函数仅在计时器完成后才会放入 javascript 线程的执行堆栈中。

【讨论】:

  • 谢谢,这很有道理!我很感激
【解决方案2】:

你可以试试这个:

setTimeout(function(){printer(name)}, 1000)

【讨论】:

    【解决方案3】:

    setTimeout 应该将函数作为其第一个参数。

    请参考:

    https://www.w3schools.com/jsref/met_win_settimeout.asp

    在这里,您将函数的结果作为第一个参数传递,即undefined

    【讨论】:

      【解决方案4】:

      你可以这样做:

      setTimeout(printer, 1000, name)
      

      【讨论】:

        【解决方案5】:

        传递函数引用的正确方法是使用回调。

        names.forEach(name => setTimeout(function() {
            printer(name);
        }, 1000));
        

        callbacks 包含对函数的引用。

        setTimeout(callbackFunction, milliseconds);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-01-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-06
          • 1970-01-01
          相关资源
          最近更新 更多