2012-09-17 43 views
11

嘗試解決這個問題時有點頭疼。我想要做的是有一個自定義的setTimeout,參數不得不創建一個函數來傳遞它。讓我的代碼解釋:帶參數的setTimeout

想要避免:

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

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

我想要做的是某種程度上只是調用1個襯墊由這樣的:

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

可以這樣做或你只能傳遞一個無參數函數嗎?

回答

22

你可以通過它調用makeTimeout使用給定參數的匿名函數:

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

還有一個替代方案,使用bind

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

這個功能,但是,是的ECMAScript 5版功能,尚未在所有主流瀏覽器中支持。爲了兼容性,您可以包括bindsource(可在MDN上獲得),允許您在本地不支持它的瀏覽器中使用它。

DEMO

+4

需要注意的是,當調用函數時,傳遞給'makeTimeout'的值將是'sp.name'的值,可能與調用'setTImeout'時的值不同。 – RobG

+0

根據http://kangax.github.io/es5-compat-table/#Function.prototype.bind,主要瀏覽器現在支持綁定。 –

+0

正如RobG所說,爲了使這個工作100%正常工作,您需要使用關閉 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures 在超時過期時,值'sp.name'可能已經改變。 – ikromm

4

如果您不想聲明單獨的函數,則可以使用立即調用的函數表達式和閉包,例如,

// 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(與功能構造函數)是效率低下,會導致懶惰的編程,所以使用另一個選項,比如上面的第一個選項。

2

看來的能力已經被添加到一些瀏覽器傳遞參數的setTimeout:

語法:setTimeout (function (p1,p2) {},1000,p1,p2);(只要你想添加儘可能多的PARAMS)

如果你想確保它的工作原理到處都可以使用附帶的代碼。

注:如果你想在安裝後立即設置超時,最好使用回調參數,做它在那裏

例如

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); 
}