【问题标题】:setTimeout with arguments带参数的 setTimeout
【发布时间】:2012-09-17 00:25:28
【问题描述】:

在尝试解决这个问题时有点头疼。我想要做的是有一个带有参数的自定义 setTimeout 必须创建一个函数来传递它。让我通过代码来解释:

想避免:

function makeTimeout(serial){
  serial.close();
}

setTimeout(makeTimeout(sp.name), 250);

我想要做的就是通过以下方式调用 1 班轮:

setTimeout(function(arg1){ .... }(argument_value), 250);

可以这样做还是只能传入无参数函数?

【问题讨论】:

    标签: javascript


    【解决方案1】:

    您可以向它传递一个匿名函数,该函数使用给定的参数调用makeTimeout

    setTimeout(function () {
      makeTimeout(sp.name);
    }, 250);
    

    还有一个替代方法,使用bind

    setTimeout(makeTimeout.bind(this, sp.name), 250);
    

    但是,此功能是 ECMAScript 第 5 版功能,尚未在所有主要浏览器中支持。为了兼容性,你可以包含 bindsource,它可以在 MDN 上找到,允许你在原生不支持它的浏览器中使用它。

    DEMO.

    【讨论】:

    【解决方案2】:

    如果不想声明单独的函数,可以使用立即调用的函数表达式和闭包,例如

    // Parameter to use
    var bar = 'bar';
    
    // Function to call
    function foo(arg) {
      alert(arg);
    }
    
    // Go…
    setTimeout(
      (function(arg1){
        return function(){
          foo(arg1);
        };
      }(bar)), 2000);
    

    或者,您可以使用函数构造函数:

    setTimeout( Function('foo(bar)'), 2000);
    

    或者你可以使用一个字符串:

    setTimeout('foo(bar)', 1000);
    

    本质上是一样的。现在等待“但这就像使用 eval 一样,每个人都知道 eval 是邪恶的并且是一个巨大的安全漏洞——你所有的长子都注定要失败!

    但说真的,eval(和 Function 构造函数)效率低下并且可能导致惰性编程,因此请使用其他选项,例如上面的第一个选项。

    【讨论】:

      【解决方案3】:

      似乎某些浏览器已添加该功能,可将参数传递给 setTimeout:

      语法: setTimeout (function (p1,p2) {},1000,p1,p2); (添加任意数量的参数)

      如果你想确保它在任何地方都能正常工作,你可以使用随附的代码。

      注意:如果你想在安装后立即设置超时,最好使用回调参数并在里面设置

      例如

      installSwizzledTimeout(function(param1,param2){
          setTimeout(myFunc,200,param1,param2);},param1,param2);
      }
      

      这是因为它使用了一个技巧来检测是否需要,通过设置一个非常短的超时并计算参数。

      window.swizzledSetTimeout = function (fn, ms) {
          if (arguments.length === 2) {
              //console.log("Bypassing swizzledSetTimeout");
              return window.originalSetTimeout(fn, ms);
          } else {
              var args = [];
              for (i = 2; i < arguments.length; i++) {
                  args.push(arguments[i])
              };
              //console.log("Setting swizzledSetTimeout for function (",args,") {...} in ",ms," msec");
              var retval = window.originalSetTimeout(function () {
                  //console.log("Invoking swizzledSetTimeout for function (",args,") {...}");
                  fn.apply(null, args);
              }, ms);
              return retval;
          }
      }
      
      function installSwizzledTimeout(cb) {
          var args = [];
          for (i = 1; i < arguments.length; i++) {
              args.push(arguments[i])
          };
          setTimeout(function (arg) {
              //console.log("arguments.length:",arguments.length,window.setTimeout.toString());
              if (arguments.length == 0) {
      
                  function doInstall() {
                      //console.log("Installing new setTimeout");
                      window.originalSetTimeout = window.setTimeout;
                      window.setTimeout = function setTimeout() {
                          return window.swizzledSetTimeout.apply(null, arguments);
                      };
                      if (cb) {
                          cb.apply(null, args);
                      };
                  }
      
                  if (window.setTimeout.toString().indexOf("swizzledSetTimeout") < 0) {
                      doInstall();
                  }
              } else {
                  //console.log("existing set time supports arguments ");
                  if (cb) {
                      cb.apply(null, args);
                  };
              }
          }, 0, 1, 2, 3, 4);
      }
      

      【讨论】:

        【解决方案4】:

        我有一个方法需要一个恒定的超时设置,也有最终执行函数的参数,所以我使用匿名函数做了如下操作:

        function checkPageLoaded(checker, callback, nextCallTime) {
            return () => {
                let checkoutLoader = document.querySelector(checker);
                if(checkoutLoader === null)
                    callback();
                else
                    setTimeout(checkPageLoaded(checker, callback, nextCallTime), nextCallTime);
            }
        }
        

        然后就这样调用它:

        setTimeout(checkPageLoaded('.loader', reloadPagination, 500), 500);
        

        这样,使用参数执行的所需函数将是定义为匿名函数的函数。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多