2012-09-17 9 views
11

avoir un peu mal à la tête en essayant de résoudre ce problème. Ce que je veux faire est d'avoir un setTimeout personnalisé avec les arguments sans sortir avoir à créer une fonction pour le passer. Laissez-moi vous expliquer par code:setTimeout avec des arguments

Vous voulez éviter:

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

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

ce que je veux faire est d'une certaine façon il suffit d'appeler un 1 revêtement par comme:

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

peut-il être fait ou pouvez-vous seulement passer une fonction sans argument?

Répondre

22

Vous pouvez passer une fonction anonyme qui invoque makeTimeout avec les arguments donnés:

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

Il y a aussi une alternative, en utilisant bind:

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

Cette fonction, cependant, est un 5 ECMAScript Fonction d'édition, pas encore pris en charge dans tous les principaux navigateurs. Pour des raisons de compatibilité, vous pouvez inclure le source de bind, disponible sur MDN, qui vous permet de l'utiliser dans les navigateurs qui ne le prennent pas en charge de manière native.

DEMO.

+4

Il convient de noter que la valeur passée à 'makeTimeout' sera la valeur de' sp.name' lorsque la fonction est appelée, ce qui pourrait être différente de la valeur qu'il avait quand 'setTImeout' a été appelé. – RobG

+0

Selon http://kangax.github.io/es5-compat-table/#Function.prototype.bind, bind est désormais pris en charge par les principaux navigateurs. –

+0

Comme RobG l'a dit, pour que cette chose fonctionne à 100%, vous devez utiliser une fermeture https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures Au moment où le délai expire, la valeur 'sp.name' peut avoir changé. – ikromm

4

Si vous ne souhaitez pas déclarer une fonction distincte, vous pouvez utiliser une expression de fonction invoquée immédiatement et une fermeture, par ex.

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

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

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

Vous pouvez également utiliser le constructeur de la fonction:

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

Ou vous pouvez utiliser une chaîne:

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

qui est essentiellement la même chose. Maintenant, attendez pour hurlements de « mais c'est comme l'utilisation de eval, et tout le monde sait eval est mal et une brèche de sécurité massif - tous vos premiers-nés sont condamnés »

Mais sérieusement, eval (et le constructeur Function) sont inefficaces et peut mener à la programmation paresseuse, alors utilisez une autre option, comme la première ci-dessus.

2

Il semble que la capacité a été ajouté à certains navigateurs passer des paramètres à setTimeout:

Syntaxe:setTimeout (function (p1,p2) {},1000,p1,p2);(ajouter autant de params que vous voulez)

Si vous voulez vous assurer qu'il fonctionne partout, vous pouvez utiliser le code joint.

Note: Si vous souhaitez définir un délai d'attente immédiatement après l'avoir installé, il est préférable d'utiliser le paramètre de rappel et de le faire là-dedans

par exemple

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

En effet, il utilise une astuce pour détecter si cela est nécessaire, en définissant un délai d'attente très court et en comptant les paramètres.

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