La fonction de rappel est une fonction appelée via un pointeur de fonction. Si vous passez un pointeur de fonction (adresse) en paramètre à une autre fonction, et que ce pointeur est utilisé pour appeler la fonction vers laquelle il pointe, on dit qu'il s'agit d'une fonction de rappel. La fonction de rappel n'est pas appelée directement par l'implémenteur de la fonction, mais est appelée par une autre partie lorsqu'un événement ou une condition spécifique se produit pour répondre à l'événement ou à la condition.
En JavaScript, la définition spécifique d'une fonction de rappel est la suivante : la fonction A est passée en paramètre (référence de fonction) à une autre fonction B, et cette fonction B exécute la fonction A. Disons simplement que la fonction A est appelée fonction de rappel. S'il n'y a pas de nom (expression de fonction), on parle de fonction de rappel anonyme. Par conséquent, le rappel n'est pas nécessairement utilisé pour une utilisation asynchrone. Il est souvent utilisé dans des scénarios généraux synchrones (bloquants), par exemple pour exiger l'exécution d'une fonction de rappel après avoir effectué certaines opérations.
Exemple
Un exemple d'utilisation du rappel en synchronisation (blocage), le but est d'exécuter func2 une fois l'exécution du code func1 terminée.
var func1=function(callback){ //do something. (callback && typeof(callback) === "function") && callback(); } func1(func2); var func2=function(){ }
Occasions d'utilisation de la fonction de rappel
Chargement des ressources : exécuter le rappel après le chargement dynamique des fichiers js, exécuter le rappel après le chargement de l'iframe, rappel de l'opération ajax, exécuter le rappel après le chargement de l'image terminé, AJAX et ainsi de suite.
Les événements DOM et Node.js sont basés sur le mécanisme de rappel (les rappels Node.js peuvent avoir des problèmes avec l'imbrication des rappels multicouches).
Le temps de retard de setTimeout est de 0. Ce hack est souvent utilisé. La fonction appelée par settimeout est en fait l'incarnation d'un rappel
Appel en chaîne : lors d'un appel en chaîne, dans la méthode assignateur (setter). Il est facile d'implémenter des appels chaînés dans une méthode (ou une méthode qui ne renvoie pas de valeur elle-même), mais il est relativement difficile d'implémenter des appels chaînés avec un getter, car vous avez besoin du getter pour renvoyer les données dont vous avez besoin à la place de cela. pointeur , si vous souhaitez implémenter une méthode de chaîne, vous pouvez utiliser des fonctions de rappel pour implémenter les appels de fonction
setTimeout et setInterval pour obtenir leurs valeurs de retour. Étant donné que les deux fonctions sont asynchrones, c'est-à-dire que leur séquence d'appel est relativement indépendante du processus principal du programme, il n'y a aucun moyen d'attendre leurs valeurs de retour dans le corps, et le programme ne s'arrêtera pas et n'attendra pas quand elles le seront. ouvert. Sinon, la signification de setTimeout et setInterval sera perdue, cela n'a donc aucun sens d'utiliser return et le rappel ne peut être utilisé. La signification du rappel est d'informer la fonction d'agent du résultat de l'exécution du minuteur pour un traitement en temps opportun.
La fonction est aussi un objet
Si vous voulez comprendre la fonction de rappel, vous devez d'abord comprendre clairement les règles de la fonction. En JavaScript, les fonctions sont bizarres, mais ce sont bien des objets. Pour être précis, une fonction est un objet Function créé à l’aide du constructeur Function(). L'objet Function contient une chaîne qui contient le code JavaScript de la fonction. Si vous venez de C ou Java, cela peut paraître étrange. Comment le code peut-il être une chaîne ? Mais avec javascript, c'est monnaie courante. La distinction entre données et code est floue.
//可以这样创建函数 var fn = new Function("arg1", "arg2", "return arg1 * arg2;"); fn(2, 3); //6
L'un des avantages de cette méthode est que vous pouvez transmettre du code à d'autres fonctions, ou vous pouvez transmettre des variables ou des objets normaux (car le code n'est littéralement qu'un objet).
Passer une fonction en rappel
Il est facile de passer une fonction en paramètre.
function fn(arg1, arg2, callback){ var num = Math.ceil(Math.random() * (arg1 - arg2) + arg2); callback(num);//传递结果 } fn(10, 20, function(num){ console.log("Callback called! Num: " + num); });//结果为10和20之间的随机数
Peut-être que cela semble fastidieux ou même un peu stupide, alors pourquoi ne pas renvoyer les résultats normalement ? Mais quand vous devez utiliser une fonction de rappel, vous ne le pensez peut-être pas !
Les fonctions traditionnelles saisissent des données sous forme de paramètres et utilisent des instructions de retour pour renvoyer des valeurs. Théoriquement, il y a une instruction return à la fin de la fonction, qui est structurellement : un point d'entrée et un point de sortie. C'est plus facile à comprendre. Une fonction est essentiellement une cartographie du processus de mise en œuvre entre l'entrée et la sortie.
Cependant, lorsque le processus d'implémentation de la fonction est très long, choisissez-vous d'attendre la fin du traitement de la fonction, ou d'utiliser une fonction de rappel pour le traitement asynchrone ? Dans ce cas, il devient crucial d'utiliser des fonctions de rappel, par exemple : les requêtes AJAX. Si vous utilisez une fonction de rappel pour le traitement, le code peut continuer à effectuer d'autres tâches sans attendre en vain. Dans le développement réel, les appels asynchrones sont souvent utilisés en JavaScript, et c'est même fortement recommandé ici !
Vous trouverez ci-dessous un exemple plus complet d'utilisation d'AJAX pour charger un fichier XML et d'utilisation de la fonction call() pour appeler la fonction de rappel dans le contexte de l'objet demandé.
function fn(url, callback){ var httpRequest; //创建XHR httpRequest = window.XMLHttpRequest ? new XMLHttpRequest() : window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP" ) : undefined;//针对IE进行功能性检测 httpRequest.onreadystatechange = function(){ if(httpRequest.readystate === 4 && httpRequest.status === 200){ //状态判断 callback.call(httpRequest.responseXML); } }; httpRequest.open("GET", url); httpRequest.send(); } fn("text.xml", function(){ //调用函数 console.log(this); //此语句后输出 }); console.log("this will run before the above callback."); //此语句先输出
Nous demandons un traitement asynchrone, ce qui signifie que lorsque nous démarrons la requête, nous leur disons d'appeler notre fonction lorsqu'elle est terminée. Dans les situations réelles, le gestionnaire d'événements onreadystatechange doit également prendre en compte la situation d'échec de la demande. Ici, nous supposons que le fichier XML existe et peut être chargé avec succès par le navigateur. Dans cet exemple, la fonction asynchrone est affectée à l'événement onreadystatechange et ne sera donc pas exécutée immédiatement.
Finalement, la deuxième instruction console.log est exécutée en premier car la fonction de rappel n'est exécutée que lorsque la requête est terminée.
L'exemple ci-dessus n'est pas facile à comprendre, alors jetez un œil à l'exemple suivant :
function foo(){ var a = 10; return function(){ a *= 2; return a; }; } var f = foo(); f(); //return 20. f(); //return 40.
函数在外部调用,依然可以访问变量a。这都是因为javascript中的作用域是词法性的。函数式运行在定义它们的作用域中(上述例子中的foo内部的作用域),而不是运行此函数的作用域中。只要f被定义在foo中,它就可以访问foo中定义的所有的变量,即便是foo的执行已经结束。因为它的作用域会被保存下来,但也只有返回的那个函数才可以访问这个保存下来的作用域。返回一个内嵌匿名函数是创建闭包最常用的手段。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!