Fonctions

  • Raccourci de la révision : JavaScript/Référence_JavaScript/Référence_JavaScript/Fonctions
  • Titre de la révision : Fonctions
  • ID de la révision : 270323
  • Créé :
  • Créateur : Julien STUBY
  • Version actuelle ? Oui
  • Commentaire 13 words added

Contenu de la révision

Résumé

D'une manière générale, une fonction est un « sous-programme » qui peut être appelé par du code externe (ou interne dans le cas d'un code récursif) à cette fonction. Comme le programme lui-même, une fonction est composée d'une séquence d'instructions appelée corps de la fonction. Des objets et valeurs peuvent être passés à une fonction, et celle-ci peut renvoyer un objet ou une valeur en retour.

En JavaScript, les fonctions sont des objets de premier ordre. C'est-à-dire qu'elles peuvent être manipulées et transmises comme n'importe quel autre objet. Pour être précis, il s'agit d'objets Function.

Général

Chaque fonction en JavaScript est en fait un objet Function. Consultez Function pour plus d'informations sur les propriétés et méthodes des objets Function.

Pour renvoyer une valeur, la fonction doit contenir une instruction return spécifiant la valeur de retour. Une fonction sans valeur de retour renverra undefined.

Les paramètres n'étant pas des objets (comme les chaînes, nombres et valeurs booléennes) sont passés aux fonctions par valeur. La valeur est passée à la fonction où elle est stockée dans une nouvelle variable. Si la fonction change la valeur de la variable, celle-ci n'est pas propagée globalement ou dans la fonction appelante. Les paramètres objet (comme les tableaux et expressions rationnelles) sont passés aux fonctions par référence. Si l'on passe un objet en paramètre à une fonction et que la fonction change les propriétés de cet objet, cette modification est visible à l'extérieur de la fonction, comme le montre l'exemple suivant :

function maFonction(unObjet) {
   unObjet.marque = "Toyota";
}

var voiture = {marque: "Honda", modèle: "Accord", année: 1998};
alert(voiture.marque); // affiche 'Honda'
maFonction(voiture);   // passe l'objet voiture à la fonction
alert(voiture.marque); // affiche 'Toyota' car la propriété marque de voiture
                       // a été changée par la fonction

Le mot-clé this ne fait pas référence à la fonction en cours d'exécution, il est donc nécessaire de se référer aux objets Function par leur nom, même au sein du corps de la fonction elle-même. Il est également possible d'utiliser la propriété arguments.callee.

Définition de fonctions

Trois manières de définir des fonctions existent :

La déclaration d'une fonction (instruction function)

Il existe une syntaxe spéciale permettant de déclarer des fonctions (consultez l'instruction function pour plus de détails) :

function [nom]([param[, param[, … param]]]) {
   instructions
}
nom 
Le nom de la fonction. Peut être omis; fait référence à une fonction anonyme.
param 
Le nom d'un paramètre à passer à la fonction. Une fonction peut avoir jusqu'à 255 paramètres.
instructions 
Les instructions constituant le corps de la fonction.

L'expression d'une fonction (opérateur function)

Une expression de fonction est semblable et a la même syntaxe qu'une déclaration de fonction (consultez l'opérateur function pour plus de détails) :

function [nom]([param] [, param] […, param]) {
   instructions
}
nom 
Le nom de la fonction. Peut ne pas être spécifié, auquel cas la fonction devient ce que l'on appelle une fonction anonyme.
param 
Le nom d'un paramètre à passer à la fonction. Une fonction peut avoir jusqu'à 255 paramètres.
instructions 
Les instructions constituant le corps de la fonction.

Le constructeur d'objets Function

Comme tous les autres objets, les objets Function peuvent être créés à l'aide de l'instruction new :

new Function ([arg1[, arg2[, ... argN]],] corps)
arg1, arg2, ... argN 
Noms à utiliser pour les paramètres formels de la fonction. Chacun doit être une chaîne correspondant à un identifiant JavaScript valide ou une liste de telles chaînes séparées par des virgules. Par exemple "x", "maValeur", or "a,b".
corps 
Une chaîne contenant les instructions JavaScript constituant la définition de la fonction.

L'appel du constructeur Function comme une fonction (sans utiliser l'opérateur new) a le même effet que son appel comme un constructeur.

L'objet arguments

Il est possible d'accéder aux paramètres passés à une fonction depuis celle-ci en utilisant l'objet arguments. Voir arguments.

Visibilité et la pile de fonctions

some section about scope and functions calling other functions

Récursivité

Une fonction peut faire référence à et s'appeler elle-même. Trois manières existent pour une fonction de s'identifier elle-même :

  1. le nom de la fonction
  2. arguments.callee
  3. une variable visible faisant référence à la fonction

Par exemple, examinons la définition de fonction suivante :

var foo = function bar() {
   // des instructions ici
};

Au sein du corps de la fonction, les lignes suivantes sont toutes équivalentes :

  1. bar();
  2. arguments.callee();
  3. foo();

Une fonction qui s'appelle elle-même est appelée fonction récursive. D'une certaine manière, la récursivité ressemble à une boucle. Ces deux constructions exécutent le même code plusieurs fois, et ont besoin d'une condition de terminaison (pour éviter une boucle infinie, ou dans ce cas, une récursivité sans fin). Par exemple, la boucle suivante :

var x = 0;
while (x < 10) { // "x < 10" est la condition de la boucle
   // faire quelque chose
   x++;
}

peut être convertie en une fonction récursive et un appel à cette fonction :

function loop(x) {
   if (x >= 10) // "x >= 10" est la condition de sortie (équivalente à "!(x < 10)")
      return;
   // faire quelque chose
   loop(x + 1); // l'appel récursif
}
loop(0);

Cependant, certains algorithmes ne peuvent pas être réduits à de simple boucles itératives. Par exemple, pour obtenir tous les nœuds d'une structure arborescente (comme le DOM) il peut être plus facile d'utiliser la récursivité :

function parcoursArbre(noeud) {
   if (noeud == null) // 
      return;
   // faire quelque chose avec le noeud
   for (var i = 0; i < noeud.childNodes.length; i++) {
      parcoursArbre(noeud.childNodes[i]);
   }
}

Contrairement à la fonction loop précédente, chaque appel récursif fait ici lui-même un grand nombre d'appels récursifs.

Il est possible de convertir n'importe quel algorithme récursif en un algorithme non récursif, mais la logique en devient souvent plus complexe et nécessite d'utiliser une pile (stack). En réalité, la récursivité elle-même utilise une pile : la pile de fonctions.

Ce comportement de pile peut être observé dans l'exemple suivant :

function foo(i) {
   if (i < 0)
      return;
   document.writeln('début : ' + i);
   foo(i - 1);
   document.writeln('fin : ' + i);
}
foo(3);

qui affichera :

début : 3
début : 2
début : 1
début : 0
fin : 0
fin : 1
fin : 2
fin : 3

Fonctions imbriquées et fermetures

Une fonction peut être intégrée dans une autre fonction. La fonction imbriquée n'est visible que depuis sa fonction contenante. Elle forme également une fermeture (closure).

Une fermeture est une expression (typiquement une fonction) qui peut disposer de variables libres avec un environnement qui lie ces variables (qui "ferme" l'expression).

Une fonction imbriquée étant une fermeture, cela signifie qu'une telle fonction peut « hériter » des paramètres et variables de sa fonction contenante. En d'autres mots, la fonction interne contient la visibilité de la fonction externe.

Pour résumer :

  • La fonction interne ne peut être appelée que depuis des instructions de la fonction externe.
  • La fonction interne forme une fermeture : la fonction interne peut utiliser les paramètres et variables de la fonction externe, alors que la fonction externe ne peut pas utiliser les paramètres et variables de la fonction interne.

Les exemples suivant montrent des fonctions imbriquées :

function sommeDesCarrés(a,b) {
   function carré(x) {
      return x * x;
   }
   return carré(a) + carré(b);
}
a = sommeDesCarrés(2,3); // renvoie 13
b = sommeDesCarrés(3,4); // renvoie 25
c = sommeDesCarrés(4,5); // renvoie 41

Comme la fonction interne forme une fermeture, on peut appeler la fonction externe en spécifiant des paramètres à la fois pour la fonction externe et la fonction interne :

function externe(x) {
   function interne(y) {
      return x + y;
   }
   return interne;
}
résultat = externe(3)(5); // renvoie 8

Questions de performances

Remarquez comme x a été conservé lorsque interne a été renvoyé. Une fermeture préserve les paramètres et variables de toutes les visibilités qu'elle contient. Comme chaque appel fournit potentiellement des paramètres différents, une fermeture doit être créée pour chaque appel de la fonction externe. En d'autres termes, chaque appel à externe crée une fermeture. Pour cette raison, les fermetures peuvent utiliser une grande quantité de mémoire. Celle-ci ne peut être libérée que lorsque la fonction interne n'est plus accessible. Dans notre cas, la fermeture de interne est conservée dans résultat. Comme résultat est dans la visibilité globale, la fermeture continuera d'exister jusqu'à ce que le script soit déchargé (dans un navigateur, cela correspondra au moment où la page contenant le script sera fermée).

Comme cela n'est pas très performant, il est conseillé d'éviter les fermetures autant que possible, c'est-à-dire d'éviter d'imbriquer des fonctions. Par exemple, examinons l'exemple suivant :

function assigneOnclick(element) {
   element.onclick = function() {
      this.style.backgroundColor = 'blue';
   };
}

Cette fonction peut être réécrite pour éviter la fermeture. Cependant, la fonction interne anonyme devrait être nommée et ne plus être privée pour assigneOnclick :

function assigneOnclick(element) {
   element.onclick = element_onclick;
}

function element_onclick() {
   this.style.backgroundColor = 'blue';
}

Imbrications multiples de fonctions

Des fonctions peuvent être imbriquées sur plusieurs niveaux. Par exemple, une fonction (A) peut contenir une fonction (B) contenant une fonction (C). Tant B que C forment des fermetures dans ce cas, ainsi B peut accéder à A et C à B. De plus, comme C peut accéder à B qui peut accéder à A, C peut également accéder à A. Par conséquent, les fermetures contiennent plusieurs visibilités différentes. Elles contiennent récursivement les visibilités de toutes les fonctions les contenant. C'est ce que l'on appelle une chaîne de visibilités. Pourquoi une chaîne, c'est ce que nous verrons plus tard.

Examinons l'exemple suivant :

function A(x) {
   function B(y) {
      function C(z) {
         alert(x + y + z);
      }
      C(3);
   }
   B(2);
}
A(1); // affiche 6 (1 + 2 + 3)

Dans cet exemple, C accède au y de B et au x de A. C'est possible car :

  1. B forme une fermeture contenant A, donc B peut accéder aux paramètres et variables de A.
  2. C forme une fermeture contenant B.
  3. Comme la fermeture de B contient A, la fermeture de C contient également A, et C peut accéder aux variables et paramètres de B et A. En d'autres mots, C enchaîne les visibilités de B et A dans cet ordre.

Le contraire, cependant, n'est pas vrai. A ne peut pas accéder à C, car A ne peut accéder à aucun paramètre ou variable de B, dont C est une variable. Par conséquent, C reste privée pour B.

Conflits de noms

Lorsque deux paramètres ou variables dans le contexte d'une fermeture ont le même nom, il y a conflit de noms. C'est la visibilité la plus interne qui a la priorité la plus grande, et la plus externe la moindre. C'est la chaîne de visibilité. La première de la chaîne est la visibilité la plus interne, et la dernière est la plus externe. Examinons le code suivant :

function externe() {
   var x = 10;
   function interne(x) {
      return x;
   }
   return interne;
}
résultat = externe()(20); // renvoie 20 plutôt que 10

Le conflit de noms se passe pour l'instruction return x et est entre le paramètre x de interne et la variable x de externe. La chaîne de visibilité est ici {interne, externe, objet global}. Par conséquent, le x de interne a priorité sur le x de externe, et 20 (le x de interne) est renvoyé plutôt que 10 (le x de externe).

Constructeur Function, déclarations ou expressions de fonction

Comparez les cas suivants :

  1. une fonction définie avec le constructeur Function assigné à la variable multiplie
    var multiplie = new Function("x", "y", "return x * y;");
    
  2. une déclaration de fonction d'une fonction appelée multiplie
    function multiplie(x, y) {
       return x * y;
    }
    
  3. une expression de fonction d'une fonction anonyme assignée à la variable multiplie
    var multiplie = function(x, y) {
       return x * y;
    }
    
  4. une expression de fonction d'une fonction appelée nom_fonction assignée à la variable multiplie
    var multiplie = function nom_fonction(x, y) {
       return x * y;
    }
    

Tous font approximativement la même chose, avec quelques différences subtiles :

  • Il y a une différence entre le nom de la fonction et la variable à laquelle elle est assignée :
  • Une déclaration de fonction crée également une variable du même nom que la fonction. Par conséquent, contrairement aux fonctions définies sous forme d'expressions, les fonctions déclarées de cette manière sont accessibles par leur nom dans la visibilité dans laquelle elles ont été définies :
    function x() {}
    alert(x); // affiche la sérialisation de x sous la forme d'une chaîne
    

    L'exemple qui suit montre comment les noms de fonctions ne sont pas liés aux noms de variables auxquelles celles-ci sont assignées. Si une « variable de fonction » est assignée à un autre identifiant, elle conservera néanmoins son nom de fonction :

    function foo() {}
    alert(foo); // la chaîne affichée contient le nom de fonction "foo"
    var bar = foo;
    alert(bar); // la chaîne affichée contient toujours le nom "foo"
    
  • Une fonction définie par le constructeur Function n'a pas de nom de fonction. Cependant, dans le moteur JavaScript SpiderMonkey, la forme sérialisée de la fonction la montre comme si son nom était « anonymous ». Par exemple, alert(new Function()) affichera :
    function anonymous() {
    }
    

    Comme la fonction n'a en fait pas de nom, anonymous n'est pas une variable accessible depuis la fonction. Par exemple, le code suivant produira une erreur :

    var foo = new Function("alert(anonymous);");
    foo();
    
  • Contrairement aux fonctions définies comme des expressions ou par le constructeur Function, une fonction définie par une déclaration peut être utilisée avant la déclaration elle-même. Par exemple :
    foo(); // affiche FOO!
    function foo() {
       alert('FOO!');
    }
    
  • Une fonction définie sous la forme d'une expression hérite de la visibilité courante. C'est-à-dire que la fonction forme une fermeture. D'un autre côté, une fonction définie par un constructeur Function n'hérite d'aucune autre visibilité que la visibilité globale (dont toutes les fonctions héritent).
  • Les fonctions définies sous forme d'expressions et par déclaration sont analysées uniquement une fois, tandis que celles qui sont définies par le constructeur Function ne le sont pas. C'est-à-dire que le corps de la fonction passé sous la forme d'une chaîne au constructeur Function sera analysé à chaque évaluation. Même si une expression de fonction crée une fermeture à chaque fois, le corps de la fonction n'est pas ré-analysé, ce qui fait que les expressions restent plus rapides que "new Function(...)". Par conséquent, le constructeur Function doit être évité tant que possible.

Une déclaration de fonction est très facilement (et souvent non intentionnellement) transformée en une expression. Une déclaration cesse de l'être dans les cas suivants :

  • lorsqu'elle devient partie d'une expression
  • lorsqu'elle n'est plus un « élément source » d'une fonction ou du script lui-même. Un « élément source » est une instruction non imbriquée dans le script ou un corps de fonction :
    var x = 0;               // élément source
    if (x == 0) {            // élément source
       x = 10;               // pas un élément source
       function boo() {}     // pas un élément source
    }
    function foo() {         // élément source
       var y = 20;           // élément source
       function bar() {}     // élément source
       while (y == 10) {     // élément source
          function blah() {} // pas un élément source
          y++;               // pas un élément source
       }
    }
    

Exemples :

  • // déclaration de fonction
    function foo() {}
    
    // expression de fonction
    (function bar() {})
    
    // expression de fonction
    x = function hello() {}
    
  • if (x) {
       // expression de fonction
       function world() {}
    }
    
  • // déclaration de fonction
    function a() {
       // déclaration de fonction
       function b() {}
       if (0) {
          // expression de fonction
          function c() {}
       }
    }
    

Définition conditionnelle d'une fonction

Des fonctions peuvent être définies conditionnellement à l'aide d'expressions de fonction ou du constructeur Function.

Dans le script qui suit, la fonction zero n'est jamais définie et ne peut pas être appelée, car 'if (0)' est évaluée à false :

if (0)
   function zero() {
      document.writeln("Ceci n'existe pas.");
   }

Si le script est modifié de sorte que la condition devienne 'if (1)', la fonction zero devient définie.

Note : même si cela ressemble à une déclaration de fonction, il s'agit bien d'une expression étant donné qu'elle est imbriquée dans une autre instruction. Consultez les différences entre les déclarations de fonctions et les expressions de fonctions ci-dessus.

Note : certains moteurs JavaScript, ce qui n'est pas le cas de SpiderMonkey, traitent incorrectement toute expression de fonction portant un nom comme une déclaration de fonction. Ceci provoquerait la définition de la fonction zero même avec sa condition toujours fausse. Une manière plus sûre de définir des fonctions conditionnellement est de définir une fonction anonyme et de l'assigner à une variable :

if (0)
   var zero = function() {
      document.writeln("Ceci n'existe pas.");
   }

Utilisation de fonctions comme gestionnaires d'évènements

En JavaScript, les gestionnaires d'évènements DOM sont des fonctions (contrairement à des objets contenant une méthode handleEvent dans les liaisons DOM d'autres langages). Les fonctions sont passées à l'objet event comme premier et unique paramètre. Comme tout autre paramètre, si l'objet évènement ne doit pas être utilisé, il peut ne pas être mentionné dans la liste de paramètres formels.

Parmi les cibles d'évènements dans un document HTML se trouvent les objets window (objets Window dont les cadres (frames)), document (objets HTMLDocument) et les éléments (objets Element). Dans le DOM HTML, les cibles d'évènements ont des propriétés de gestionnaires d'évènements. Ces propriétés sont les noms d'évènements en minuscules précédés de "on", par exemple onfocus. Une autre manière plus robuste d'ajouter des gestionnaires d'évènements est définie dans DOM Level 2 Events.

Note : les évènements font partie du DOM, pas de JavaScript. (JavaScript fournit simplement une liaison vers le DOM.)

L'exemple suivant assigne une fonction au gestionnaire d'évènement focus d'un objet window.

window.onfocus = function() {
   document.body.style.backgroundColor = 'white';
};

Si une fonction est assignée à une variable, la variable peut être assignée à un gestionnaire d'évènement. Le code qui suit assigne une fonction à la variable setBGColor.

var setBGColor = new Function("document.body.style.backgroundColor = 'white';");

Cette variable peut ensuite être utilisée pour être assignée à un gestionnaire d'évènement de différentes manières. Voici deux d'entre-elles :

  1. utilisation des propriétés d'évènement DOM HTML
    document.form1.colorButton.onclick = setBGColor;
    
  2. avec l'attribut HTML event
    <input name="colorButton" type="button"
       value="Change background color"
       onclick="setBGColor();"/>
    

    Un gestionnaire d'évènement défini de cette manière est en fait une fonction, du nom de l'attribut enveloppant le code spécifié. C'est pour cette raison que les parenthèses dans "setBGColor()" sont nécessaires (plutôt que simplement "setBGColor"). C'est l'équivalent de :

    document.form1.colorButton.onclick = function onclick(event) {
       setBGColor();
    };
    

    Notez la manière dont l'objet event est passé à cette fonction anonyme dans un paramètre event. C'est ce qui permet au code d'utiliser cet objet :

    <input ...
        onclick="alert(event.target.tagName);"/>
    

Comme toute autre propriété se référant à une fonction, le gestionnaire d'évènement peut se comporter comme une méthode, et this fera référence à l'élément contenant le gestionnaire d'évènement. Dans l'exemple qui suit, la fonction à laquelle se réfère onfocus est appelée avec une valeur this pointant vers window.

window.onfocus();

Une erreur courante des débutants en JavaScript est d'ajouter des parenthèses et/ou des paramètres à la fin de la variable, c'est-à-dire d'appeler le gestionnaire d'évènement sans l'assigner. L'ajout de ces parenthèses assignera la valeur renvoyée par le gestionnaire d'évènement, qui est souvent undefined (si la fonction ne renvoie rien), plutôt que le gestionnaire d'évènement lui-même :

document.form1.button1.onclick = setBGColor();

Pour passer des paramètres à un gestionnaire d'évènement, celui-ci doit être enveloppé dans une autre fonction de la manière suivante :

document.form1.button1.onclick = function() {
   setBGColor('some value');
};

Compatibilité avec les versions antérieures

JavaScript 1.1 et versions précédentes

Il n'est pas possible d'imbriquer une instruction de fonction dans une autre instruction ou à l'intérieur d'elle-même.

Variables locales dans des fonctions

arguments : Un objet semblable à un tableau contenant les paramètres passés à la fonction actuellement en cours d'exécution.

arguments.callee : Indique la fonction actuellement en cours d'exécution.

arguments.caller: Indique la fonction ayant invoqué la fonction actuellement en cours d'exécution.

arguments.length : Indique le nombre de paramètres passés à la fonction.

Exemples

Exemple : formatage d'un nombre

La fonction qui suit renvoie une chaîne contenant une représentation formatée d'un nombre complété par des zéros initiaux.

// Cette fonction renvoie une chaîne complétée par des zéros initiaux
function ajZeros(nbr, longueur) {
   var nbrStr = nbr.toString();             // Initialise la valeur de retour
   var nbrZeros = longueur - nbrStr.length; // Calcule le nombre de zéros
   for (var i = 1; i <= nbrZeros; i++) {
      nbrStr = "0" + nbrStr;
   }
   return nbrStr;
}

Les instructions suivantes appellent la fonction ajZeros.

var resultat;
resultat = ajZeros(42,4); // renvoie "0042"
resultat = ajZeros(42,2); // renvoie "42"
resultat = ajZeros(5,4);  // renvoie "0005" 

Exemple : déterminer si une fonction existe

Il est possible de déterminer si une fonction existe en utilisant l'opérateur typeof. Dans l'exemple qui suit, un test est effectué pour déterminer si l'objet window a une propriété appelée noFunc qui est une fonction. Si c'est le cas, celle-ci est utilisée, dans le cas contraire d'autres instructions sont exécutées.

 if (typeof window.noFunc == 'function') {
   // utilise noFunc()
 } else {
   // fait autre chose
 }

Notez que dans le test if, on utilise une référence à noFunc ; il n'y a pas de parenthèses "()" après le nom de la fonction, donc celle-ci n'est pas appelée.

Voir aussi

Function, l'instruction function, l'opérateur function

{{ Besoin_de_révision_technique() }}

{{ languages( { "en": "en/Core_JavaScript_1.5_Reference/Functions", "es": "es/Referencia_de_JavaScript_1.5/Funciones", "ja": "ja/Core_JavaScript_1.5_Reference/Functions", "ru": "ru/\u042f\u0434\u0440\u043e_JavaScript_1.5_\u0421\u043f\u0440\u043e\u0432\u0447\u043d\u0438\u043a/Functions" } ) }}

Source de la révision

<p>
</p>
<h3 id="R.C3.A9sum.C3.A9" name="R.C3.A9sum.C3.A9"> Résumé </h3>
<p>D'une manière générale, une fonction est un « sous-programme » qui peut être <i>appelé</i> par du code externe (ou interne dans le cas d'un code récursif) à cette fonction. Comme le programme lui-même, une fonction est composée d'une séquence d'instructions appelée <i>corps de la fonction</i>. Des objets et valeurs peuvent être <i>passés</i> à une fonction, et celle-ci peut renvoyer un objet ou une valeur en retour.
</p><p>En JavaScript, les fonctions sont des objets de premier ordre. C'est-à-dire qu'elles peuvent être manipulées et transmises comme n'importe quel autre objet. Pour être précis, il s'agit d'objets <code><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Objets_globaux/Function">Function</a></code>.
</p>
<h3 id="G.C3.A9n.C3.A9ral" name="G.C3.A9n.C3.A9ral"> Général </h3>
<p>Chaque fonction en JavaScript est en fait un objet <code>Function</code>. Consultez <code><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Objets_globaux/Function">Function</a></code> pour plus d'informations sur les propriétés et méthodes des objets <code>Function</code>.
</p><p>Pour renvoyer une valeur, la fonction doit contenir une instruction <code><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Instructions/return">return</a></code> spécifiant la valeur de retour. Une fonction sans valeur de retour renverra <code>undefined</code>.
</p><p>Les paramètres n'étant pas des objets (comme les chaînes, nombres et valeurs booléennes) sont passés aux fonctions <i>par valeur</i>. La valeur est passée à la fonction où elle est stockée dans une nouvelle variable. Si la fonction change la valeur de la variable, celle-ci n'est pas propagée globalement ou dans la fonction appelante. Les paramètres objet (comme les tableaux et expressions rationnelles) sont passés aux fonctions <i>par référence</i>. Si l'on passe un objet en paramètre à une fonction et que la fonction change les propriétés de cet objet, cette modification est visible à l'extérieur de la fonction, comme le montre l'exemple suivant :
</p>
<pre class="eval">function maFonction(unObjet) {
   unObjet.marque = "Toyota";
}

var voiture = {marque: "Honda", modèle: "Accord", année: 1998};
alert(voiture.marque); // affiche 'Honda'
maFonction(voiture);   // passe l'objet voiture à la fonction
alert(voiture.marque); // affiche 'Toyota' car la propriété marque de voiture
                       // a été changée par la fonction
</pre>
<p>Le mot-clé <code>this</code> ne fait pas référence à la fonction en cours d'exécution, il est donc nécessaire de se référer aux objets <code>Function</code> par leur nom, même au sein du corps de la fonction elle-même. Il est également possible d'utiliser la propriété <a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Fonctions/arguments/callee">arguments.callee</a>.
</p>
<h3 id="D.C3.A9finition_de_fonctions" name="D.C3.A9finition_de_fonctions"> Définition de fonctions </h3>
<p>Trois manières de définir des fonctions existent :
</p>
<h4 id="La_d.C3.A9claration_d.27une_fonction_.28instruction_function.29" name="La_d.C3.A9claration_d.27une_fonction_.28instruction_function.29">La déclaration d'une fonction (instruction <code>function</code>)</h4>
<p>Il existe une syntaxe spéciale permettant de déclarer des fonctions (consultez <a href="/fr/Référence_de_JavaScript_1.5_Core/Instructions/function" title="fr/Référence_de_JavaScript_1.5_Core/Instructions/function"><code>l'instruction function</code></a> pour plus de détails) :</p>
<pre class="eval">function <em>[nom]</em>([<em>param</em>[, <em>param</em>[, … <em>param</em>]]]) {
   <em>instructions</em>
}
</pre>
<dl> <dt><code>nom</code> </dt> <dd>Le nom de la fonction. Peut être omis; fait référence à une fonction anonyme.</dd>
</dl>
<dl> <dt><code>param</code> </dt> <dd>Le nom d'un paramètre à passer à la fonction. Une fonction peut avoir jusqu'à 255 paramètres.</dd>
</dl>
<dl> <dt><code>instructions</code> </dt> <dd>Les instructions constituant le corps de la fonction.</dd>
</dl><h4 id="L.27expression_d.27une_fonction_.28op.C3.A9rateur_function.29" name="L.27expression_d.27une_fonction_.28op.C3.A9rateur_function.29"> L'expression d'une fonction (opérateur <code>function</code>) </h4>
<p>Une expression de fonction est semblable et a la même syntaxe qu'une déclaration de fonction (consultez <a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Op%c3%a9rateurs/Op%c3%a9rateurs_sp%c3%a9ciaux/L'op%c3%a9rateur_function">l'opérateur <code>function</code></a> pour plus de détails) :
</p>
<pre class="eval">function [<i>nom</i>]([<i>param</i>] [, <i>param</i>] […, <i>param</i>]) {
   <i>instructions</i>
}
</pre>
<dl><dt> <code>nom</code> </dt><dd> Le nom de la fonction. Peut ne pas être spécifié, auquel cas la fonction devient ce que l'on appelle une fonction anonyme.
</dd></dl>
<dl><dt> <code>param</code> </dt><dd> Le nom d'un paramètre à passer à la fonction. Une fonction peut avoir jusqu'à 255 paramètres.
</dd></dl>
<dl><dt> <code>instructions</code> </dt><dd> Les instructions constituant le corps de la fonction.
</dd></dl>
<h4 id="Le_constructeur_d.27objets_Function" name="Le_constructeur_d.27objets_Function"> Le constructeur d'objets <code>Function</code> </h4>
<p>Comme tous les autres objets, les objets <code>Function</code> peuvent être créés à l'aide de l'instruction <code>new</code> :
</p>
<pre class="eval">new Function ([<i>arg1</i>[, <i>arg2</i>[, ... <i>argN</i>]],] <i>corps</i>)
</pre>
<dl><dt> <code>arg1, arg2, ... arg<i>N</i></code> </dt><dd> Noms à utiliser pour les paramètres formels de la fonction. Chacun doit être une chaîne correspondant à un identifiant JavaScript valide ou une liste de telles chaînes séparées par des virgules. Par exemple "<code>x</code>", "<code>maValeur</code>", or "<code>a,b</code>".
</dd></dl>
<dl><dt> <code>corps</code> </dt><dd> Une chaîne contenant les instructions JavaScript constituant la définition de la fonction.
</dd></dl>
<p>L'appel du constructeur <code>Function</code> comme une fonction (sans utiliser l'opérateur <code>new</code>) a le même effet que son appel comme un constructeur. </p>
<h3 id="L.27objet_arguments" name="L.27objet_arguments"> L'objet <code>arguments</code> </h3>
<p>Il est possible d'accéder aux paramètres passés à une fonction depuis celle-ci en utilisant l'objet <code>arguments</code>. Voir <a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Fonctions/arguments">arguments</a>.
</p>
<h3 id="Visibilit.C3.A9_et_la_pile_de_fonctions" name="Visibilit.C3.A9_et_la_pile_de_fonctions"> Visibilité et la pile de fonctions </h3>
<p><span class="comment">some section about scope and functions calling other functions</span>
</p>
<h3 id="R.C3.A9cursivit.C3.A9" name="R.C3.A9cursivit.C3.A9"> Récursivité </h3>
<p>Une fonction peut faire référence à et s'appeler elle-même. Trois manières existent pour une fonction de s'identifier elle-même :
</p>
<ol><li> le nom de la fonction
</li><li> <code><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Fonctions/arguments/callee">arguments.callee</a></code>
</li><li> une variable visible faisant référence à la fonction
</li></ol>
<p>Par exemple, examinons la définition de fonction suivante :
</p>
<pre class="eval">var foo = function bar() {
   // des instructions ici
};
</pre>
<p>Au sein du corps de la fonction, les lignes suivantes sont toutes équivalentes :
</p>
<ol><li> <code>bar();</code>
</li><li> <code>arguments.callee();</code>
</li><li> <code>foo();</code>
</li></ol>
<p>Une fonction qui s'appelle elle-même est appelée <i>fonction récursive</i>. D'une certaine manière, la récursivité ressemble à une boucle. Ces deux constructions exécutent le même code plusieurs fois, et ont besoin d'une condition de terminaison (pour éviter une boucle infinie, ou dans ce cas, une récursivité sans fin). Par exemple, la boucle suivante :
</p>
<pre class="eval">var x = 0;
while (x &lt; 10) { // "x &lt; 10" est la condition de la boucle
   // faire quelque chose
   x++;
}
</pre>
<p>peut être convertie en une fonction récursive et un appel à cette fonction :
</p>
<pre class="eval">function loop(x) {
   if (x &gt;= 10) // "x &gt;= 10" est la condition de sortie (équivalente à "!(x &lt; 10)")
      return;
   // faire quelque chose
   loop(x + 1); // l'appel récursif
}
loop(0);
</pre>
<p>Cependant, certains algorithmes ne peuvent pas être réduits à de simple boucles itératives. Par exemple, pour obtenir tous les nœuds d'une structure arborescente (comme le <a href="fr/DOM">DOM</a>) il peut être plus facile d'utiliser la récursivité :
</p>
<pre class="eval">function parcoursArbre(noeud) {
   if (noeud == null) // 
      return;
   // faire quelque chose avec le noeud
   for (var i = 0; i &lt; noeud.childNodes.length; i++) {
      parcoursArbre(noeud.childNodes[i]);
   }
}
</pre>
<p>Contrairement à la fonction <code>loop</code> précédente, chaque appel récursif fait ici lui-même un grand nombre d'appels récursifs.
</p><p>Il est possible de convertir n'importe quel algorithme récursif en un algorithme non récursif, mais la logique en devient souvent plus complexe et nécessite d'utiliser une pile (stack). En réalité, la récursivité elle-même utilise une pile : la pile de fonctions.
</p><p>Ce comportement de pile peut être observé dans l'exemple suivant :
</p>
<pre class="eval">function foo(i) {
   if (i &lt; 0)
      return;
   document.writeln('début : ' + i);
   foo(i - 1);
   document.writeln('fin : ' + i);
}
foo(3);
</pre>
<p>qui affichera :
</p>
<pre class="eval">début : 3
début : 2
début : 1
début : 0
fin : 0
fin : 1
fin : 2
fin : 3
</pre>
<h3 id="Fonctions_imbriqu.C3.A9es_et_fermetures" name="Fonctions_imbriqu.C3.A9es_et_fermetures"> Fonctions imbriquées et fermetures </h3>
<p>Une fonction peut être intégrée dans une autre fonction. La fonction imbriquée n'est visible que depuis sa fonction contenante. Elle forme également une <i>fermeture</i> (<i>closure</i>).
</p>
<dl><dd> Une fermeture est une expression (typiquement une fonction) qui peut disposer de variables libres avec un environnement qui lie ces variables (qui "ferme" l'expression). <a class="external" href="http://jibbering.com/faq/faq_notes/closures.html">
</a></dd></dl><a class="external" href="http://jibbering.com/faq/faq_notes/closures.html">
<p>Une fonction imbriquée étant une fermeture, cela signifie qu'une telle fonction peut « hériter » des paramètres et variables de sa fonction contenante. En d'autres mots, la fonction interne contient la visibilité de la fonction externe.
</p><p>Pour résumer :
</p>
<ul><li> La fonction interne ne peut être appelée que depuis des instructions de la fonction externe.
</li></ul>
<ul><li> La fonction interne forme une fermeture : la fonction interne peut utiliser les paramètres et variables de la fonction externe, alors que la fonction externe ne peut pas utiliser les paramètres et variables de la fonction interne.
</li></ul>
<p>Les exemples suivant montrent des fonctions imbriquées :
</p>
<pre class="eval">function sommeDesCarrés(a,b) {
   function carré(x) {
      return x * x;
   }
   return carré(a) + carré(b);
}
a = sommeDesCarrés(2,3); // renvoie 13
b = sommeDesCarrés(3,4); // renvoie 25
c = sommeDesCarrés(4,5); // renvoie 41
</pre>
<p>Comme la fonction interne forme une fermeture, on peut appeler la fonction externe en spécifiant des paramètres à la fois pour la fonction externe et la fonction interne :
</p>
<pre class="eval">function externe(x) {
   function interne(y) {
      return x + y;
   }
   return interne;
}
résultat = externe(3)(5); // renvoie 8
</pre>
<h4 id="Questions_de_performances" name="Questions_de_performances"> Questions de performances </h4>
<p>Remarquez comme <code>x</code> a été conservé lorsque <code>interne</code> a été renvoyé. Une fermeture préserve les paramètres et variables de toutes les visibilités qu'elle contient. Comme chaque appel fournit potentiellement des paramètres différents, une fermeture doit être créée pour chaque appel de la fonction externe. En d'autres termes, chaque appel à <code>externe</code> crée une fermeture. Pour cette raison, les fermetures peuvent utiliser une grande quantité de mémoire. Celle-ci ne peut être libérée que lorsque la fonction <code>interne</code> n'est plus accessible. Dans notre cas, la fermeture de <code>interne</code> est conservée dans <code>résultat</code>. Comme <code>résultat</code> est dans la visibilité globale, la fermeture continuera d'exister jusqu'à ce que le script soit déchargé (dans un navigateur, cela correspondra au moment où la page contenant le script sera fermée).
</p><p>Comme cela n'est pas très performant, il est conseillé d'éviter les fermetures autant que possible, c'est-à-dire d'éviter d'imbriquer des fonctions. Par exemple, examinons l'exemple suivant :
</p>
<pre class="eval">function assigneOnclick(element) {
   element.onclick = function() {
      this.style.backgroundColor = 'blue';
   };
}
</pre>
<p>Cette fonction peut être réécrite pour éviter la fermeture. Cependant, la fonction interne anonyme devrait être nommée et ne plus être privée pour <code>assigneOnclick</code> :
</p>
<pre class="eval">function assigneOnclick(element) {
   element.onclick = element_onclick;
}

function element_onclick() {
   this.style.backgroundColor = 'blue';
}
</pre>
<h4 id="Imbrications_multiples_de_fonctions" name="Imbrications_multiples_de_fonctions"> Imbrications multiples de fonctions </h4>
<p>Des fonctions peuvent être imbriquées sur plusieurs niveaux. Par exemple, une fonction (A) peut contenir une fonction (B) contenant une fonction (C). Tant B que C forment des fermetures dans ce cas, ainsi B peut accéder à A et C à B. De plus, comme C peut accéder à B qui peut accéder à A, C peut également accéder à A. Par conséquent, les fermetures contiennent plusieurs visibilités différentes. Elles contiennent récursivement les visibilités de toutes les fonctions les contenant. C'est ce que l'on appelle une <i>chaîne de visibilités</i>. Pourquoi une chaîne, c'est ce que nous verrons plus tard.
</p><p>Examinons l'exemple suivant :
</p>
<pre class="eval">function A(x) {
   function B(y) {
      function C(z) {
         alert(x + y + z);
      }
      C(3);
   }
   B(2);
}
A(1); // affiche 6 (1 + 2 + 3)
</pre>
<p>Dans cet exemple, <code>C</code> accède au <code>y</code> de <code>B</code> et au <code>x</code> de <code>A</code>. C'est possible car :
</p>
<ol><li> <code>B</code> forme une fermeture contenant <code>A</code>, donc <code>B</code> peut accéder aux paramètres et variables de <code>A</code>.
</li><li> <code>C</code> forme une fermeture contenant <code>B</code>.
</li><li> Comme la fermeture de <code>B</code> contient <code>A</code>, la fermeture de <code>C</code> contient également <code>A</code>, et <code>C</code> peut accéder aux variables et paramètres de <code>B</code> <i>et</i> <code>A</code>. En d'autres mots, <code>C</code> <i>enchaîne</i> les visibilités de <code>B</code> et <code>A</code> dans cet ordre.
</li></ol>
<p>Le contraire, cependant, n'est pas vrai. <code>A</code> ne peut pas accéder à <code>C</code>, car <code>A</code> ne peut accéder à aucun paramètre ou variable de <code>B</code>, dont <code>C</code> est une variable. Par conséquent, <code>C</code> reste privée pour <code>B</code>.
</p>
<h4 id="Conflits_de_noms" name="Conflits_de_noms"> Conflits de noms </h4>
<p>Lorsque deux paramètres ou variables dans le contexte d'une fermeture ont le même nom, il y a <i>conflit de noms</i>. C'est la visibilité la plus interne qui a la priorité la plus grande, et la plus externe la moindre. C'est la chaîne de visibilité. La première de la chaîne est la visibilité la plus interne, et la dernière est la plus externe. Examinons le code suivant :
</p>
<pre class="eval">function externe() {
   var x = 10;
   function interne(x) {
      return x;
   }
   return interne;
}
résultat = externe()(20); // renvoie 20 plutôt que 10
</pre>
<p>Le conflit de noms se passe pour l'instruction <code>return x</code> et est entre le paramètre <code>x</code> de <code>interne</code> et la variable <code>x</code> de <code>externe</code>. La chaîne de visibilité est ici {<code>interne</code>, <code>externe</code>, objet global}. Par conséquent, le <code>x</code> de <code>interne</code> a priorité sur le <code>x</code> de <code>externe</code>, et 20 (le <code>x</code> de <code>interne</code>) est renvoyé plutôt que 10 (le <code>x</code> de <code>externe</code>).
</p>
<h3 id="Constructeur_Function.2C_d.C3.A9clarations_ou_expressions_de_fonction" name="Constructeur_Function.2C_d.C3.A9clarations_ou_expressions_de_fonction"> Constructeur <code>Function</code>, déclarations ou expressions de fonction </h3>
<p>Comparez les cas suivants :
</p>
<ol>
<li>
une fonction définie avec le constructeur <code>Function</code> assigné à la variable <code>multiplie</code>
<pre>var multiplie = new Function("x", "y", "return x * y;");
</pre>
</li>
<li>
une <i>déclaration de fonction</i> d'une fonction appelée <code>multiplie</code>
<pre>function multiplie(x, y) {
   return x * y;
}
</pre>
</li>
<li>
une <i>expression de fonction</i> d'une fonction anonyme assignée à la variable <code>multiplie</code>
<pre>var multiplie = function(x, y) {
   return x * y;
}
</pre>
</li>
<li>
une expression de fonction d'une fonction appelée <code>nom_fonction</code> assignée à la variable <code>multiplie</code>
<pre>var multiplie = function nom_fonction(x, y) {
   return x * y;
}
</pre>
</li>
</ol>
<p>Tous font approximativement la même chose, avec quelques différences subtiles :
</p>
</a><ul><a class="external" href="http://jibbering.com/faq/faq_notes/closures.html">
</a><li><a class="external" href="http://jibbering.com/faq/faq_notes/closures.html">
Il y a une différence entre le nom de la fonction et la variable à laquelle elle est assignée :
</a><ul><a class="external" href="http://jibbering.com/faq/faq_notes/closures.html">
<li>
Le nom de la fonction ne peut pas être modifié, tandis que la variable à laquelle la fonction est assignée peut être réassignée.
</li>
</a><li><a class="external" href="http://jibbering.com/faq/faq_notes/closures.html">
Le nom de la fonction ne peut être utilisé qu'au sein du corps de la fonction. Si l'on essaie de l'utiliser depuis l'extérieur, on obtiendra une erreur (ou <code>undefined</code> si le nom de la fonction a été déclaré précédemment avec une instruction <code>var</code>). Par exemple :
<pre> var y = function x() {};
 alert(x); // provoque une erreur
</pre>
</a><p><a class="external" href="http://jibbering.com/faq/faq_notes/closures.html">Le nom de la fonction apparait également lorsque celle-ci est sérialisée à l'aide de la méthode <code></code></a><code><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Objets_globaux/Function/toString">toString</a></code> de <code>Function</code>.
</p><p>D'un autre côté, la variable à laquelle la fonction est assignée est limitée uniquement à sa visibilité, qui comprend forcément l'endroit dans lequel la fonction est déclarée.
</p>
</li>
<li>
Comme le montre le quatrième exemple, le nom de la fonction peut être différent du nom de la variable à laquelle la fonction est assignée. Ces noms peuvent n'avoir aucun lien.
</li>
</ul>
</li>
<li>
Une déclaration de fonction crée également une variable du même nom que la fonction. Par conséquent, contrairement aux fonctions définies sous forme d'expressions, les fonctions déclarées de cette manière sont accessibles par leur nom dans la visibilité dans laquelle elles ont été définies : <pre>function x() {}
alert(x); // affiche la sérialisation de x sous la forme d'une chaîne
</pre>
<p>L'exemple qui suit montre comment les noms de fonctions ne sont pas liés aux noms de variables auxquelles celles-ci sont assignées. Si une « variable de fonction » est assignée à un autre identifiant, elle conservera néanmoins son nom de fonction :
</p>
<pre>function foo() {}
alert(foo); // la chaîne affichée contient le nom de fonction "foo"
var bar = foo;
alert(bar); // la chaîne affichée contient toujours le nom "foo"
</pre>
</li>
<li>
Une fonction définie par le constructeur <code>Function</code> n'a pas de nom de fonction. Cependant, dans le moteur JavaScript <a href="fr/SpiderMonkey">SpiderMonkey</a>, la forme sérialisée de la fonction la montre comme si son nom était « anonymous ». Par exemple, <code>alert(new Function())</code> affichera :
<pre>function anonymous() {
}
</pre>
<p>Comme la fonction n'a en fait pas de nom, <code>anonymous</code> n'est pas une variable accessible depuis la fonction. Par exemple, le code suivant produira une erreur :
</p>
<pre>var foo = new Function("alert(anonymous);");
foo();
</pre>
</li>
<li>
Contrairement aux fonctions définies comme des expressions ou par le constructeur <code>Function</code>, une fonction définie par une déclaration peut être utilisée avant la déclaration elle-même. Par exemple :
<pre>foo(); // affiche FOO!
function foo() {
   alert('FOO!');
}
</pre>
</li>
<li>
Une fonction définie sous la forme d'une expression hérite de la visibilité courante. C'est-à-dire que la fonction forme une fermeture. D'un autre côté, une fonction définie par un constructeur <code>Function</code> n'hérite d'aucune autre visibilité que la visibilité globale (dont toutes les fonctions héritent).
</li>
<li>
Les fonctions définies sous forme d'expressions et par déclaration sont analysées uniquement une fois, tandis que celles qui sont définies par le constructeur <code>Function</code> ne le sont pas. C'est-à-dire que le corps de la fonction passé sous la forme d'une chaîne au constructeur <code>Function</code> sera analysé à chaque évaluation. Même si une expression de fonction crée une fermeture à chaque fois, le corps de la fonction n'est pas ré-analysé, ce qui fait que les expressions restent plus rapides que "<code>new Function(...)</code>". Par conséquent, le constructeur <code>Function</code> doit être évité tant que possible.
</li>
</ul>
<p>Une déclaration de fonction est très facilement (et souvent non intentionnellement) transformée en une expression. Une déclaration cesse de l'être dans les cas suivants :
</p>
<ul>
<li>
lorsqu'elle devient partie d'une expression
</li>
<li>
lorsqu'elle n'est plus un « élément source » d'une fonction ou du script lui-même. Un « élément source » est une instruction non imbriquée dans le script ou un corps de fonction :
<pre>var x = 0;               // élément source
if (x == 0) {            // élément source
   x = 10;               // pas un élément source
   function boo() {}     // pas un élément source
}
function foo() {         // élément source
   var y = 20;           // élément source
   function bar() {}     // élément source
   while (y == 10) {     // élément source
      function blah() {} // pas un élément source
      y++;               // pas un élément source
   }
}
</pre>
</li>
</ul>
<p>Exemples :
</p>
<ul>
<li>
<pre>// déclaration de fonction
function foo() {}

// expression de fonction
(function bar() {})

// expression de fonction
x = function hello() {}
</pre>
</li>
<li>
<pre>if (x) {
   // expression de fonction
   function world() {}
}
</pre>
</li>
<li>
<pre>// déclaration de fonction
function a() {
   // déclaration de fonction
   function b() {}
   if (0) {
      // expression de fonction
      function c() {}
   }
}
</pre>
</li>
</ul>
<h4 id="D.C3.A9finition_conditionnelle_d.27une_fonction" name="D.C3.A9finition_conditionnelle_d.27une_fonction"> Définition conditionnelle d'une fonction </h4>
<p>Des fonctions peuvent être définies conditionnellement à l'aide d'expressions de fonction ou du constructeur <code>Function</code>.
</p><p>Dans le script qui suit, la fonction <code>zero</code> n'est jamais définie et ne peut pas être appelée, car '<code>if (0)</code>' est évaluée à <code>false</code> :
</p>
<pre class="eval">if (0)
   function zero() {
      document.writeln("Ceci n'existe pas.");
   }
</pre>
<p>Si le script est modifié de sorte que la condition devienne '<code>if (1)</code>', la fonction <code>zero</code> devient définie.
</p><p>Note : même si cela ressemble à une déclaration de fonction, il s'agit bien d'une expression étant donné qu'elle est imbriquée dans une autre instruction. Consultez les <a href="#Constructeur_Function.2C_d.C3.A9clarations_ou_expressions_de_fonction">différences entre les déclarations de fonctions et les expressions de fonctions</a> ci-dessus.
</p><p>Note : certains moteurs JavaScript, ce qui n'est pas le cas de <a href="fr/SpiderMonkey">SpiderMonkey</a>, traitent incorrectement toute expression de fonction portant un nom comme une déclaration de fonction. Ceci provoquerait la définition de la fonction <code>zero</code> même avec sa condition toujours fausse. Une manière plus sûre de définir des fonctions conditionnellement est de définir une fonction anonyme et de l'assigner à une variable :
</p>
<pre class="eval">if (0)
   var zero = function() {
      document.writeln("Ceci n'existe pas.");
   }
</pre>
<h3 id="Utilisation_de_fonctions_comme_gestionnaires_d.27.C3.A9v.C3.A8nements" name="Utilisation_de_fonctions_comme_gestionnaires_d.27.C3.A9v.C3.A8nements"> Utilisation de fonctions comme gestionnaires d'évènements </h3>
<p>En JavaScript, les gestionnaires d'évènements <a href="fr/DOM">DOM</a> sont des fonctions (contrairement à des objets contenant une méthode <code>handleEvent</code> dans les liaisons DOM d'autres langages). Les fonctions sont passées à l'objet <a href="fr/DOM/event">event</a> comme premier et unique paramètre. Comme tout autre paramètre, si l'objet évènement ne doit pas être utilisé, il peut ne pas être mentionné dans la liste de paramètres formels.
</p><p>Parmi les cibles d'évènements dans un document <a href="fr/HTML">HTML</a> se trouvent les objets <code>window</code> (objets <code>Window</code> dont les cadres (frames)), <code>document</code> (objets <code>HTMLDocument</code>) et les éléments (objets <code>Element</code>). Dans le <a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/">DOM HTML</a>, les cibles d'évènements ont des propriétés de gestionnaires d'évènements. Ces propriétés sont les noms d'évènements en minuscules précédés de "on", par exemple <code>onfocus</code>. Une autre manière plus robuste d'ajouter des gestionnaires d'évènements est définie dans <a class="external" href="http://www.w3.org/TR/DOM-Level-2-Events/">DOM Level 2 Events</a>.
</p><p>Note : les évènements font partie du DOM, pas de JavaScript. (JavaScript fournit simplement une liaison vers le DOM.)
</p><p>L'exemple suivant assigne une fonction au gestionnaire d'évènement <code>focus</code> d'un objet <code>window</code>.
</p>
<pre>window.onfocus = function() {
   document.body.style.backgroundColor = 'white';
};
</pre>
<p>Si une fonction est assignée à une variable, la variable peut être assignée à un gestionnaire d'évènement. Le code qui suit assigne une fonction à la variable <code>setBGColor</code>.
</p>
<pre>var setBGColor = new Function("document.body.style.backgroundColor = 'white';");
</pre>
<p>Cette variable peut ensuite être utilisée pour être assignée à un gestionnaire d'évènement de différentes manières. Voici deux d'entre-elles :
</p>
<ol>
<li>
utilisation des propriétés d'évènement DOM HTML
<pre>document.form1.colorButton.onclick = setBGColor;
</pre>
</li>
<li>
avec l'attribut HTML event <pre>&lt;input name="colorButton" type="button"
   value="Change background color"
   onclick="setBGColor();"/&gt;
</pre>
<p>Un gestionnaire d'évènement défini de cette manière est en fait une fonction, du nom de l'attribut enveloppant le code spécifié. C'est pour cette raison que les parenthèses dans "<code>setBGColor()</code>" sont nécessaires (plutôt que simplement "<code>setBGColor</code>"). C'est l'équivalent de :
</p>
<pre>document.form1.colorButton.onclick = function onclick(event) {
   setBGColor();
};
</pre>
<p>Notez la manière dont l'objet <code>event</code> est passé à cette fonction anonyme dans un paramètre <code>event</code>. C'est ce qui permet au code d'utiliser cet objet :
</p>
<pre>&lt;input ...
    onclick="alert(event.target.tagName);"/&gt;
</pre>
</li>
</ol>
<p>Comme toute autre propriété se référant à une fonction, le gestionnaire d'évènement peut se comporter comme une méthode, et <code>this</code> fera référence à l'élément contenant le gestionnaire d'évènement. Dans l'exemple qui suit, la fonction à laquelle se réfère <code>onfocus</code> est appelée avec une valeur <code>this</code> pointant vers <code>window</code>.
</p>
<pre class="eval">window.onfocus();
</pre>
<p>Une erreur courante des débutants en JavaScript est d'ajouter des parenthèses et/ou des paramètres à la fin de la variable, c'est-à-dire d'appeler le gestionnaire d'évènement sans l'assigner. L'ajout de ces parenthèses assignera la <i>valeur renvoyée par le gestionnaire d'évènement</i>, qui est souvent <code>undefined</code> (si la fonction ne renvoie rien), plutôt que le gestionnaire d'évènement lui-même :
</p>
<pre class="eval">document.form1.button1.onclick = setBGColor();
</pre>
<p>Pour passer des paramètres à un gestionnaire d'évènement, celui-ci doit être enveloppé dans une autre fonction de la manière suivante :
</p>
<pre class="eval">document.form1.button1.onclick = function() {
   setBGColor('some value');
};
</pre>
<h3 id="Compatibilit.C3.A9_avec_les_versions_ant.C3.A9rieures" name="Compatibilit.C3.A9_avec_les_versions_ant.C3.A9rieures"> Compatibilité avec les versions antérieures </h3>
<h4 id="JavaScript_1.1_et_versions_pr.C3.A9c.C3.A9dentes" name="JavaScript_1.1_et_versions_pr.C3.A9c.C3.A9dentes"> JavaScript 1.1 et versions précédentes </h4>
<p>Il n'est pas possible d'imbriquer une instruction de fonction dans une autre instruction ou à l'intérieur d'elle-même.
</p>
<h3 id="Variables_locales_dans_des_fonctions" name="Variables_locales_dans_des_fonctions"> Variables locales dans des fonctions </h3>
<p><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Fonctions/arguments">arguments</a> : Un objet semblable à un tableau contenant les paramètres passés à la fonction actuellement en cours d'exécution.
</p><p><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Fonctions/arguments/callee">arguments.callee</a> : Indique la fonction actuellement en cours d'exécution.
</p><p><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Fonctions/arguments/caller">arguments.caller</a>: Indique la fonction ayant invoqué la fonction actuellement en cours d'exécution.
</p><p><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Fonctions/arguments/length">arguments.length</a> : Indique le nombre de paramètres passés à la fonction.
</p>
<h3 id="Exemples" name="Exemples"> Exemples </h3>
<h4 id="Exemple_:_formatage_d.27un_nombre" name="Exemple_:_formatage_d.27un_nombre"> Exemple : formatage d'un nombre </h4>
<p>La fonction qui suit renvoie une chaîne contenant une représentation formatée d'un nombre complété par des zéros initiaux.
</p>
<pre class="eval">// Cette fonction renvoie une chaîne complétée par des zéros initiaux
function ajZeros(nbr, longueur) {
   var nbrStr = nbr.toString();             // Initialise la valeur de retour
   var nbrZeros = longueur - nbrStr.length; // Calcule le nombre de zéros
   for (var i = 1; i &lt;= nbrZeros; i++) {
      nbrStr = "0" + nbrStr;
   }
   return nbrStr;
}
</pre>
<p>Les instructions suivantes appellent la fonction ajZeros.
</p>
<pre class="eval">var resultat;
resultat = ajZeros(42,4); // renvoie "0042"
resultat = ajZeros(42,2); // renvoie "42"
resultat = ajZeros(5,4);  // renvoie "0005" 
</pre>
<h4 id="Exemple_:_d.C3.A9terminer_si_une_fonction_existe" name="Exemple_:_d.C3.A9terminer_si_une_fonction_existe"> Exemple : déterminer si une fonction existe </h4>
<p>Il est possible de déterminer si une fonction existe en utilisant l'opérateur <code>typeof</code>. Dans l'exemple qui suit, un test est effectué pour déterminer si l'objet <code>window</code> a une propriété appelée <code>noFunc</code> qui est une fonction. Si c'est le cas, celle-ci est utilisée, dans le cas contraire d'autres instructions sont exécutées.
</p>
<pre> if (typeof window.noFunc == 'function') {
   // utilise noFunc()
 } else {
   // fait autre chose
 }
</pre>
<p>Notez que dans le test <code>if</code>, on utilise une référence à <code>noFunc</code> ; il n'y a pas de parenthèses "()" après le nom de la fonction, donc celle-ci n'est pas appelée.
</p>
<h3 id="Voir_aussi" name="Voir_aussi"> Voir aussi </h3>
<p><a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Objets_globaux/Function">Function</a>, <a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Instructions/function">l'instruction <code>function</code></a>, <a href="fr/R%c3%a9f%c3%a9rence_de_JavaScript_1.5_Core/Op%c3%a9rateurs/Op%c3%a9rateurs_sp%c3%a9ciaux/L'op%c3%a9rateur_function">l'opérateur <code>function</code></a>
</p><p>{{ Besoin_de_révision_technique() }}
</p>
<div class="noinclude">
</div>
{{ languages( { "en": "en/Core_JavaScript_1.5_Reference/Functions", "es": "es/Referencia_de_JavaScript_1.5/Funciones", "ja": "ja/Core_JavaScript_1.5_Reference/Functions", "ru": "ru/\u042f\u0434\u0440\u043e_JavaScript_1.5_\u0421\u043f\u0440\u043e\u0432\u0447\u043d\u0438\u043a/Functions" } ) }}
Revenir à cette révision