2012-09-17 31 views
11

teniendo un poco de dolor de cabeza tratando de resolver esto. Lo que quiero hacer es tener un setTimeout personalizado con argumentos sin teniendo que crear una función para pasarlo. Voy a explicar por código:setTimeout con argumentos

quieren evitar:

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

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

lo que yo quiero hacer es de alguna manera simplemente llamar a un 1 forro por igual:

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

se puede hacer esto o ¿solo puedes pasar una función sin argumento?

Respuesta

22

Puede pasar que una función anónima que invoca makeTimeout con los argumentos dados:

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

También hay una alternativa, utilizando bind:

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

Esta función, sin embargo, es una quinta ECMAScript La función de edición, aún no es compatible con todos los principales navegadores. Para compatibilidad, puede incluir bind 's source, que está disponible en MDN, lo que le permite usarlo en navegadores que no lo admiten de forma nativa.

DEMO.

+4

Cabe señalar que el valor pasado a 'makeTimeout' será el valor de' sp.name' cuando la función es llamada, lo que podría ser diferente al valor que tenía cuando fue llamado 'setTImeout'. – RobG

+0

De acuerdo con http://kangax.github.io/es5-compat-table/#Function.prototype.bind, bind ahora es compatible con los principales navegadores. –

+0

Como dijo RobG, para hacer que esto funcione al 100%, necesita usar un cierre https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures Para cuando expira el tiempo de espera, el valor 'sp.name' puede haber cambiado. – ikromm

4

Si no desea declarar una función por separado, puede utilizar una expresión de función invocada inmediatamente y el cierre, p. Ej.

// Parameter to use 
var bar = 'bar'; 

// Function to call 
function foo(arg) { 
    alert(arg); 
} 

// Go… 
setTimeout(
    (function(arg1){ 
    return function(){ 
     foo(arg1); 
    }; 
    }(bar)), 2000); 

Como alternativa, puede utilizar la función constructora:

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

O puede utilizar una cadena:

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

que es esencialmente la misma cosa. Ahora esperar a gritos de "pero eso es como usar eval, y todo el mundo sabe eval es malo y una brecha de seguridad masiva - todos sus primogénitos están condenados"

Pero en serio, eval (y el constructor de funciones) son ineficientes y puede conducir a una programación perezosa, por lo tanto, use otra opción, como la primera anterior.

2

Parece que la capacidad se ha añadido a algunos navegadores pasar parámetros a setTimeout:

sintaxis:setTimeout (function (p1,p2) {},1000,p1,p2);(añada tantas params como desee)

Si desea asegurarse de que funciona en todas partes, puede usar el código adjunto.

Nota: Si desea establecer un tiempo de espera inmediatamente después de instalarlo, lo mejor es utilizar el parámetro de devolución de llamada y hacerlo allí

por ejemplo

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

Esto se debe a usa un truco para detectar si es necesario, estableciendo un tiempo de espera muy corto y contando los parámetros.

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