J'ai besoin de créer une fonction qui ne peut être exécutée qu'une seule fois, à chaque fois après la première, elle ne sera pas exécutée. Je connais, grâce au C++ et à Java, les variables statiques qui peuvent faire le travail, mais j'aimerais savoir s'il existe un moyen plus élégant de le faire ?
Réponses
Trop de publicités?Si par "ne sera pas exécuté" vous voulez dire "ne fera rien s'il est appelé plus d'une fois", vous pouvez créer une fermeture :
var something = (function() {
var executed = false;
return function() {
if (!executed) {
executed = true;
// do something
}
};
})();
something(); // "do something" happens
something(); // nothing happens
En réponse à un commentaire de @Vladloffe (maintenant supprimé) : Avec une variable globale, un autre code pourrait réinitialiser la valeur de l'indicateur "exécuté" (quel que soit le nom que vous lui donnez). Avec une fermeture, un autre code n'a aucun moyen de le faire, que ce soit accidentellement ou délibérément.
Comme d'autres réponses ici le soulignent, plusieurs bibliothèques (telles que Underscore y Ramda ) ont une petite fonction d'utilité (généralement appelée once()
[*] ) qui accepte une fonction comme argument et renvoie une autre fonction qui appelle la fonction fournie exactement une fois, quel que soit le nombre de fois où la fonction renvoyée est appelée. La fonction retournée met également en cache la valeur retournée en premier par la fonction fournie et la retourne lors des appels suivants.
Cependant, si vous n'utilisez pas une telle bibliothèque tierce, mais que vous voulez quand même une fonction utilitaire (plutôt que la solution nonce que j'ai proposée ci-dessus), elle est assez facile à mettre en œuvre. La plus belle version que j'ai vue est la suivante celui-ci a été posté par David Walsh :
function once(fn, context) {
var result;
return function() {
if (fn) {
result = fn.apply(context || this, arguments);
fn = null;
}
return result;
};
}
Je serais enclin à changer fn = null;
a fn = context = null;
. Il n'y a aucune raison pour que la fermeture maintienne une référence à context
une fois fn
a été appelé.
Utilisation :
function something() { /* do something */ }
var one_something = once(something);
one_something(); // "do something" happens
one_something(); // nothing happens
[*] Sachez cependant que d'autres bibliothèques, telles que <a href="https://www.drupal.org/node/444344" rel="noreferrer">cette extension Drupal de jQuery </a>peut avoir une fonction nommée <code>once()</code> qui fait quelque chose de tout à fait différent.
Pointer vers un vide une fois qu'elle a été appelée :
function myFunc(){
myFunc = function(){}; // kill it as soon as it was called
console.log('call once and never again!'); // your stuff here
};
<button onClick=myFunc()>Call myFunc()</button>
Ou, comme ça :
var myFunc = function func(){
if( myFunc.fired ) return;
myFunc.fired = true;
console.log('called once and never again!'); // your stuff here
};
// even if referenced & "renamed"
((refToMyfunc)=>{
setInterval(refToMyfunc, 1000);
})(myFunc)
UnderscoreJs a une fonction qui fait cela, underscorejs.org/#once
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = function(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
memo = func.apply(this, arguments);
func = null;
return memo;
};
};
- Réponses précédentes
- Plus de réponses