Aller au menu - Aller au contenu

Icône Retour sur les fonctions

Mise à jour : 22/07/2009
5 116 visites depuis 7 jours, dont 88 sur ce chapitre classé 38/786
Revenons sur un sujet abordé quelques chapitres plus tôt : les fonctions.
C'est une notion récurrente en JS, et il y a encore pas mal de choses à en dire !
Cependant, vous savez déjà des choses à leur sujet : créer des fonctions qui prennent des arguments et qui renvoient des valeurs... bref, tout ce qu'il faut savoir pour les utiliser ;) .

Mais ce chapitre va apporter un regard nouveau : on va découvrir qu'une fonction, ce n'est en fait... qu'une variable ! o_O
On va également apprendre à créer des fonctions auxquelles on peut donner n'importe quel nombre d'arguments, selon notre envie, mais surtout selon notre besoin...


Rassurez-vous : rien de bien compliqué, vous avez déjà acquis toutes les notions nécessaires dans les chapitres précédents ;) .
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Fonctions et variables

Enregistrer une fonction dans... une variable ?!



Nous avons, dans les chapitres précédents, étudié séparément les variables et les fonctions.
Mais en fait, une fonction, ce n'est pas si différent que ça d'une variable...


Rappel



Histoire de vous rafraîchir un peu la mémoire, je vous rappelle qu'une fonction se déclare dans l'en-tête de la page, de cette manière :
Code : JavaScript
1
2
3
4
5
function toto(arg1, arg2)
{
        // code
        return valeur;
}



Quelques explications succinctes pour se remettre dans le bain :
  • Le mot-clé function indique... qu'on déclare une fonction ;)
  • toto est le nom de notre fonction
  • arg1 et arg2 sont les arguments de cette fonction, séparés par une virgule, et mis entre des parenthèses qui sont obligatoires (même s'il n'y a aucun argument).
  • On place le code de la fonction dans un bloc d'instructions, délimité par des accolades.
  • On renvoie éventuellement une valeur (c'est la valeur que "prendra" la fonction quand on l'appellera).



Créer une fonction dans une variable



Eh bien figurez-vous qu'il existe une autre manière de créer une fonction, en utilisant une variable.
Voyez plutôt :
Code : JavaScript
1
2
3
4
var toto = function(arg1, arg2)
{
        // code
}


Cette fonction est exactement la même que celle au dessus (à l'exception du return valeur;).


Cette fois-ci :
  • On a déclaré notre variable, à l'aide du mot-clé var (comme nous avons vu dans le chapitre à ce sujet).
  • On a donné à notre variable le nom de toto.
  • On lui a affecté (on lui a donné pour valeur) une fonction, prenant deux paramètres nommés arg1 et arg2, et exécutant le code entre les accolades.



Mais alors, si ce sont les mêmes fonctions, quel est l'intérêt d'utiliser cette nouvelle méthode plutôt que l'ancienne ?

C'est en fait un autre point de vue, assez différent : en déclarant une fonction de cette manière, on voit clairement qu'on enregistre notre fonction dans une variable.

On peut donc très facilement :
  • créer une fonction locale ou globale
  • re-déclarer une fonction (autrement dit, modifier son code), simplement en modifiant la variable
  • créer des tableaux de fonctions
  • etc.



Exemple : un tableau de fonctions



Pour vous montrer, créons un tableau de fonctions.
Pour cela, on commence par déclarer notre tableau, comme on l'a appris auparavant, puis on associe à chaque élément (chaque case) une fonction, comme nous venons de le voir :
Code : JavaScript
1
2
3
4
5
6
var operation = new Array();
   operation["add"] = function(x,y){ return x+y; };
   operation["soustr"] = function(x,y){ return x-y; };
   operation["mult"] = function(x,y){ return x*y; };
   operation["div"] = function(x,y){ return x/y; };
   operation["moy"] = function(x,y){ return (x+y)/2; };


On fait un essai : on demande deux nombres à l'utilisateur, ainsi que le nom de la fonction à appliquer (add, soustr, mult, div ou moy).
Code : JavaScript
1
2
3
4
5
6
var a = parseFloat( prompt("Premier nombre ?") );
var b = parseFloat( prompt("Deuxieme nombre ?") );
var fct = prompt("Fonction a appliquer ?");

var resultat = operation[fct](a,b);
alert("Resultat : " + resultat);



C'est quand même plus joli que d'effectuer cinq if à la suite, pas vrai ? :)


Rappel : portée des variables



Puisqu'on parle de variable, un petit rappel concernant la portée de celles-ci ne sera pas inutile...

En JavaScript, on distingue les variables globales (accessibles n'importe où dans votre code) des variables locales.
Les variables locales déclarées dans une fonction ne seront accessibles (et "visibles") qu'à l'intérieur de cette fonction. On peut donc sans problème utiliser le même nom pour des variables locales de deux fonctions différentes.

Comme je l'ai déjà dit, il faut éviter d'utiliser des variables globales.


Comment ça marche ?
  • On déclare une variable locale à l'aide de var, dans le bloc d'instructions (qui est généralement "matérialisé" par des accolades) dans lequel elle doit être accessible.
  • Il y a deux façons de créer une variable globale : soit en la déclarant en dehors de tout bloc d'instructions (tout au début du code JS), soit on l'utilise sans la déclarer, comme si elle l'avait déjà été (on parle alors de déclaration implicite).


Un exemple :
Code : JavaScript
1
2
3
4
5
6
7
8
var a;  // on declare une variable globale
function test(argument)
{
        var resultat = 5*argument + 2;
        a = argument;   // modification de la variable globale
        b = resultat;   // declaration implicite d'une variable globale
        return resultat;
}


  • Lorsque la fonction n'a pas été appelée, il y a une seule variable globale : a.
  • Quand on appelle la fonction, celle-ci modifie cette variable globale, et on en déclare (implicitement) une autre : b.
  • Une fois la fonction exécutée, on peut toujours accéder aux variables a et b, car elles sont globales.
  • Cependant, on ne peut accéder à la variable resultat uniquement à l'intérieur de la fonction, car c'est une variable locale.



Voilà, ce n'était finalement pas compliqué ;) .

Les arguments facultatifs : nombre fixé d'arguments

Plutôt que de vous faire un long discours théorique, voyons ensemble le fonctionnement.

Comment ça se passe lorsqu'on appelle une fonction ?



Prenons une fonction comme celle-ci :
Code : JavaScript
1
2
3
4
function f(x,y)
{
        // code de la fonction
}

Elle a pour nom f, et prend deux paramètres, x et y.


Que se passe-t-il si on l'appelle en ne précisant qu'un seul argument, comme ci-dessous ?
Code : JavaScript
1
f(5);


Essayons de comprendre ce qui va se passer lors de cet appel :
  • deux variables locales, x et y, vont être créées (ce sont les arguments)
  • la variable x va être initialisée avec la valeur 5 (c'est la valeur qu'on a donnée lors de l'appel pour le premier argument)
  • mais y ne sera pas initialisée, car on n'a pas précisé le second argument


Autrement dit, il va se passer quelque chose comme ceci :
Code : JavaScript
1
2
3
var x, y;
x = 5;
// code de la fonction



Une variable non initialisée !



Quels sont les symptômes ?



On se retrouve donc face à une variable déclarée, mais... qui n'a pas de valeur !
Poursuivons donc nos essais : que va-t-il se passer avec un tel code ? :pirate:
Code : JavaScript
1
2
var y;
alert(y);

On voit alors s'afficher : undefined.

En effet, undefined est un mot-clé signifiant que la variable est déclarée, mais qu'on ne lui a jamais donné de valeur :'( .
Si la variable n'avait pas été déclarée, on n'aurait pas eu de message du tout : le script aurait été interrompu (l'ordinateur ne peut pas deviner qu'il s'agit d'une variable, puisqu'on ne l'a pas déclarée).



Comment ça se soigne ?



On peut effectuer un test comme celui-ci pour vérifier si la variable y est définie :
Code : JavaScript
1
if(y == undefined)


Et on peut aussi créer une fonction qui renvoie true ("vrai", cf. le chapitre sur les conditions) si la variable est définie, false sinon.
Code : JavaScript
1
2
3
4
function isDefined(variable)
{
   return (variable != undefined);
}


Si l'écriture vous perturbe, sachez que c'est équivalent à ceci :
Code : JavaScript
1
2
3
4
5
6
7
function isDefined(variable)
{
   if(variable == undefined)
      return false;
   else
      return true;
}

Mais c'est "bête" d'écrire un tel code : "si condition est vrai, alors renvoie vrai, sinon renvoie faux"...


Notez que la valeur booléenne d'une variable non initialisée est false.
Ainsi, en effectuant le test if(y), si la variable y n'est pas initialisée, c'est comme si elle était initialisée avec false.



Exemple



Tout ça pour dire qu'on peut créer des fonctions pour lesquelles certains arguments sont facultatifs.

Un exemple : une fonction dist(a,b) qui calcule la distance entre a et b (autrement dit, la valeur absolue de b-a).
Mais si on appelle dist(a), on veut que la fonction calcule la valeur absolue de a (la distance entre a et 0).

Comment faire ?
Pour le calcul de la distance, pas de problème, on teste si a est plus grand que b, et on calcule a-b ou b-a selon le cas.
En revanche, la nouveauté se trouve dans le second point : si on ne donne qu'un seul paramètre, il va falloir initialiser b à 0.

Code : JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
function dist(a,b)
{
   // on initialise b a 0 si besoin
   if(b == undefined)
      b = 0;
   // on continue ensuite normalement
   if(a > b)
      return a-b;
   else
      return b-a;
}


Au début de la fonction, il faut donc vérifier si les arguments facultatifs ont été précisés : si ce n'est pas le cas, il va falloir leur donner une valeur par défaut.

Les arguments facultatifs : nombre illimité d'arguments

C'est bien gentil tout ça, mais ça ne permet pas de réaliser la fonction d'addition dont on a parlé quelques chapitres plus tôt, qui additionnait tous les arguments qu'elle avait !


En effet, on avait parlé d'une fonction qui devait pouvoir s'utiliser comme ceci :
Code : JavaScript
1
2
3
addition(12, 5);   // nous donnerait 17
addition(21, 4, 15, 11, 6);   // nous donnerait 57
// etc. avec autant de nombres qu'on veut



Où sont stockés tous ces arguments ?



Ce qui serait pratique, c'est que les arguments soient numérotés... un peu comme... un tableau !
Justement, il est possible de récupérer un tableau qui contient tous les arguments de la fonction. Du coup, le problème semble tout de suite plus simple :) .


Un tableau contenant tous les arguments



Partons de la fonction d'addition qu'on veut réaliser. On peut déjà commencer par la créer comme ceci :
Code : JavaScript
1
2
3
4
function addition()
{
   // corps de la fonction
};


Maintenant, il nous faut récupérer le tableau contenant les arguments.
Ce tableau est addition.arguments : ce sont les arguments de la fonction addition, stockés sous forme de tableau.

Ce tableau contient tous les arguments qu'on a donnés à la fonction lors de son appel.
Ainsi, en appelant addition(21, 4, 15, 11, 6), on aurait (schématiquement) :
Code : JavaScript
1
addition.arguments = new Array(21, 4, 15, 11, 6);


Petite parenthèse : le point rouge . ne vous rappelle-t-il pas monTableau.length, qui est la longueur de monTableau ?


Le tour est joué !



Eh bien on a gagné !
Non ? Je vous sens sceptiques...

Commençons par créer une variable contenant ce tableau, qu'on va appeler nb (les arguments sont les nombres à additionner) :
Code : JavaScript
1
var nb = addition.arguments;


nb et addition.arguments sont un seul et même tableau !
Si on le modifie, il sera modifié sous les deux noms.


Et maintenant, il ne reste plus qu'à tout additionner (qui dit tableau, dit boucle...), ce qui nous donne cette fonction :
Code : JavaScript
1
2
3
4
5
6
7
8
function addition()
{
   var nb = addition.arguments;
   var somme = 0;
   for(var i=0; i<nb.length; i++)
      somme += nb[i];
   return somme;
};


Il ne nous reste plus qu'à tester (le moment le plus stressant en programmation :D ) :
Code : JavaScript
1
2
alert( addition(12, 5) );
alert( addition(21, 4, 15, 11, 6) );

Qui nous affiche bel et bien 17, puis 57 :) .

Notez qu'on peut très bien appeler addition(), sans aucun paramètre : le résultat est 0.


Un autre exemple



Pour que ce soit bien clair pour vous, étudions un nouvel exemple : une fonction, prenant encore une fois autant de paramètres (des nombres) qu'on veut, et qui renvoie le plus grand de ces nombres.

Cette fois-ci, à la différence de l'addition, on ne sait pas trop quoi renvoyer s'il n'y a aucun paramètre...
On va donc créer une fonction comme ceci :
Code : JavaScript
1
function maxi(m) { };


Dans le tableau d'arguments, la valeur de m sera également prise en compte, dans la première case (la case numéro 0).


On va ensuite parcourir le tableau, et enregistrer la plus grande valeur "lue" dans une variable (on peut utiliser la variable m) : cette variable contiendra donc le plus grand nombre parmi ceux qu'on a déjà parcourus.

Code : JavaScript
1
2
3
4
5
6
7
8
function maxi(m)
{
   var nb = maxi.arguments;   // on a donc m = nb[0]
   for(var i=1; i<nb.length; i++)
      if(nb[i] > m)   // si l'argument est plus grand que le maximum...
         m = nb[i];   // ... alors c'est le maximum
   return m;
}


Et, encore une fois, on peut tester :
Code : JavaScript
1
2
3
4
5
var n = maxi(7, 3);
alert(n);

var p = maxi(2, 8, 4, 1, 9, 4);
alert(p);


Remarquez au passage que cette dernière fonction peut s'avérer utile :) .

Q.C.M.

Laquelle de ces déclarations de fonction est incorrecte ?
Quel est l'avantage de la nouvelle méthode pour déclarer les fonctions ?
On veut créer une fonction f qui puisse s'utiliser de deux manières (x et y sont ici des variables) :
Code : JavaScript
1
2
f(x);   // premiere façon
f(x,y);   // seconde façon


Il va falloir :

Statistiques de réponses au QCM

Et voilà, cette fois-ci, nous y sommes !
Enfin prêts !
Après tant de labeur, des chapitres pas toujours drôles... vous connaissez maintenant tout ce qu'il faut savoir (la syntaxe du JS) pour vous attaquer à... la POO !

En effet, le JavaScript, c'est avant tout de la Programmation Orientée Objet. Mais pour l'instant, nous n'avons pas vu l'ombre d'un objet. Enfin si, quelques allusions par-ci par-là, mais presque rien.


Par contre, dès les prochains chapitres, on va apprendre à interagir avec le visiteur en utilisant la page web, et vous verrez qu'on en a, des possibilités !
Chapitre précédent Sommaire Chapitre suivant

Partager

9 commentaires pour "Retour sur les fonctions"
Note moyenne : 3.51 / 4 (260 votes)
Pseudo Commentaire
Hors ligne wboss # Posté le 01/12/2008 à 15:06:15

Ville : Bondy
Pays : France métropolitaine

Je me demande pourquoi le for 2 :
for(indice in tab)
ne fonctionne pas avec nomfonction.arguments ?
Hors ligne yoby's # Posté le 15/04/2009 à 11:26:05
Avatar

Ville : Bar le duc
Pays : France métropolitaine
Études : Epitech Nancy

Très bon tuto :-)

Juste une question qui me tracasse ...

<code ="javascript">function maxi(m) { };</code>

Pourquoi un point virgule ici ? :o
Hors ligne azarashi # Posté le 16/01/2010 à 01:34:32
Avatar

Je suis complètement perdu avec ce chapitre, je ne comprend pas l'intérêt de mettre une fonction dans une variable ni les arguments facultatifs infinis... Je vais tout relire ce soir mais ce chapitre là pour moi (un débutant en programmation, pas seulement en JS) est mal expliqué ! :/
Connecté BigPuppy # Posté le 20/04/2010 à 07:19:15
Avatar

Ville : Le havre
Pays : France métropolitaine

Salut! Dans la partie "rappel" tout au debut :
"On renvoie éventuellement une valeur (c'est la valeur que "prendra" la fonction quand on l'appellera)."
ce serait pas plutot la valeur que prendra la variable qui appelle la fonction ?
Hors ligne Georges_ # Posté le 14/08/2010 à 12:22:54
Avatar

Ville : Sevres
Pays : France métropolitaine
Études : Sciences-Po

@azarachi +1
Je suis un zero, et je déplore que le code ne soit pas systématiquement commenté.
Des notions nouvelles (parseFloat) sont aussi introduites sans explications.
...et il n'y a pas de réponses aux commentaires depuis 2007.

Voir tous les commentaires