En JavaScript, une fonction nâest pas une âstructure de langage magiqueâ, mais un type de valeur particulier.
La syntaxe utilisée précédemment sâappelle une déclaration de fonction :
function sayHi() {
alert( "Hello" );
}
Il existe une autre syntaxe pour créer une fonction appelée Expression de Fonction.
Cela nous permet de créer une nouvelle fonction au milieu de nâimporte quelle expression.
Par exemple :
let sayHi = function() {
alert( "Hello" );
};
Ici, nous pouvons voir une variable sayHi obtenir une valeur, la nouvelle fonction, créée en tant que function() { alert("Hello"); }.
Comme la création de la fonction se produit dans le contexte de lâexpression dâaffectation (à droite de =), il sâagit dâune Fonction 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 fonctions expressions.
Ici, nous lâassignons immédiatement à la variable, donc la signification de ces exemples de code est la même : âcréer une fonction et la mettre 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 planifiée pour une exécution ultérieure, non stockée nulle part, restant ainsi anonyme.
La fonction est une valeur
Répétons-le : quelle que soit 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.
La signification de ces exemples de code est la même : âcréer une fonction et la placer dans la variable sayHiâ.
Nous pouvons même afficher cette valeur en utilisant alert :
function sayHi() {
alert( "Hello" );
}
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 y a des langages de programmation où toute mention dâun nom de fonction provoque son exécution, mais JavaScript nâest pas comme ça.
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 de caractères, qui est le code source.
Certes, une fonction est une valeur spéciale, en ce sens que nous pouvons lâappeler comme cela sayHi().
Mais câest toujours une valeur. Nous pouvons donc travailler avec comme avec dâautres types de valeurs.
Nous pouvons copier une fonction dans une autre variable :
function sayHi() { // (1) créer
alert( "Hello" );
}
let func = sayHi; // (2) copier
func(); // Hello // (3) exécuter la copie (ça fonctionne)!
sayHi(); // Hello // cela fonctionne 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éesayHi. - La ligne
(2)la copie dans la variablefunc. Veuillez noter à nouveau : il nây a pas de parenthèses aprèssayHi. Sâil y en avait, alorsfunc = sayHi()écrirait le résultat de lâappelsayHi()dansfunc, et non la fonctionsayHielle-même. - Maintenant, la fonction peut être appelée à la fois en tant que
sayHi()etfunc().
Nous aurions aussi pu utiliser une Fonction Expression pour déclarer sayHi, à la première ligne :
let sayHi = function() { // (1) create
alert( "Hello" );
};
let func = sayHi;
// ...
Tout fonctionnerait de la même manière.
Il peut y avoir une question, pourquoi la Fonction Expression a un point-virgule ; à la fin, et la Fonction Déclaration non :
function sayHi() {
// ...
}
let sayHi = function() {
// ...
};
La réponse est simple : une expression de fonction est créée ici en tant que function(â¦) {â¦} à lâintérieur de lâinstruction dâaffectation : let sayHi = â¦;. Le point-virgule ; est recommandé à la fin de lâinstruction, il ne fait pas partie de la syntaxe de la fonction.
Le point-virgule serait là pour une affectation plus simple, telle que let sayHi = 5;, et il est également là pour une affectation de fonction.
Fonctions callback (de rappel)
Examinons plus dâexemples de fonctions passées en tant que valeurs et utilisant des 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 âYesâ
no- Fonction à exécuter si la réponse est âNoâ
La fonction doit poser la question et, en fonction de la réponse de lâutilisateur, appeler yes() ou no() :
function ask(question, yes, no) {
if (confirm(question)) yes();
else no();
}
function showOk() {
alert( "You agreed." );
}
function showCancel() {
alert( "You canceled the execution." );
}
// utilisation: les fonctions showOk, showCancel sont transmises en tant qu'arguments à ask
ask("Do you agree?", showOk, showCancel);
En pratique, ces fonctions sont très utiles. La principale différence entre une demande réelle (ask) et lâexemple ci-dessus est que les fonctions réelles utilisent des moyens dâinteragir avec lâutilisateur plus complexes que la simple confirmation (confirm). Dans le navigateur, une telle fonction dessine généralement une belle fenêtre de questions. Mais câest une autre histoire.
Les arguments showOk et showCancel de ask sâappellent des fonctions callback (fonctions de rappel) ou simplement des callbacks (rappels).
Lâidée est que nous passions une fonction et attendions 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 les Fonctions Expressions pour écrire la même fonction mais plus courte :
function ask(question, yes, no) {
if (confirm(question)) yes();
else no();
}
ask(
"Do you agree?",
function() { alert("You agreed."); },
function() { alert("You canceled the execution."); }
);
Ici, les fonctions sont déclarées directement dans lâappel ask(...). Elles nâont pas de nom et sont donc appelées 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.
Ce genre de code apparaît dans nos scripts très naturellement, câest dans lâesprit de JavaScript.
Des valeurs régulières telles que des chaînes de caractères ou des nombres représentent les données.
Une fonction peut être perçue comme une action.
Nous pouvons tout aussi bien la passer en tant que variable ou lâexécuter si nous le voulons.
Fonction Expression vs Fonction Déclaration
Formulons les principales différences entre les déclarations de fonction et les expressions de fonctions.
Tout dâabord, la syntaxe : comment les différencier dans le code.
-
La Fonction Déclaration une fonction déclarée séparément dans le flux de code principal.
// Function Declaration function sum(a, b) { return a + b; } -
La Fonction Expression : une fonction créée dans une expression ou dans une autre construction de syntaxe. Ici, la fonction est créée à droite de âlâaffectation de lâexpressionâ
=:// Function Expression let sum = function(a, b) { return a + b; };
La différence la plus subtile est quand une fonction est créée par le moteur JavaScript.
Une Fonction Expression est créée lorsque lâexécution lâatteint.
Une fois que le flux dâexécution passe à droite de lâaffectation, let sum = function⦠, la fonction est créée et peut désormais être utilisée (assignée, appelée, etc.).
Les déclarations de fonction sont différentes.
Une Fonction Déclaration peut être appelée plus tôt que sa définition.
Par exemple, une fonction déclaration globale est visible dans tout le script, peu importe où elle se trouve.
Cela est dû aux algorithmes internes. Lorsque JavaScript se prépare à exécuter le script, il recherche dâabord les fonctions déclarations globales et les crée. Nous pouvons considérer cela comme une âétape dâinitialisationâ.
Une fois que toutes les déclarations de fonctions ont été traitées, le reste du code est exécuté. Ainsi, il a accès à ces fonctions pour les appeler.
Par exemple, cela fonctionne :
sayHi("John"); // Hello, John
function sayHi(name) {
alert( `Hello, ${name}` );
}
La déclaration de fonction sayHi est créée lorsque JavaScript est sur le point de démarrer le script et est visible partout dans celui-ci.
⦠Sâil sâagissait dâune Fonction Expression, cela ne fonctionnerait pas :
sayHi("John"); // erreur!
let sayHi = function(name) { // (*) plus de magie
alert( `Hello, ${name}` );
};
Les expressions de fonction sont créées lorsque lâexécution les atteint. Cela ne se produirait que dans la ligne (*). Trop tard.
Une autre particularité des Fonctions Declaration est leur portée de bloc.
En mode strict, quand une Fonction Déclaration se trouve dans un bloc de code, elle est visible partout dans ce bloc. Mais pas en dehors.
Par exemple, imaginons que nous ayons besoin de déclarer une fonction welcome() en fonction de la variable dâage obtenue lors de lâexécution. Et ensuite, nous prévoyons de lâutiliser quelque temps plus tard.
Si nous utilisons la fonction déclaration, cela ne fonctionnera pas comme prévu :
let age = prompt("Quel est votre age ?", 18);
// déclarer conditionnellement une fonction
if (age < 18) {
function welcome() {
alert("Hello!");
}
} else {
function welcome() {
alert("Greetings!");
}
}
// ...l'utiliser plus tard
welcome(); // Error: welcome is not defined
Câest parce quâune déclaration de fonction nâest visible que dans le bloc de code dans lequel elle réside.
Voici un autre exemple :
let age = 16; // prendre 16 comme exemple
if (age < 18) {
welcome(); // \ (exécution)
// |
function welcome() { // |
alert("Hello!"); // | La déclaration de fonction est disponible
} // | partout dans le bloc où elle est déclarée
// |
welcome(); // / (exécution)
} else {
function welcome() {
alert("Greetings!");
}
}
// Ici, nous sommes en dehors des accolades,
// nous ne pouvons donc pas voir les déclarations de fonction faites à l'intérieur de celles-ci.
welcome(); // Error: welcome is not defined
Que pouvons-nous faire pour rendre welcome visible en dehors de if ?
Lâapproche correcte consisterait à utiliser une expression de fonction et à attribuer welcome à la variable déclarée en dehors de if et offrant la visibilité appropriée.
Ce code fonctionne comme prévu :
let age = prompt("What is your age?", 18);
let welcome;
if (age < 18) {
welcome = function() {
alert("Hello!");
};
} else {
welcome = function() {
alert("Greetings!");
};
}
welcome(); // ok maintenant
Ou nous pourrions simplifier encore davantage en utilisant un opérateur conditionnel ternaire ? :
let age = prompt("What is your age?", 18);
let welcome = (age < 18) ?
function() { alert("Hello!"); } :
function() { alert("Greetings!"); };
welcome(); // ok maintenant
En règle générale, lorsque nous devons déclarer une fonction, la première chose à prendre en compte est la syntaxe de la fonction déclaration. Cela donne plus de liberté dans lâorganisation de 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 la fonction f(â¦) {â¦} dans le code que let f = function(â¦) {â¦};. Les fonction déclarations sont plus âaccrocheusesâ.
⦠Mais si une déclaration de fonction ne nous convient pas pour une raison quelconque (nous en avons vu un exemple ci-dessus), alors il convient dâutiliser une Fonction Expression.
Résumé
- Les fonctions sont des valeurs. Elles peuvent être attribuées, copiées ou déclarées à nâimporte quel endroit du code.
- Si la fonction est déclarée comme une 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 fonctions sont traitées avant lâexécution du bloc de code. Elles 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, lorsque nous devons déclarer une fonction, une fonction déclaration est préférable parce quâelle est visible avant la déclaration elle-même. Cela nous donne plus de flexibilité dans lâorganisation du code et il est généralement plus lisible.
Nous devrions donc utiliser une fonction expression uniquement lorsquâune fonction déclaration nâest pas adaptée à la tâche. Nous en avons vu quelques exemples dans ce chapitre et nous en verrons dâautres à lâavenir.
Commentaires
<code>, pour plusieurs lignes â enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâ¦)