TrĂšs souvent, nous devons effectuer une action similaire Ă plusieurs endroits du script.
Par exemple, nous devons afficher un beau message lorsquâun visiteur se connecte, se dĂ©connecte et peut-ĂȘtre ailleurs.
Les fonctions sont les principales âcomposantesâ du programme. Ils permettent au code dâĂȘtre appelĂ© plusieurs fois sans rĂ©pĂ©tition.
Nous avons déjà vu des exemples de fonctions intégrées, telles que alert(message)
, prompt(message, default)
et confirm(question)
. Mais nous pouvons aussi créer nos propres fonctions.
Déclaration de fonction
Pour créer une fonction, nous pouvons utiliser une déclaration de fonction.
Cela ressemble Ă ceci :
function showMessage() {
alert( 'Hello everyone!' );
}
Le mot-clé function
commence en premier, puis le nom de la fonction, puis une liste de paramĂštres entre les parenthĂšses (sĂ©parĂ©s par des virgules, vides dans lâexemple ci-dessus, nous verrons des exemples plus tard) et enfin le code de la fonction, Ă©galement appelĂ© âle corps de la fonctionâ, entre des accolades.
function name(parameter1, parameter2, ... parameterN) {
// body
}
Notre nouvelle fonction peut ĂȘtre appelĂ©e par son nom : showMessage()
.
Par exemple :
function showMessage() {
alert( 'Hello everyone!' );
}
showMessage();
showMessage();
Lâappel showMessage()
exĂ©cute le code de la fonction. Ici, nous verrons le message deux fois, parce quâon lâappelle deux fois.
Cet exemple illustre clairement lâun des principaux objectifs des fonctions: Ă©viter la duplication de code.
Si nous devons un jour modifier le message ou son affichage, il suffit de modifier le code Ă un endroit: la fonction qui le renvoie.
Variables locales
Une variable dĂ©clarĂ©e Ă lâintĂ©rieur dâune fonction nâest visible quâĂ lâintĂ©rieur de cette fonction.
Par exemple :
function showMessage() {
let message = "Hello, I'm JavaScript!"; // variable locale
alert( message );
}
showMessage(); // Hello, I'm JavaScript!
alert( message ); // <-- Erreur! La variable est locale Ă la fonction
Variables externes
Une fonction peut également accéder à une variable externe, par exemple :
let userName = 'John';
function showMessage() {
let message = 'Hello, ' + userName;
alert(message);
}
showMessage(); // Hello, John
La fonction a un accĂšs complet Ă la variable externe. Cela peut aussi la modifier.
Par exemple :
let userName = 'John';
function showMessage() {
userName = "Bob"; // (1) changé la variable externe
let message = 'Hello, ' + userName;
alert(message);
}
alert( userName ); // John avant l'appel de fonction
showMessage();
alert( userName ); // Bob, la valeur a été modifiée par la fonction
La variable externe nâest utilisĂ©e que sâil nây a pas de variable locale.
Si une variable du mĂȘme nom est dĂ©clarĂ©e Ă lâintĂ©rieur de la fonction, elle eclipsera la variable externe. Par exemple, dans le code ci-dessous, la fonction utilise le nom userName
local. Lâexterne est ignorĂ© :
let userName = 'John';
function showMessage() {
let userName = "Bob"; // déclarer une variable locale
let message = 'Hello, ' + userName; // Bob
alert(message);
}
// la fonction créera et utilisera son propre userName
showMessage();
alert( userName ); // John, inchangé, la fonction n'a pas accédé à la variable externe
Les variables déclarées en dehors de toute fonction, telle que userName
externe dans le code ci-dessus, sont appelées globales.
Les variables globales sont visibles depuis nâimporte quelle fonction (sauf si elles sont masquĂ©es par les variables locales).
Câest une bonne pratique de minimiser lâutilisation de variables globales. Le code moderne a peu ou pas de variable globales. La plupart des variables rĂ©sident dans leurs fonctions. Parfois, cependant, ils peuvent ĂȘtre utiles pour stocker des donnĂ©es au niveau du projet.
Arguments
Nous pouvons transmettre des donnĂ©es arbitraires Ă des fonctions Ă lâaide de paramĂštres.
Dans lâexemple ci-dessous, la fonction a deux paramĂštres: from
et text
.
function showMessage(from, text) { // arguments : from, text
alert(from + ': ' + text);
}
showMessage('Ann', 'Hello!'); // Ann: Hello! (*)
showMessage('Ann', "What's up?"); // Ann: What's up? (**)
Lorsque la fonction est appelée dans les lignes (*)
et (**)
, les valeurs données sont copiées dans les variables locales from
et text
. Ensuite, la fonction les utilise.
Voici un autre exemple: nous avons une variable from
et la transmettons Ă la fonction. Remarque : la fonction change from
, mais le changement nâest pas visible Ă lâextĂ©rieur, car une fonction obtient toujours une copie de la valeur :
function showMessage(from, text) {
from = '*' + from + '*'; // améliore l'apparence de "from"
alert( from + ': ' + text );
}
let from = "Ann";
showMessage(from, "Hello"); // *Ann*: Hello
// la valeur de "from" est la mĂȘme, la fonction a modifiĂ© une copie locale
alert( from ); // Ann
Lorsquâune valeur est passĂ©e en tant que paramĂštre de fonction, elle est Ă©galement appelĂ©e argument.
En dâautres termes, pour mettre ces termes au clair :
- Un paramĂštre est la variable rĂ©pertoriĂ©e entre parenthĂšses dans la fonction dĂ©claration (câest un terme du temps de la dĂ©claration).
- Un argument est la valeur qui est transmise Ă la fonction lorsquâelle est appelĂ©e (câest un terme du temps de lâappel).
Nous déclarons des fonctions en listant leurs paramÚtres, puis les appelons en passant des arguments.
Dans lâexemple ci-dessus, on pourrait dire : "la fonction showMessage
est déclarée avec deux paramÚtres, puis appelée avec deux arguments : from
et "Hello"
.
Les valeurs par défaut
Si une fonction est appelĂ©e, mais quâaucun argument nâest fourni, alors la valeur correspondante devient undefined
.
Par exemple, la fonction showMessage(from, text)
mentionnĂ©e prĂ©cĂ©demment peut ĂȘtre appelĂ©e avec un seul argument :
showMessage("Ann");
Ce nâest pas une erreur. Un tel appel produirait "*Ann*: undefined"
. Comme la valeur de text
nâest pas transmise, elle devient undefined
.
Nous pouvons spĂ©cifier la valeur dite âpar dĂ©fautâ (Ă utiliser si omise) pour un paramĂštre dans la dĂ©claration de fonction, en utilisant =
:
function showMessage(from, text = "no text given") {
alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given
Maintenant, si le paramĂštre text
nâest pas passĂ©, il obtiendra la valeur "no text given"
.
La valeur par défaut saute également si le paramÚtre existe, mais est strictement égal à undefined
, comme ceci :
showMessage("Ann", undefined); // Ann: no text given
Ici, "no text given"
est une chaĂźne de caractĂšres, mais il peut sâagir dâune expression plus complexe, qui nâest Ă©valuĂ©e et affectĂ©e que si le paramĂštre est manquant. Donc, cela est Ă©galement possible :
function showMessage(from, text = anotherFunction()) {
// anotherFunction() est exécuté uniquement si aucun texte n'est fourni
// son résultat devient la valeur de text
}
En JavaScript, un paramÚtre par défaut est évalué chaque fois que la fonction est appelée sans le paramÚtre correspondant.
Dans lâexemple ci-dessus, anotherFunction()
nâest pas du tout appelĂ©, si le paramĂštre text
est fourni.
Dâun autre cĂŽtĂ©, il est appelĂ© indĂ©pendamment Ă chaque fois que text
est manquant.
Il y a plusieurs annĂ©es, JavaScript ne prenait pas en charge la syntaxe des paramĂštres par dĂ©faut. Les gens ont donc utilisĂ© dâautres moyens pour les spĂ©cifier.
De nos jours, on peut les croiser dans dâanciens scripts.
Par exemple, une vérification explicite pour undefined
:
function showMessage(from, text) {
if (text === undefined) {
text = 'no text given';
}
alert( from + ": " + text );
}
âŠOu en utilisant lâopĂ©rateur ||
:
function showMessage(from, text) {
// Si la valeur du texte est fausse, attribuez la valeur par défaut
// cela suppose que text == "" est identique Ă pas de texte du tout
text = text || 'no text given';
...
}
ParamÚtres par défaut alternatifs
Il est parfois judicieux de définir des valeurs par défaut pour les paramÚtres non pas dans la fonction déclaration, mais à un stade ultérieur, lors de son exécution.
Nous pouvons vĂ©rifier si le paramĂštre est passĂ© lors de lâexĂ©cution de la fonction, en le comparant avec undefined
:
function showMessage(text) {
// ...
if (text === undefined) { // si le paramĂštre est manquant
text = 'empty message';
}
alert(text);
}
showMessage(); // empty message
âŠOu nous pourrions utiliser lâopĂ©rateur ||
:
function showMessage(text) {
// if text is undefined or otherwise falsy, set it to 'empty'
text = text || 'empty';
...
}
Les moteurs JavaScript modernes prennent en charge lâopĂ©rateur de coalescence des nuls ??
, câest mieux quand des valeurs fausses, telles que 0
, sont considĂ©rĂ©es comme ânormalesâ :
function showCount(count) {
// if count is undefined or null, show "unknown"
alert(count ?? "unknown");
}
showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown
Renvoyer une valeur
Une fonction peut renvoyer une valeur dans le code appelant en tant que résultat.
Lâexemple le plus simple serait une fonction qui additionne deux valeurs :
function sum(a, b) {
return a + b;
}
let result = sum(1, 2);
alert( result ); // 3
La directive return
peut ĂȘtre nâimporte oĂč dans la fonction. Lorsque lâexĂ©cution le permet, la fonction sâarrĂȘte et la valeur est renvoyĂ©e au code appelant (affectĂ© Ă result
ci-dessus).
Il peut y avoir plusieurs occurrences de return
dans une seule fonction. Par exemple :
function checkAge(age) {
if (age >= 18) {
return true;
} else {
return confirm('Do you have permission from your parents?');
}
}
let age = prompt('How old are you?', 18);
if ( checkAge(age) ) {
alert( 'Access granted' );
} else {
alert( 'Access denied' );
}
Il est possible dâutiliser return
sans valeur. Cela entraßne la sortie immédiate de la fonction.
Par exemple :
function showMovie(age) {
if ( !checkAge(age) ) {
return;
}
alert( "Showing you the movie" ); // (*)
// ...
}
Dans le code ci-dessus, si checkAge(age)
renvoie false
, alors ShowMovie
nâeffectuera pas lâalert
.
return
vide ou rien dedans retourne undefined
function doNothing() { /* vide */ }
alert( doNothing() === undefined ); // true
Un return
vide est également identique à un return undefined
:
function doNothing() {
return;
}
alert( doNothing() === undefined ); // true
return
et la valeurPour une longue expression dans return
, il pourrait ĂȘtre tentant de la mettre sur une ligne sĂ©parĂ©e, comme ceci :
return
(some + long + expression + or + whatever * f(a) + f(b))
Cela ne fonctionne pas, car JavaScript suppose un point-virgule aprĂšs le return
. Cela fonctionnera comme :
return;
(some + long + expression + or + whatever * f(a) + f(b))
Donc, cela devient effectivement un retour vide.
Si nous voulons que lâexpression renvoyĂ©e recouvre plusieurs lignes, nous devons la dĂ©marrer Ă la mĂȘme ligne que return
. Ou du moins mettre les parenthĂšses dâouverture comme suit :
return (
some + long + expression
+ or +
whatever * f(a) + f(b)
)
Et cela fonctionnera comme prévu.
Nommer une fonction
Les fonctions sont des actions. Donc, leur nom est gĂ©nĂ©ralement un verbe. Il convient de dĂ©crire briĂšvement, mais aussi prĂ©cisĂ©ment que possible, le rĂŽle de la fonction. Pour quâune personne qui lit le code reçoive le bon indice.
Câest une pratique rĂ©pandue de commencer une fonction avec un prĂ©fixe verbal qui dĂ©crit vaguement lâaction. Il doit exister un accord au sein de lâĂ©quipe sur la signification des prĂ©fixes.
Par exemple, les fonctions qui commencent par "show"
affichent généralement quelque chose.
Fonction commençant parâŠ
"getâŠ"
â retourne une valeur,"calcâŠ"
â calcule quelque chose,"createâŠ"
â crĂ©er quelque chose,"checkâŠ"
â vĂ©rifie quelque chose et retourne un boolĂ©en, etc.
Exemples de quelques noms :
showMessage(..) // affiche un message
getAge(..) // renvoie l'Ăąge (l'obtient en quelque sorte)
calcSum(..) // calcule une somme et renvoie le résultat
createForm(..) // crée un formulaire (et le retourne généralement)
checkPermission(..) // vérifie une permission, retourne vrai/faux
Avec les prĂ©fixes en place, un coup dâĆil sur un nom de fonction permet de comprendre le type de travail effectuĂ© et le type de valeur renvoyĂ©.
Une fonction doit faire exactement ce qui est suggéré par son nom, pas plus.
Deux actions indĂ©pendantes mĂ©ritent gĂ©nĂ©ralement deux fonctions, mĂȘme si elles sont gĂ©nĂ©ralement appelĂ©es ensemble (dans ce cas, nous pouvons crĂ©er une troisiĂšme fonction qui appelle ces deux actions).
Quelques exemples de violation de cette rĂšgle :
getAge
â serait mauvais si elle affichait unealert
avec lâĂąge (devrait seulement obtenir).createForm
â serait mauvais sâil modifiait le document en y ajoutant un formulaire (il ne devrait que le crĂ©er et le renvoyer).checkPermission
â serait mauvais sâil affiche le message dâaccĂšs accordĂ©/refusĂ© (doit uniquement effectuer la vĂ©rification et renvoyer le rĂ©sultat).
Ces exemples supposent des significations communes de prĂ©fixes. Vous et votre Ă©quipe ĂȘtes libres de vous entendre sur dâautres sens, mais ils ne sont gĂ©nĂ©ralement pas trĂšs diffĂ©rents. Dans tous les cas, vous devez bien comprendre ce que signifie un prĂ©fixe, ce quâune fonction prĂ©fixĂ©e peut et ne peut pas faire. Toutes les fonctions ayant le mĂȘme prĂ©fixe doivent obĂ©ir aux rĂšgles. Et lâĂ©quipe devrait partager ces connaissances.
Fonctions == Commentaires
Les fonctions doivent ĂȘtre courtes et faire exactement une seule chose. Si cette chose est consĂ©quente, il vaut peut-ĂȘtre la peine de scinder la fonction en quelques fonctions plus petites. Parfois, suivre cette rĂšgle peut ne pas ĂȘtre aussi facile, mais câest dĂ©finitivement une bonne pratique.
Une fonction distincte est non seulement plus facile Ă tester et Ă dĂ©boguer â son existence mĂȘme est un excellent commentaire!
Par exemple, comparez les deux fonctions showPrimes(n)
ci-dessous. Chacune extrait les nombres premiers jusquâĂ n
.
La premiĂšre variante utilise un label :
function showPrimes(n) {
nextPrime: for (let i = 2; i < n; i++) {
for (let j = 2; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert( i ); // un nombre premier
}
}
La deuxiÚme variante utilise une fonction supplémentaire isPrime(n)
pour tester la primalité :
function showPrimes(n) {
for (let i = 2; i < n; i++) {
if (!isPrime(i)) continue;
alert(i); // un nombre premier
}
}
function isPrime(n) {
for (let i = 2; i < n; i++) {
if ( n % i == 0) return false;
}
return true;
}
La deuxiĂšme variante est plus facile Ă comprendre, nâest-ce pas ? Au lieu du bloc de code, nous voyons le nom de lâaction (isPrime
). Parfois, les gens se réfÚrent à ce code comme étant auto-descriptif.
Des fonctions peuvent donc ĂȘtre créées mĂȘme si nous nâavons pas lâintention de les rĂ©utiliser. Ils structurent le code et le rendent lisible.
Résumé
Une déclaration de fonction ressemble à ceci :
function name(parameters, delimited, by, comma) {
/* code */
}
- Les valeurs transmises à une fonction en tant que paramÚtres sont copiées dans ses variables locales.
- Une fonction peut accĂ©der Ă des variables externes. Mais cela ne fonctionne que de lâintĂ©rieur. Le code en dehors de la fonction ne voit pas ses variables locales.
- Une fonction peut renvoyer une valeur. Si ce nâest pas le cas, le rĂ©sultat est
undefined
.
Pour rendre le code propre et facile Ă comprendre, il est recommandĂ© dâutiliser principalement des variables et des paramĂštres locaux dans la fonction, et non des variables externes.
Il est toujours plus facile de comprendre une fonction qui possĂšde des paramĂštres, fonctionne avec eux et renvoie un rĂ©sultat, plutĂŽt quâune fonction qui ne comporte aucun paramĂštre, mais modifie des variables externes comme un effet secondaire.
Nommage de fonction :
- Un nom doit clairement dĂ©crire le rĂŽle de la fonction. Lorsque nous voyons un appel de fonction dans le code, un bon nom nous donne instantanĂ©ment une comprĂ©hension de ce quâelle fait et de ce quâelle retourne.
- Une fonction est une action, les noms de fonctions sont donc généralement verbaux.
- Il existe de nombreux préfixes de fonctions bien connus, tels que
createâŠ
,showâŠ
,getâŠ
,checkâŠ
et ainsi de suite. Utilisez-les pour indiquer ce que fait une fonction.
Les fonctions sont les principaux Ă©lĂ©ments constitutifs des scripts. Maintenant que nous avons couvert les bases, nous pouvons donc commencer Ă les crĂ©er et les utiliser. Mais ce nâest que le dĂ©but du chemin. Nous allons y revenir plusieurs fois, en approfondissant leurs fonctionnalitĂ©s avancĂ©es.
Commentaires
<code>
, pour plusieurs lignes â enveloppez-les avec la balise<pre>
, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâŠ)