Accueil

Traduction

Tutoriel sur JS natif, Vue.js, jQuery.js & Node.js

Tutoriel JavaScript - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

JavaScript : les fonctions

Lorsqu'une séquence d'instructions doit être exécutée plusieurs fois il faut utiliser une fonction.
Tous les langages proposent des fonctions natives c'est à dire déjà définies, prêtes à l'emploi.
Dans tous les langages le développeur peut créer ses propres fonctions.

Les fonctions natives de JavaScript

Nous avons déjà utilisé dans nos scripts des fonctions JavaScript natives suivantes : alert(), prompt(), parseInt(), parseFloat(), etc.
Ces fonctions sont dites natives car elles sont déjà définies dans le langage. Aussi les appelle t-on également fonctions prédéfinies.

Les fonctions citées sont natives & génériques car elles peuvent s'appliquer à différents types d'objets à la différence des méthodes.
Une méthode est une fonction propre à un type d'objet.
Par exemple vous pouvez appliquer à un objet de type String les méthodes trim(), toUpperCase(), toLowerCase() etc. (et seulement à une chaine).
Il existe aussi des méthodes pour les objets de type Date, de type Array, de type Map, de type Set, de type Document, etc.
J'ai consacré tout un chapitre sur les objets natifs de JS et leurs méthodes : les objets natifs de JS

Fonctions génériques et méthodes

Tapez les commandes suivantes dans la console !

>unechaine ="    aAbBcCdD     " 
'    aAbBcCdD     '
>typeof unechaine
'string'
>unechaine.toLowerCase()
'    aabbccdd     '
>unechaine.toUpperCase()
'    AABBCCDD     '
>parseInt(100.25)
100
>parseInt("100.25")
100
>unnombre =1234.565789
1234.565789
>unnombre.trim()
... unnombre.trim is not a function

J'applique les méthodes .toUpperCase() & .toLowerCase() à un objet de type String : la variable "unechaine".
Notez la syntaxe : objetString.méthode(). C'est ce qu'on appelle la notation pointée.
Si je tente d'appliquer la méthode .trim() à un nombre, j'ai une erreur !

Par contre je peux appliquer la fonction générique ParseInt() à un nombre mais aussi à une chaine (si cette chaine est au format numérique).
La syntaxe est alors différente : fonction(valeur).
typeof n'est pas une fonction mais un opérateur.

Programme reprenant les principales fonctions génériques

Le code de la page

Tout le script est repris dans une fonction "mère" nommée "mon_script". Ainsi le script de la page peut être appelé (ou pas) par simple clic sur un bouton de commande.

On reste dans la boucle tant que la valeur saisie n'est pas au format numérique (suite de chiffres avec éventuellement le point en guise de séparateur décimal).
La fonction isNaN() retourne VRAI tant que l'argument n'est pas au format numérique.
La valeur retournée par la fonction prompt est toujours de type string.
Pour effectuer des calculs il faut donc convertir cette valeur en numérique (entier ou décimal) avec respectivement les fonctions parseInt() & parseFloat()

Le rendu dans un Iframe

Les fonctions dites génériques sont en fait des méthodes de l'objet parent de JavaScript : window.
Le terme "window" peut être sous entendu.
Ainsi les instructions window.alert(expression), window.prompt(message) peuvent être simplifiées en alert(expression), prompt(message).

Créez ses propres fonctions

Les fonctions génériques et méthodes ne couvrent pas tous les besoins.
Donc un script contient souvent un bloc dans lequel on définit ses propres fonctions puis un bloc dans lequel on fait appel à ces fonctions.

Si vous souhaitez utiliser vos fonctions personnelles dans différentes pages, vous pouvez bien sûr créer un fichier de fonctions : un fichier d'extension .js. C'est d'ailleurs le principe de certaines librairies JS célèbres ...

Fonctions personnelles - niveau 1

Il s'agit d'une fonction personnelle basique car il n'y a pas de paramètre à passer (un argument lors de son appel) et cette fonction ne retourne pas de valeur.
Objet de cette fonction basique : calculer la surface d'un cercle de 2 cm de rayon.

Le script

Il est appelé pour un bouton de commande.
Instruction HTML dans BODY :
<button onclick ="mon_script()" > Appel du script </button >

function mon_script()
{
	function f_cercle() 
		{ 	// fonction qui calcule la surface d'un cercle de rayon 2 cm 
			var vrayon = 2 ; 
			var vsurface = vrayon * vrayon * 3.14 ;
			alert("surface du cercle : " + vsurface + "cm2") ; 
		}
		f_cercle() ; //appel fonction
		f_cercle(); // appel fonction 
		alert("type de f_cercle : " + typeof f_cercle); 
		alert(vrayon); // erreur : vrayon is not defined  
} // fin mon_script

Le script comprend deux parties :

Pour définir une fonction il faut utiliser le mot réservé function suivi du nom que vous donnez à cette fonction.
Ici il s'agit d'une fonction basique qui se nomme fsurface_cercle.
Les instructions de la fonction sont délimitées par une paire d'accolades.
Cette fonction calcule la surface d'un cercle de rayon 2cm. Il n'y a donc pas d'argument à passer.

Le rendu dans un Iframe

Dans le programme principal on appelle deux fois la fonction.
Puis on demande le type de "f_cercle" ; la réponse est "function". Une fonction est en fait une variable de type function.
Puis on demande d'afficher la variable vrayon ; la console affiche le message d'erreur : "vrayon is not defined". En effet vrayon est une variable créée dans le cadre de la fonction donc elle est inconnue du programme principal.

Toute variable déclarée dans le cadre d'une fonction n'est utilisable qu'au sein de cette fonction. On dit que la variable est locale.
Donc dans l'exemple f_cercle est une variable globale et vrayon est une variable locale.

Je rappelle que pour afficher la console du navigateur, il faut faire un clic droit dans l'onglet et sélectionner "inspecter".

Fonctions personnelles - niveau 2

La fonction de l'exemple précédent était d'un usage des plus limité : calcul de la surface d'un cercle de rayon 2 unités (cm ou mètre ou ...)
Nous allons maintenant définir et utiliser une fonction capable de calculer la surface d'un cercle indépendamment de son rayon et unité de mesure.
C'est possible mais alors il faut alors créer une fonction personnelle avec paramètres c'est à dire passage d'arguments lors de son appel.

Le script

Il est appelé par un bouton de commande comme dans l'exemple précédent.

function mon_script()
{
	function fsurface_cercle(rayon,unite) 
	{ 
	let surface = rayon * rayon * 3.14 ;
	alert(`surface du cercle  ${surface}  ${unite} carrés`) ; 
	} // fin fonction

// appels de la fonction
		fsurface_cercle(2,"cm") ; // premier appel
		let rayon = prompt('rayon du cercle ? '); 
		let unite = prompt('unite de mesure ? ') ; 
		fsurface_cercle(rayon, unite); // deuxième appel
		fsurface_cercle(15); // troisième appel
} // fin mon_script

Notez bien l'argument de la fonction alert() : `surface du cercle ${surface} ${unite} carrés`.
J'ai donc utilisé (pour éviter une concaténation fastidieuse) la notation "template strings" ou "littéraux de gabarit".
Pour en savoir davantage sur les littéraux de gabarit

Le rendu dans un Iframe

Cette fonction nommée fsurface_cercle calcule la surface d'un cercle quelque soit son rayon et l'unité de mesure (cm ou dm ou décimètre, ...).
Il s'agit donc d'une fonction avec deux paramètres. Donc pour appeler cette fonction il faut indiquer entre parenthèses deux arguments ; ce que je ne fais pas lors du troisième appel ...

Fonction personnelle - niveau 3

Vous savez que les fonctions natives sont paramétrables mais en plus retournent une valeur. Nous allons tenter de créer une fonction perso ayant les mêmes propriétés.
Pour qu'une fonction retourne une valeur (vers le programme principal) il faut que dans sa définition celle-ci comporte l'instruction return suivie de la valeur à retourner.

Le script

Il est appelé par un bouton de commande comme dans l'exemple précédent.

function mon_script()
{
	let fpuissance2 = function(nombre) 
	{ 	return nombre * nombre ; 	} 

	let vnombre = prompt('saisir un entier '); 
	alert(fpuissance2(vnombre)); 
	alert(fpuissance2(12)); 
	alert(typeof(fpuissance2));
} // fin mon_script

La fonction se nomme fpuissance2 et exige le passage d'un argument lors de son appel.

Au lieu d'écrire function fpuissance2(nombre) j'ai écrit var fpuissance2 = function(nombre). Ce qui montre qu'une fonction est en fait une forme particulière de variable.

Le rendu dans un Iframe

La dernière instruction retourne "function" !
Erreur d'exécution : tapez "4O (lettre O au lieu du zéro) et observez ...

La fonction nommée fpuissance2 calcule le carré d'un nombre, n'affiche rien mais retourne une valeur. Donc l'appel de cette fonction dans le programme principal affiche la valeur retournée.
Dans le programme principal j'appelle deux fois la fonction "fpuissance2".

Conversions automatiques

J'ai dit que toute saisie via la fonction prompt() est de type String. Et qu'il faut donc convertir en "Number" avant tout calcul. Or dans le script je ne convertis pas la valeur saisie avant de l'élever au carré ...
En effet en cas de multiplication / division / soustraction la conversion est automatique mais en cas en présence du signe + JavaScript procède à une concaténation. En effet le signe + est ambigu en JS : il désigne addition de nombres OU concaténation de chaines.

Créez et testez le script suivant !

function mon_script()
{
	let fdouble = function(nombre) 
	{ 	return nombre + nombre ; 	} 

	let vnombre1 = prompt('saisir un entier '); 
	alert(fdouble(vnombre1)); 
	let vnombre2 = prompt('saisir un entier ');
	alert(fdouble(vnombre2));
} // fin mon_script

Exécution :
Saisissez 7 ; affichage de 77
Saisissez 25 ; affichage de 2525
Il y a donc bien concaténation et non pas addition puisqu'il s'agit d'objets String.

Le bon code :
Insérez dans la fonction l'instruction : nombre = pareseFloat(nombre)
La conversion ne sera possible que si la saisie est au format numérique.

Appel de fonction avec en argument le mot "this"

L'argument passé lors de l'appel d'une fonction peut être le mot réservé this qui désigne l'objet courant.

Thème : script donnant des infos sur les images de la page : source & texte alternatif.

Le code HTML

Notez bien la syntaxe : ... onclick ='fafficher(this)' ...

this est un mot réservé de JS très pratique. Il désigne l'élément HTML courant (la cible de la manipulation).

Attention pour qu'une fonction s'applique à l'élément HTML courant il faut employer le mot magique "this" comme argument lors de l'appel de la fonction mais jamais comme paramètre dans la définition de la fonction.
Le nom du paramètre pour la description est toujours libre. Ici j'emploie le terme image puisque la fonction s'applique toujours à un élément IMG mais j'aurais pu utiliser "img"

Le script

Il se résume à une fonction nommée "fafficher()".
Cette fonction peut s'appliquer à n'importe quelle image de la page du moment qu'elle est l'objet courant.

function fafficher(image)
{
	let chemin = image.src ; 
	let texte = image.alt
	alert(`chemin image :  ${chemin} ` );
	alert (`texte alternatif de l'image :  ${texte} `) ; 
} // fin fonction

Notez l'emploi de la notation "template strings".

Le rendu dans un Iframe

Si je clique sur la première image j'ai des infos sur celle-ci : valeurs des attributs src & alt.
Si je clique sur la deuxième image j'ai les mêmes infos pour la deuxième image.
Je pourrais ajouter d'autres images dans la page avec à chaque fois dans l'instruction IMG l'attribut : ... onclick ='fafficher(this)'

Les fonctions anonymes

Sachez qu'il existe des fonctions anonymes.
Dans une même bloc on décrit et on appelle la fonction. Une fonction anonyme ne peut être utilisée qu'une fois.
La syntaxe d'une fonction anonyme sur un évènement est la suivante:

élément.évènement = function() 
	{ 
		instruction1; 
		instruction2;
		... ; 
		instructionN; 
	}

Thèmatique : nous voulons que le visiteur de la page puisse modifier la couleur du texte.

Solution traditionnelle : emploi d'une fonction nommée

Le rendu du script dans un Iframe

Pour chaque bouton on intègre un attribut événementiel. Par exemple : onclick = "fcouleur('green')

Ce qui veut dire que si vous cliquez sur ce bouton vous appelez la fonction fcouleur() avec passage d'une valeur : green.
Dans le script je déclare deux variables : titre et texte.

Pour cibler dans un script un élément HTML de la page j'utilise les nouvelles méthodes de l'objet document : querySelector() & querySelectorAll(). Ces deux méthodes acceptent comme argument un sélecteur CSS.

Notre code est tout à fait correct mais présente un inconvénient majeur : le code JS est mélangé avec le code HTML.

Solution moderne : avec des fonctions anonymes

Non seulement je vais utiliser des fonctons anonymes mais de plus je vais centralisé le JS dans le script. En effet la détection des évènements va se faire dans le script (et non plus via le HTML).
En d'autres termes je vais abandonner le gestionnaire d'évènements HTML pour le gestionnaire d'évènements JS.

Le code HTML

Plus aucune trace de JS dans le code HTML. Par contre j'ai affecté à chaque élément button un ID ; ID qui sera utilisé dans le script ...

Le script

let titre = document.querySelector('h1') ; 
let texte = document.querySelector('p') ; 
document.querySelector('#vert').onclick = function() 
		{ titre.style.color = 'green'; texte.style.color = 'green'; }
document.querySelector('#rouge').onclick = function() 
		{ titre.style.color = 'red'; texte.style.color = 'red'; }
document.querySelector('#bleu').onclick = function() 
		{ titre.style.color = 'blue'; texte.style.color = 'blue'; }

J'utilise désormais le gestionnaire d'évènements de JS (et non plus le gestionnaire d'évènements HTML). Ainsi tout le code JS est centralisé dans le script et plus aucun 'scorie' JS dans le code HTML.
Pour en savoir plus sur la gestion des évènements en JS : Les évènements

Étudions plus en détail la première fonction anonyme !

Le rendu dans un Iframe

Solution définitive

Vous pouvez trouver que le script précédent est un peu lourd.
Il le serait davantage si au lieu de modifier l'aspect de deux éléments HTML il s'agit d'en modifier 4 ...
Il serait plus logique que chaque fonction anonyme appelle à son tour une fonction nommée.

Le code HTML

Il y désormais un titre et trois éléments de type P. Donc le script doit modifier désormais le DOM pour 4 éléments (et non plus 2) !

Le script

function changer_couleur(couleur)
{
	document.querySelector('h1').style.color = couleur ; 
	document.querySelector('p').style.color = couleur; 
	document.querySelectorAll('p')[1].style.color = couleur ; 
	document.querySelectorAll('p')[2].style.color  = couleur ; 
	
} // fin fonction

// appel de la fonction changer_couleur via des fonctions anonymes : 
document.querySelector('#vert').onclick = function() {changer_couleur('green'); }
document.querySelector('#rouge').onclick = function() {changer_couleur('red');}
document.querySelector('#bleu').onclick = function() {changer_couleur('blue'); }

Chaque fonction anonyme consiste à appeler la fonction nommée "changer_couleur()" avec passage en argument de la couleur retenue.

Le rendu dans un Iframe

Fonctions particulières

Fonctions qui retournent plusieurs valeurs

Une fonction peut retourner un tableau indicé de valeurs.

Le script

function mon_script()
{
	function fcercle(rayon)
	{
		let aire = Math.round(rayon * rayon * 3.14); 
		let circonference = Math.round(rayon * 2 * 3.14) ; 
		let tab =[aire, circonference]; 
		return tab; // retourne un tableau de 2 éléments
	}
 
 
	let rayon =parseInt(prompt("saisir le rayon du cercle !")); 
	let tableau =fcercle(rayon);  //appel de la fonction fcercle
	document.write("aire : " + tableau[0]); 
	
	document.write("circonférence : " + tableau[1]); 
} // fin mon_script

La fonction fcercle() retourne deux valeurs sous forme d'un tableau indicé (objet Array) nommé "tab".
Donc lors de l'appel de fonction la variable d'affectation "tableau" est un tableau avec deux éléments. Le premier élément contient l'aire et le deuxième la circonférence.
Math.round(expression) : méthode de l'objet Math pour arrondir à l'entier le plus proche.

Le rendu dans un Iframe

Fonction avec un nombre variable de paramètres

Nous voulons créer une fonction qui cumule un nombre variable d'entiers : 2 ou 3 ou 4 ou 5 ou n ... Donc le nombre d'arguments à saisir lors de l'appel de la fonction est variable.

Le script

function mon_script()
{
	function fsomme(...tab)
	{
		let cumul = 0; 
		for (let i in tab) 
		{cumul+=tab[i] 	} ; 
		return cumul; 
	} // fin fsomme

// appels fonction
	let cumul1 = fsomme(10,10,30); 
	let cumul2 = fsomme(1,2,3,4); 
	let cumul3 = fsomme(1000, 2000); 
	console.log(cumul1); 
	console.log(cumul2);
	console.log(cumul3);
} // fin mon_script

Dans cette fonction "tab" est un tableau indicé.
Dans la parenthèse le nom du tableau doit être précédé de trois points.
Emploi de la syntaxe simplifiée "for ... in" pour parcourir le tableau.

Notez les différents appels de la fonction avec 3 puis 4 et enfin 2 arguments.

Le rendu dans un Iframe

La page se contente d'afficher "affichez la console !".
Pour ouvrir la console : clic droit sur l'iframe puis sélectionnez "inspecter" puis onglet "console".

Vous voyez apparaitre : 50 puis 10 puis 3000.

Fonctions fléchées

Avec la dernière version de ECMAScript, il est possible de définir des fonctions avec une syntaxe très simple.
Objectif : créer la fonction qui fait la sommme de deux nombres et multiplie le tout par un troisième nombre.

Le script

function mon_script()
{
	let x =10, y = 12, z = 13; w = 14;  
	// ci-dessous fonction nommmée standard
	let fstandard = function(n1,n2,n3) 
		{  return (n1 + n2) *  n3;	};
// fonction anonyme fléchée 
	let fflechee = (n1,n2,n3) => (n1 + n2) * n3;

alert("appel fonction standard : " +  fstandard(x,y,z)); 
alert(`appel fonction fléchée :   ${fflechee(y,z,w)} `); 
} // fin mon_script

Les fonctions fstandard & fflechee font exactement la même chose.
La première a une syntaxe standard alors que la seconde a un syntaxe simplifiée dite "fléchée".
Dans cette syntaxe simplifiée le mot "function" disparait ; le mot "return" est remplacé par une flèche d'où l'expression "fonction fléchée".
La définition de la fonction fléchée tient en une seule instruction : l'intérêt est là !
Quant à l'appel d'une fonction fléchée, il n'y a aucune différence par rapport à une fonction standard.
Notez que je peux utiliser la syntaxe "template strings" pour appeler une fonction : deuxième instruction alert()

Le rendu dans un Iframe