Trs souvent, nous devons effectuer une action similaire plusieurs endroits du script.
Par exemple, nous devons afficher un beau message lorsquun visiteur se connecte, se dconnecte et peut-tre ailleurs.
Les fonctions sont les principales composantes du programme. Ils permettent au code dtre appel plusieurs fois sans rptition.
Nous avons dj vu des exemples de fonctions intgres, telles que alert(message), prompt(message, default) et confirm(question). Mais nous pouvons aussi crer nos propres fonctions.
Dclaration de fonction
Pour crer une fonction, nous pouvons utiliser une dclaration 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 paramtres entre les parenthses (spars par des virgules, vides dans lexemple 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 appele par son nom : showMessage().
Par exemple :
function showMessage() {
alert( 'Hello everyone!' );
}
showMessage();
showMessage();
Lappel showMessage() excute le code de la fonction. Ici, nous verrons le message deux fois, parce quon lappelle deux fois.
Cet exemple illustre clairement lun 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 dclare lintrieur dune fonction nest visible qu lintrieur 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 accder une variable externe, par exemple :
let userName = 'John';
function showMessage() {
let message = 'Hello, ' + userName;
alert(message);
}
showMessage(); // Hello, John
La fonction a un accs 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 modifie par la fonction
La variable externe nest utilise que sil ny a pas de variable locale.
Si une variable du mme nom est dclare lintrieur de la fonction, elle eclipsera la variable externe. Par exemple, dans le code ci-dessous, la fonction utilise le nom userName local. Lexterne est ignor :
let userName = 'John';
function showMessage() {
let userName = "Bob"; // dclarer une variable locale
let message = 'Hello, ' + userName; // Bob
alert(message);
}
// la fonction crera et utilisera son propre userName
showMessage();
alert( userName ); // John, inchang, la fonction n'a pas accd la variable externe
Les variables dclares en dehors de toute fonction, telle que userName externe dans le code ci-dessus, sont appeles globales.
Les variables globales sont visibles depuis nimporte quelle fonction (sauf si elles sont masques par les variables locales).
Cest une bonne pratique de minimiser lutilisation de variables globales. Le code moderne a peu ou pas de variable globales. La plupart des variables rsident dans leurs fonctions. Parfois, cependant, ils peuvent tre utiles pour stocker des donnes au niveau du projet.
Arguments
Nous pouvons transmettre des donnes arbitraires des fonctions laide de paramtres.
Dans lexemple ci-dessous, la fonction a deux paramtres: 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 appele dans les lignes (*) et (**), les valeurs donnes sont copies 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 nest pas visible lextrieur, car une fonction obtient toujours une copie de la valeur :
function showMessage(from, text) {
from = '*' + from + '*'; // amliore l'apparence de "from"
alert( from + ': ' + text );
}
let from = "Ann";
showMessage(from, "Hello"); // *Ann*: Hello
// la valeur de "from" est la mme, la fonction a modifi une copie locale
alert( from ); // Ann
Lorsquune valeur est passe en tant que paramtre de fonction, elle est galement appele argument.
En dautres termes, pour mettre ces termes au clair :
- Un paramtre est la variable rpertorie entre parenthses dans la fonction dclaration (cest un terme du temps de la dclaration).
- Un argument est la valeur qui est transmise la fonction lorsquelle est appele (cest un terme du temps de lappel).
Nous dclarons des fonctions en listant leurs paramtres, puis les appelons en passant des arguments.
Dans lexemple ci-dessus, on pourrait dire : "la fonction showMessage est dclare avec deux paramtres, puis appele avec deux arguments : from et "Hello".
Les valeurs par dfaut
Si une fonction est appele, mais quaucun argument nest fourni, alors la valeur correspondante devient undefined.
Par exemple, la fonction showMessage(from, text) mentionne prcdemment peut tre appele avec un seul argument :
showMessage("Ann");
Ce nest pas une erreur. Un tel appel produirait "*Ann*: undefined". Comme la valeur de text nest pas transmise, elle devient undefined.
Nous pouvons spcifier la valeur dite par dfaut ( utiliser si omise) pour un paramtre dans la dclaration de fonction, en utilisant =:
function showMessage(from, text = "no text given") {
alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given
Maintenant, si le paramtre text nest pas pass, il obtiendra la valeur "no text given".
La valeur par dfaut saute galement si le paramtre existe, mais est strictement gal undefined, comme ceci:
showMessage("Ann", undefined); // Ann: no text given
Ici, "no text given" est une chane de caractres, mais il peut sagir dune expression plus complexe, qui nest value et affecte que si le paramtre est manquant. Donc, cela est galement possible :
function showMessage(from, text = anotherFunction()) {
// anotherFunction() est excut uniquement si aucun texte n'est fourni
// son rsultat devient la valeur de text
}
En JavaScript, un paramtre par dfaut est valu chaque fois que la fonction est appele sans le paramtre correspondant.
Dans lexemple ci-dessus, anotherFunction() nest pas du tout appel, si le paramtre text est fourni.
Dun autre ct, il est appel indpendamment chaque fois que text est manquant.
Il y a plusieurs annes, JavaScript ne prenait pas en charge la syntaxe des paramtres par dfaut. Les gens ont donc utilis dautres moyens pour les spcifier.
De nos jours, on peut les croiser dans danciens scripts.
Par exemple, une vrification explicite pour undefined:
function showMessage(from, text) {
if (text === undefined) {
text = 'no text given';
}
alert( from + ": " + text );
}
Ou en utilisant loprateur ||:
function showMessage(from, text) {
// Si la valeur du texte est fausse, attribuez la valeur par dfaut
// cela suppose que text == "" est identique pas de texte du tout
text = text || 'no text given';
...
}
Paramtres par dfaut alternatifs
Il est parfois judicieux de dfinir des valeurs par dfaut pour les paramtres non pas dans la fonction dclaration, mais un stade ultrieur, lors de son excution.
Nous pouvons vrifier si le paramtre est pass lors de lexcution de la fonction, en le comparant avec undefined:
function showMessage(text) {
// ...
if (text === undefined) { // si le paramtre est manquant
text = 'empty message';
}
alert(text);
}
showMessage(); // empty message
Ou nous pourrions utiliser loprateur || :
function showMessage(text) {
// if text is undefined or otherwise falsy, set it to 'empty'
text = text || 'empty';
...
}
Les moteurs JavaScript modernes prennent en charge loprateur de coalescence des nuls ??, cest mieux quand des valeurs fausses, telles que 0, sont considres 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 rsultat.
Lexemple 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 nimporte o dans la fonction. Lorsque lexcution le permet, la fonction sarrte et la valeur est renvoye 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 dutiliser return sans valeur. Cela entrane la sortie immdiate 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 neffectuera pas lalert.
return vide ou rien dedans retourne undefinedfunction 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 spare, comme ceci :
return
(some + long + expression + or + whatever * f(a) + f(b))
Cela ne fonctionne pas, car JavaScript suppose un point-virgule aprs 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 lexpression renvoye recouvre plusieurs lignes, nous devons la dmarrer la mme ligne que return. Ou du moins mettre les parenthses douverture comme suit :
return (
some + long + expression
+ or +
whatever * f(a) + f(b)
)
Et cela fonctionnera comme prvu.
Nommer une fonction
Les fonctions sont des actions. Donc, leur nom est gnralement un verbe. Il convient de dcrire brivement, mais aussi prcisment que possible, le rle de la fonction. Pour quune personne qui lit le code reoive le bon indice.
Cest une pratique rpandue de commencer une fonction avec un prfixe verbal qui dcrit vaguement laction. Il doit exister un accord au sein de lquipe sur la signification des prfixes.
Par exemple, les fonctions qui commencent par "show" affichent gnralement quelque chose.
Fonction commenant par
"get"retourne une valeur,"calc"calcule quelque chose,"create"crer quelque chose,"check"vrifie quelque chose et retourne un boolen, 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 rsultat
createForm(..) // cre un formulaire (et le retourne gnralement)
checkPermission(..) // vrifie une permission, retourne vrai/faux
Avec les prfixes en place, un coup dil 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 suggr par son nom, pas plus.
Deux actions indpendantes mritent gnralement deux fonctions, mme si elles sont gnralement appeles ensemble (dans ce cas, nous pouvons crer une troisime fonction qui appelle ces deux actions).
Quelques exemples de violation de cette rgle :
getAgeserait mauvais si elle affichait unealertavec lge (devrait seulement obtenir).createFormserait mauvais sil modifiait le document en y ajoutant un formulaire (il ne devrait que le crer et le renvoyer).checkPermissionserait mauvais sil affiche le message daccs accord/refus (doit uniquement effectuer la vrification et renvoyer le rsultat).
Ces exemples supposent des significations communes de prfixes. Vous et votre quipe tes libres de vous entendre sur dautres sens, mais ils ne sont gnralement pas trs diffrents. Dans tous les cas, vous devez bien comprendre ce que signifie un prfixe, ce quune fonction prfixe peut et ne peut pas faire. Toutes les fonctions ayant le mme prfixe doivent obir aux rgles. Et lquipe devrait partager ces connaissances.
Fonctions == Commentaires
Les fonctions doivent tre courtes et faire exactement une seule chose. Si cette chose est consquente, il vaut peut-tre la peine de scinder la fonction en quelques fonctions plus petites. Parfois, suivre cette rgle peut ne pas tre aussi facile, mais cest dfinitivement une bonne pratique.
Une fonction distincte est non seulement plus facile tester et dboguer son existence mme est un excellent commentaire!
Par exemple, comparez les deux fonctions showPrimes(n) ci-dessous. Chacune extrait les nombres premiers jusqu n.
La premire 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 deuxime variante utilise une fonction supplmentaire 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 deuxime variante est plus facile comprendre, nest-ce pas ? Au lieu du bloc de code, nous voyons le nom de laction (isPrime). Parfois, les gens se rfrent ce code comme tant auto-descriptif.
Des fonctions peuvent donc tre cres mme si nous navons pas lintention de les rutiliser. Ils structurent le code et le rendent lisible.
Rsum
Une dclaration de fonction ressemble ceci :
function name(parameters, delimited, by, comma) {
/* code */
}
- Les valeurs transmises une fonction en tant que paramtres sont copies dans ses variables locales.
- Une fonction peut accder des variables externes. Mais cela ne fonctionne que de lintrieur. Le code en dehors de la fonction ne voit pas ses variables locales.
- Une fonction peut renvoyer une valeur. Si ce nest pas le cas, le rsultat est
undefined.
Pour rendre le code propre et facile comprendre, il est recommand dutiliser principalement des variables et des paramtres locaux dans la fonction, et non des variables externes.
Il est toujours plus facile de comprendre une fonction qui possde des paramtres, fonctionne avec eux et renvoie un rsultat, plutt quune fonction qui ne comporte aucun paramtre, mais modifie des variables externes comme un effet secondaire.
Nommage de fonction :
- Un nom doit clairement dcrire le rle de la fonction. Lorsque nous voyons un appel de fonction dans le code, un bon nom nous donne instantanment une comprhension de ce quelle fait et de ce quelle retourne.
- Une fonction est une action, les noms de fonctions sont donc gnralement verbaux.
- Il existe de nombreux prfixes de fonctions bien connus, tels que
create,show,get,checket ainsi de suite. Utilisez-les pour indiquer ce que fait une fonction.
Les fonctions sont les principaux lments constitutifs des scripts. Maintenant que nous avons couvert les bases, nous pouvons donc commencer les crer et les utiliser. Mais ce nest que le dbut du chemin. Nous allons y revenir plusieurs fois, en approfondissant leurs fonctionnalits avances.
Commentaires
<code>, pour plusieurs lignes enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen)