Passer une fonction avec des paramètres comme paramètre?


151

Est-il possible de passer une fonction javascript avec des paramètres comme paramètre?

Exemple:

$(edit_link).click( changeViewMode( myvar ) );

5
Cela ressemble à JQuery, et c'est probablement le cas, mais ce n'est pas pertinent. L'utilisation ou les paramètres et les fonctions sont les mêmes quelles que soient les bibliothèques Javascript que vous utilisez.
Guffa

@Guffa - Je me demandais s'il devait être tagué avec jQuery
Russ Cam

1
@Lucia Veuillez envisager de modifier la réponse acceptée à cette question .
Michał Perłakowski

Si vous travaillez avec React, pensez à stackoverflow.com/questions/41369497/…
Michael Freidgeim

Réponses:


244

Utilisez une "fermeture":

$(edit_link).click(function(){ return changeViewMode(myvar); });

Cela crée un wrapper de fonction temporaire anonyme qui connaît le paramètre et le transmet à l'implémentation de rappel réelle.


3
Si vous souhaitez appeler une fonction sur un objet, vous devez appeler bind (). myObj.click (function () {this.doSomething ();} .bind (myObj)); Cela fera de "this" myObj.
Eli

1
N'est-ce pas un problème de performance lorsque l'on traite beaucoup de ces derniers? Par exemple, vous rendez un onPress d'affilée et vous avez 10 000 lignes. Cela crée un nouveau wrapper de fonction temporaire anonyme pour chaque ligne. Y a-t-il un autre moyen de le faire?
Joshua Pinter

@JoshuaPinter La technique en elle-même n'est pas un problème. Si vous avez besoin du même appel de fonction 10 000 fois, vous pouvez simplement enregistrer le wrapper dans une variable, de sorte que vous ne le créez qu'une seule fois. Si vous avez besoin de passer 10 000 contextes différents, vous ne pouvez pas faire grand-chose. Méfiez-vous de l'optimisation prématurée: comme toujours avec les performances, vous devez mesurer pour voir s'il y a un problème ou non. Les moteurs JavaScript actuels sont très puissants et pourraient optimiser le code de manière surprenante.
Ferdinand Beyer

@FerdinandBeyer Génial, merci pour la pointe. Un ami m'a dit que c'était une mauvaise pratique et que vous devriez plutôt l'utiliser this.myFunction = this.myFunction.bind(this)dans votre constructorméthode. Mais, comme vous l'avez dit, lorsque vous devez lui transmettre différents contextes pour chacun, comme toutes les différentes lignes sur lesquelles vous cliquez pour ouvrir la page de détail de cette ligne, ce n'est pas évitable.
Joshua Pinter

@FerdinandBeyer, disons que myvar est une chaîne et qu'elle est modifiée entre deux invocations consécutives de passage de changeViewMode en tant que fermeture, mais changeViewMode reçoit toujours la première valeur de myvar, je veux appeler la fonction de fermeture avec une valeur d'argument différente affectée à la même variable myvar,
nmxprime

42

Utilisez Function.prototype.bind(). Citant MDN:

La bind()méthode crée une nouvelle fonction qui, lorsqu'elle est appelée, a son thismot-clé défini sur la valeur fournie, avec une séquence donnée d'arguments précédant tout fourni lorsque la nouvelle fonction est appelée.

Il est pris en charge par tous les principaux navigateurs, y compris IE9 +.

Votre code doit ressembler à ceci:

$(edit_link).click(changeViewMode.bind(null, myvar));

Note latérale: je suppose que vous êtes dans un contexte global, c'est- thisà- dire que la variable est window; sinon utilisez à la thisplace de null.


Merci, cela m'a aidé. Utilisé comme ceci:$.ajax(url).done(handler.bind(this, var1, var2));
Thomas

2
Quelle option est la meilleure? Utiliser la fermeture ou utiliser la fonction de liaison? S'il vous plaît laissez-moi savoir s'il y a un impact sur les performances
Varun


15

Non, mais vous pouvez en passer un sans paramètres, et procédez comme suit:

$(edit_link).click(
  function() { changeViewMode(myvar); }
);

Donc, vous passez une fonction anonyme sans paramètres, cette fonction appelle ensuite votre fonction paramétrée avec la variable dans la fermeture



7

Ou si vous utilisez es6, vous devriez pouvoir utiliser une fonction fléchée

$(edit_link).click(() => changeViewMode(myvar));

2

Tu peux le faire

var message  = 'Hello World';

var callback = function(){
alert(this)
}.bind(message);

puis

function activate(callback){
  callback && callback();
}

activate(callback);

Ou si votre rappel contient une logique plus flexible, vous pouvez passer un objet.

Démo


2

Voici un exemple suivant l'approche de Ferdinand Beyer:

function function1()
{
    function2(function () { function3("parameter value"); });
}
function function2(functionToBindOnClick)
{
    $(".myButton").click(functionToBindOnClick);
}
function function3(message) { alert(message); }

Dans cet exemple, la "valeur du paramètre" est transmise de function1 à function3 via function2 en utilisant une fonction wrap.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.