En JavaScript, une fonction n’est pas une « structure de langage magique », mais un type particulier de valeur.
La syntaxe que nous avons utilisée auparavant s'appelle une déclaration de fonction :
fonction direSalut() { alert( "Bonjour" ); }
Il existe une autre syntaxe pour créer une fonction appelée Function Expression .
Cela nous permet de créer une nouvelle fonction au milieu de n'importe quelle expression.
Par exemple:
disonsSalut = fonction() { alert( "Bonjour" ); } ;
Ici, nous pouvons voir une variable sayHi
obtenir une valeur, la nouvelle fonction, créée sous function() { alert("Hello"); }
.
Comme la création de fonction se produit dans le contexte de l’expression d’affectation (à droite de =
), il s’agit d’une Function Expression .
Veuillez noter qu'il n'y a pas de nom après le mot-clé function
. L'omission d'un nom est autorisée pour les expressions de fonction.
Ici, nous l'attribuons immédiatement à la variable, donc la signification de ces exemples de code est la même : « créez une fonction et mettez-la dans la variable sayHi
».
Dans des situations plus avancées, que nous verrons plus tard, une fonction peut être créée et immédiatement appelée ou programmée pour une exécution ultérieure, sans être stockée nulle part, restant ainsi anonyme.
Rappelons-le : peu importe la manière dont la fonction est créée, une fonction est une valeur. Les deux exemples ci-dessus stockent une fonction dans la variable sayHi
.
Nous pouvons même imprimer cette valeur en utilisant alert
:
fonction direSalut() { alert( "Bonjour" ); } alert( sayHi ); // affiche le code de la fonction
Veuillez noter que la dernière ligne n'exécute pas la fonction, car il n'y a pas de parenthèses après sayHi
. Il existe des langages de programmation dans lesquels toute mention d'un nom de fonction provoque son exécution, mais ce n'est pas le cas de JavaScript.
En JavaScript, une fonction est une valeur, nous pouvons donc la traiter comme une valeur. Le code ci-dessus montre sa représentation sous forme de chaîne, qui est le code source.
Certes, une fonction est une valeur spéciale, dans le sens où nous pouvons l'appeler comme sayHi()
.
Mais ça reste une valeur. Nous pouvons donc travailler avec cela comme avec d’autres types de valeurs.
On peut copier une fonction dans une autre variable :
function sayHi() { // (1) créer alert( "Bonjour" ); } let func = sayHi; // (2) copie fonction(); // Bonjour // (3) lancez la copie (ça marche) ! disBonjour(); // Bonjour // ça marche toujours aussi (pourquoi pas)
Voici ce qui se passe ci-dessus en détail :
La déclaration de fonction (1)
crée la fonction et la place dans la variable nommée sayHi
.
La ligne (2)
le copie dans la variable func
. Attention encore : il n'y a pas de parenthèses après sayHi
. S'il y en avait, alors func = sayHi()
écrirait le résultat de l'appel sayHi()
dans func
, pas dans la fonction sayHi
elle-même.
Maintenant, la fonction peut être appelée à la fois comme sayHi()
et func()
.
Nous aurions également pu utiliser une Function Expression pour déclarer sayHi
, dans la première ligne :
let sayHi = function() { // (1) créer alert( "Bonjour" ); } ; let func = sayHi; //...
Tout fonctionnerait de la même manière.
Pourquoi y a-t-il un point-virgule à la fin ?
Vous vous demandez peut-être pourquoi les expressions de fonction ont un point-virgule ;
à la fin, mais les déclarations de fonction ne :
fonction direSalut() { //... } disonsSalut = fonction() { //... } ;
La réponse est simple : une expression de fonction est créée ici sous function(…) {…}
à l'intérieur de l'instruction d'affectation : let sayHi = …;
. Le point-virgule ;
est recommandé à la fin de l'instruction, cela ne fait pas partie de la syntaxe de la fonction.
Le point-virgule serait là pour une affectation plus simple, comme let sayHi = 5;
, et il est également là pour une affectation de fonction.
Examinons d'autres exemples de transmission de fonctions en tant que valeurs et d'utilisation d'expressions de fonction.
Nous allons écrire une fonction ask(question, yes, no)
avec trois paramètres :
question
Texte de la question
yes
Fonction à exécuter si la réponse est « Oui »
no
Fonction à exécuter si la réponse est « Non »
La fonction doit poser la question
et, selon la réponse de l'utilisateur, appeler yes()
ou no()
:
fonction demander (question, oui, non) { si (confirmer(question)) oui() sinon non(); } fonction showOk() { alert( "Vous avez accepté." ); } fonction showAnnuler() { alert( "Vous avez annulé l'exécution." ); } // utilisation : les fonctions showOk, showCancel sont passées en arguments à demander request("Etes-vous d'accord ?", showOk, showCancel);
En pratique, ces fonctions sont très utiles. La principale différence entre une ask
réelle et l'exemple ci-dessus est que les fonctions réelles utilisent des moyens plus complexes pour interagir avec l'utilisateur qu'une simple confirm
. Dans le navigateur, ces fonctions dessinent généralement une jolie fenêtre de questions. Mais c'est une autre histoire.
Les arguments showOk
et showCancel
de ask
sont appelés fonctions de rappel ou simplement rappels .
L’idée est que nous transmettons une fonction et nous attendons à ce qu’elle soit « rappelée » plus tard si nécessaire. Dans notre cas, showOk
devient le rappel pour la réponse « oui » et showCancel
pour la réponse « non ».
Nous pouvons utiliser des expressions de fonction pour écrire une fonction équivalente et plus courte :
fonction demander (question, oui, non) { si (confirmer(question)) oui() sinon non(); } demander( "Êtes-vous d'accord?", function() { alert("Vous avez accepté."); }, function() { alert("Vous avez annulé l'exécution."); } );
Ici, les fonctions sont déclarées directement dans l'appel ask(...)
. Ils n’ont pas de nom et sont donc appelés anonymes . De telles fonctions ne sont pas accessibles en dehors de ask
(car elles ne sont pas affectées à des variables), mais c'est exactement ce que nous voulons ici.
Un tel code apparaît très naturellement dans nos scripts, c'est dans l'esprit de JavaScript.
Une fonction est une valeur représentant une « action »
Les valeurs régulières comme les chaînes ou les nombres représentent les données .
Une fonction peut être perçue comme une action .
Nous pouvons le transmettre entre variables et l'exécuter quand nous le souhaitons.
Formulons les principales différences entre les déclarations de fonction et les expressions.
Tout d’abord, la syntaxe : comment les différencier dans le code.
Déclaration de fonction : une fonction, déclarée sous forme d'instruction distincte, dans le flux de code principal :
// Déclaration de fonction fonction somme(a, b) { renvoyer a + b ; }
Expression de fonction : une fonction, créée dans une expression ou dans une autre construction syntaxique. Ici, la fonction est créée sur le côté droit de « l’expression d’affectation » =
:
//Expression de fonction soit somme = fonction (a, b) { renvoyer a + b ; } ;
La différence la plus subtile se produit lorsqu'une fonction est créée par le moteur JavaScript.
Une expression de fonction est créée lorsque l'exécution l'atteint et n'est utilisable qu'à partir de ce moment.
Une fois que le flux d'exécution passe du côté droit de l'affectation, let sum = function…
– c'est parti, la fonction est créée et peut être utilisée (attribuée, appelée, etc.) à partir de maintenant.
Les déclarations de fonction sont différentes.
Une déclaration de fonction peut être appelée avant d'être définie.
Par exemple, une déclaration de fonction globale est visible dans l'ensemble du script, peu importe où elle se trouve.
Cela est dû aux algorithmes internes. Lorsque JavaScript se prépare à exécuter le script, il y recherche d'abord les déclarations de fonction globales et crée les fonctions. On peut le considérer comme une « étape d’initialisation ».
Et une fois toutes les déclarations de fonction traitées, le code est exécuté. Il a donc accès à ces fonctions.
Par exemple, cela fonctionne :
sayBonjour("Jean"); // Bonjour, Jean fonction sayHi(nom) { alert( `Bonjour, ${name}` ); }
La déclaration de fonction sayHi
est créée lorsque JavaScript se prépare à démarrer le script et est visible partout dans celui-ci.
… S'il s'agissait d'une expression de fonction, cela ne fonctionnerait pas :
sayBonjour("Jean"); // erreur! let sayHi = function(name) { // (*) plus de magie alert( `Bonjour, ${name}` ); } ;
Les expressions de fonction sont créées lorsque l'exécution les atteint. Cela n'arriverait que dans la ligne (*)
. Trop tard.
Une autre particularité des déclarations de fonction est leur portée de bloc.
En mode strict, lorsqu'une déclaration de fonction se trouve dans un bloc de code, elle est visible partout à l'intérieur de ce bloc. Mais pas en dehors.
Par exemple, imaginons que nous devions déclarer une fonction welcome()
en fonction de la variable age
que nous obtenons lors de l'exécution. Et puis nous prévoyons de l’utiliser quelque temps plus tard.
Si nous utilisons la déclaration de fonction, cela ne fonctionnera pas comme prévu :
let age = prompt("Quel âge as-tu ?", 18); // déclare conditionnellement une fonction si (âge < 18) { fonction bienvenue() { alert("Bonjour !"); } } autre { fonction bienvenue() { alert("Salutations!"); } } // ...utilise-le plus tard accueillir(); // Erreur : l'accueil n'est pas défini
En effet, une déclaration de fonction n'est visible qu'à l'intérieur du bloc de code dans lequel elle réside.
Voici un autre exemple :
soit âge = 16 ; // prend 16 comme exemple si (âge < 18) { accueillir(); // (fonctionne) // | fonction bienvenue() { // | alert("Bonjour !"); // | La déclaration de fonction est disponible } // | partout dans le bloc où c'est déclaré // | accueillir(); // / (fonctionne) } autre { fonction bienvenue() { alert("Salutations!"); } } // Ici, nous n'avons plus d'accolades, // nous ne pouvons donc pas voir les déclarations de fonction faites à l'intérieur d'eux. accueillir(); // Erreur : l'accueil n'est pas défini
Que pouvons-nous faire pour rendre welcome
visible à l'extérieur de if
?
L'approche correcte serait d'utiliser une expression de fonction et d'attribuer welcome
à la variable déclarée en dehors de if
et ayant la visibilité appropriée.
Ce code fonctionne comme prévu :
let age = prompt("Quel âge as-tu ?", 18); laissez accueillir; si (âge < 18) { bienvenue = fonction() { alert("Bonjour !"); } ; } autre { bienvenue = fonction() { alert("Salutations!"); } ; } accueillir(); // ok maintenant
Ou pourrions-nous le simplifier encore davantage en utilisant un opérateur de point d'interrogation ?
:
let age = prompt("Quel âge as-tu ?", 18); let bienvenue = (âge < 18) ? function() { alert("Bonjour !"); } : function() { alert("Salutations !"); } ; accueillir(); // ok maintenant
Quand choisir la déclaration de fonction plutôt que l’expression de fonction ?
En règle générale, lorsque nous devons déclarer une fonction, la première chose à considérer est la syntaxe de déclaration de fonction. Cela donne plus de liberté dans la manière d'organiser notre code, car nous pouvons appeler de telles fonctions avant qu'elles ne soient déclarées.
C'est également meilleur pour la lisibilité, car il est plus facile de rechercher function f(…) {…}
dans le code que de let f = function(…) {…};
. Les déclarations de fonction sont plus « accrocheuses ».
… Mais si une déclaration de fonction ne nous convient pas pour une raison quelconque, ou si nous avons besoin d'une déclaration conditionnelle (nous venons de voir un exemple), alors l'expression de fonction doit être utilisée.
Les fonctions sont des valeurs. Ils peuvent être attribués, copiés ou déclarés à n'importe quel endroit du code.
Si la fonction est déclarée en tant qu'instruction distincte dans le flux de code principal, cela s'appelle une « Déclaration de fonction ».
Si la fonction est créée dans le cadre d'une expression, elle est appelée « Expression de fonction ».
Les déclarations de fonction sont traitées avant l'exécution du bloc de code. Ils sont visibles partout dans le bloc.
Les expressions de fonction sont créées lorsque le flux d'exécution les atteint.
Dans la plupart des cas où nous devons déclarer une fonction, une déclaration de fonction est préférable, car elle est visible avant la déclaration elle-même. Cela nous donne plus de flexibilité dans l'organisation du code et est généralement plus lisible.
Nous devrions donc utiliser une expression de fonction uniquement lorsqu'une déclaration de fonction n'est pas adaptée à la tâche. Nous en avons vu quelques exemples dans ce chapitre, et nous en verrons davantage à l'avenir.