Support avancé sur la programmation web javascript
Programmation, Conception et Design Patterns en JavaScript; Web Côté Client avec jQuery
Rémy Malgouyres
LIMOS UMR 6158, IUT, département info
Université Clermont Auvergne B.P. 86
63172 AUBIERE cedex
Tous mes cours sur le Web sont sur le Web :
Coursdeprogrammation WEB surlesdocumentshypertexte HTML/CSS :
Tutorielsurle CMS Drupal :
Coursdeprogrammation WEB côtéserveuren PHP :
Coursdeprogrammation WEB côtéclienten JavaScript :
Courssurl’administrationdeserveurs(Serveurs WEB avec apache, SSL, LDAP ):
Table des matières
1 Premierspasen JavaScript 6
1.1 Balise . On a alors accès au document dans le code JavaScript et on peut sortir du code HTML :
Figure 1.1 : Illustration du code source 1.1
Code Source 1.1 : (cf. Fig 1.1)
<!doctype HTML>
” fr ”>
”UTF?8” />
Hello World en Javascript
1.1.2 Hello Word Avec la Méthode alert de Popup
Une autre manière d’insérer un script JavaScript dans un fichier HTML est de mettre le code JavaScript dans un fichier .js séparé, qui est inclus dans le HTML au niveau du header par une balise.
Figure 1.2 : Illustration du code source 1.2
Code Source 1.2 : (cf. Fig 1.2)
<!doctype HTML>
” fr ”>
”UTF?8” />
Hello World en Javascript
Code Source 1.3 :
alert (” Hello World !”) ;
Dans ce dernier cas, on ne peut pas générer de code directement dans le document HTML (avec document.write) dans le fichier JavaScript, mais il y a d’autres avantages (factorisation et mise en cache du code JavaScript partagé entre plusieurs pages HTML par exemple).
La fonction alert peut par exemple utilisé pour du débuggage si l’on ne dispose pas d’un outil de debug intégré dans notre IDE.
1.1.3 Document Template et Modification Dynamique de la Vue
Dans une application HTML/JavaScript côté client, on organise souvent le code avec, d’une part, un squelette de document HTML, appelé template, et d’autre part des fichiers JavaScript, inclus le plus tard possible dans la page HTML, qui modifie a posteriori le document pour générer certaines parties dynamiquement.
Code Source 1.4 :
<!doctype HTML>
” fr ”>
”UTF?8” />
Hello World en Javascript
<!?? Cré ation d ’ unepage”Template ” , squelette de notrepage ??>
<!?? Paragraphe qui va contenir le code ??>
” paragrapheResultat ”>
<!?? Inclusion du fichier JavaScript pour le code dynamique ??>
Code Source 1.5 :
// Géné ration dynamique de code HTML :var codeHTML = ” Hello world !” ;
// Mise à jour de la vue
document . getElementById(” paragrapheResultat ”) .innerHTML = codeHTML ;
1.2 Types, Variables et Portée
Le JavaScript est un langage faiblement typé, car on n’indique pas le type des variables lors de la déclaration. Lors le la déclaration des variables, le type est fixé implicitement par le type de la donnée affectée à la variable.
La déclaration de la variable peut contenir ou non le mot clef var. Un variable déclarée avec le mot clef var (on parle de déclaration explicite) est locale à la fonction où la variable est déclarée. Une variable déclarée sans le mot clef var (on parle de déclaration implicite) est globale.
Il n’y a pas, contrairement au C++ ou Java, de visibilité locale à un bloc. Un variable déclarée n’importe où dans une fonction est visible dans toute la fonction au moins. Pour cette raison, on déclarera systématiquement les variables locales à la fonction au début du corps de la fonction, contrairement aux bonnes pratiques dans d’autres langages où on déclare la variable au plus près de son point de première utilisation.
Dans les programmes assez gros structurés en modules ou packages, on peut créer en JavaScript l’équivalent d’un namespace par un patron de conception consistant à mettre le code de l’ensemble d’un module dans le corps de définition d’une fonction ou dans un littéral définissant un objet (voir plus loin pour la notion d’objet).
1.3 Fonctions
Les fonctions en JavaScript sont déclarées par le mot clef function. c’est un type de données comme un autre, et une fonction peut ainsi être affectée à une variable. Voici un exemple de fonction qui calcule le prix TTC d’un produit à partir de son prix hors taxes. Comme les paramètres des fonctions ne sont pas typés, on peut vérifier le type des paramètres dans la fonction et éventuellement renvoyer une exception si le type du paramètre effectif n’est pas le bon.
Code Source 1.6 :
<!doctype HTML>
” fr ”>
”UTF 8” />
4 ?
Fonctions
<!?? Cré ation d ’ unepage”Template ” , squelette de notrepage ??>
<!?? Paragraphe qui va contenir le code ??>
” paragrapheResultat ”>
<!?? Inclusion du fichier JavaScript pour le code dynamique ??>
Code Source 1.7 :
/** @description Calcule le prix TTC d ’un produit
* @function calculPrixTTC
* @param {number} prixHT ? Le prix hors taxe du produit
* @param {number} tauxTVA ? Le taux de TVA à appliquer
* @throws Si les paramètres prixHT et tauxTVA ne sont pas des nombres
*/
var calculPrixTTC = function (prixHT , tauxTVA){ if ( !( typeof prixHT == ”number”) | | !(typeof tauxTVA == ”number”) ){
throw new Error (”Function calculPrixTTC appel ée avec paramètre incorrect . ”)
}
return prixHT*(1.0+tauxTVA/100.0) ; } ;
// Géné ration dynamique de code HTML :var codeHTML = ”” ;
// Appel correct de la fonction :try{
codeHTML += ”Prix TTC : ” + calculPrixTTC (180.0 , 19.6) ;
}catch ( err ){ alert ( err ) ; }
// Appel incorrect de la fonction dé clenchant une exception :try{
codeHTML += ”Prix TTC : ” + calculPrixTTC (”coucou” , 19.6) ;
}catch ( err ){ alert ( err ) ;
}
// Mise à jour de la vue
document . getElementById(” paragrapheResultat ”) .innerHTML = codeHTML ;
Notons que l’on peut aussi déclarer une fonction un peu comme en PHP de la manière suivante :
Code Source 1.8 : Ne jamais faire ça!
function myFunction(myParam){
return (myParam < 0) ;
}
3 mais la fonction est alors globale (son nom existe dans tout le programme).
La bonne pratique consiste à déclarer les éléments d’un programme de sorte qu’ils aient la portée la plus locale possible, donc à déclarer la fonction avec le mot clé var comme dans le premier exemple de fonction ci-dessus.
1.4 Objets
Un objet JavaScript rassemble plusieurs propriétés, qui peuvent être des données, d’autres objets, ou encore des fonctions, alors appelées méthodes. Un objet n’est ni tout à fait une structure comme en C, ni tout à fait une classe comme dans un langage objet classique. Par exemple, un objet JavaScript n’a pas de visibilité (privée, public) pour ses propriétés. Par ailleurs, le principal mécanisme d’héritage en JavaScript se fait par la notion de prototype et est très différent de l’héritage dans les langages objet classiques. Là encore, on peut mimer une notion de visibilité via des patrons de conception. Les noms de propriétés peuvent être • Soit une chaîne de caractère (comme ”nom de propriété!”) quelconque (respecter les doubles quotes dans un tel cas).
- • Soit des noms légaux (commençant par une lettre suivi par une suite de lettres, chiffres, et underscores (caractère _) auquel cas les doubles quotes sont optionnelles pour désigner le nom.
1.4.1 Création d’un objet au moyen d’un littéral
On peut créer un nouvel objet par un littéral, en définissant ses propriétés des accolades {}. On met alors chaque nom de propriété suivi d’un : suivi de la valeur de la propriété. Les propriétés ainsi construites sont séparées par des virgules.
Code Source 1.9 :
/** @description Litt é ral dé finissant un objet appel é ” produit ” */var produit = {
”denomination” : ”Notebook sous Ubuntu 4 cores 2.0GB” ,
”prixHT” : 180.0 ,
”tauxTVA” : 19.6
} ;
/**
* @description Calcule le prix TTC d ’un produit
* @function calculPrixTTC
* @param {Object} prod ? Le produit à traiter
* @param {number} prod . prixHT ? Le prix hors taxe du produit
* @param {number} prod .tauxTVA ? Le taux de TVA à appliquer
* @throws Si les propri é t és du paramètre prod ne sont pas des nombres
*/
var calculPrixTTC = function(prod){
// Test d ’ existence des propri é t és de l ’ objet :if (”prixHT”in prod && ”tauxTVA”in prod){ return prod . prixHT*(1.0+prod .tauxTVA/100.0) ; }else{
// Rejet d ’une exception personnalis ée :
// On rejette un objet avec une prop . ”name” et une prop . ”message ”.throw {
name : ”Bad Parameter” ,
message : ”Mauvais type de paramètre pour la fonction calculPrixTTC”
} ;
}
} ;
// Essai d ’ appel de la fonctiontry{ var codeHTML = ”Prix TTC du produit \””+produit . denomination
+”\” : ”+calculPrixTTC ( produit ) ;
} catch (e) { // affichage de l ’ exception personnalis ée . alert (”Une erreur \”” + e .name + ”\” s ’ est produite :\n” + e . message) ;
}
// Mise à jour de la vue
document . getElementById(” paragrapheResultat ”) .innerHTML = codeHTML ;
1.4.2 Méthodes
Un objet peut contenir des propriétés qui sont de type function. On parle alors de méthode de l’objet. Dans une méthode, on accède aux propriétés des l’objet grâce à l’identificateur this, désignant l’objet auquel appartien la méthode.
Figure 1.3 : Illustration du code source 1.10
Code Source 1.10 : (cf. Fig 1.3)
/** @description Litt é ral dé finissant un objet appel é ” produit ” */var produit = {
”denomination” : ”Notebook sous Ubuntu 4 cores 2.0GB” ,
”prixHT” : 180.0 , ”tauxTVA” : 19.6 ,
/**
* @description Calcule le prix TTC d ’un produit
* @method calculPrixTTC
* @return Le prix TTC du produit
*/ getPrixTTC : function (){ return this . prixHT*(1.0+ this .tauxTVA/100.0) ; }
} ;
// Fonction dans le contexte global :
/** @description Génère le code HTML pour afficher un objet quelconque
* @function getHtmlObjet
* @param {Object} objet ? L ’ objet à traiter
* @return Le code HTML pour afficher l ’ objet
*/var getHtmlObjet = function( objet ){ var chaine = ”” ;
// Parcours de toutes les propri é t és de l ’ objet ( style ” foreach ”) :for (var nom in objet ){ chaine += ” objet [\” ”+nom+” \”] = ”
+ objet [nom] // Appel de la mé thode toString par dé faut +”<br/>” ;
}
return chaine ;
} ;
// appel d ’une fonction dé finie dans le contexte global :var codeHTML = ”
” + getHtmlObjet( produit ) + ”
” ; // appel d ’une mé thode : codeHTML += ”
Prix TTC : ” + produit . getPrixTTC () + ”” ;
// Mise à jour de la vue
document . getElementById(” paragrapheResultat ”) .innerHTML = codeHTML ;
Une méthode d’objet JavaScript n’est pas tout à fait comme une méthode d’un langage à objet classique, car la méthode JavaScript existe en autant d’exemplaires qu’il y a d’instance des objets. Nous verrons plus loin la notion de prototype, qui permet de crée des méthodes qui existent en un seul exemplaire pour toute une classe d’objets ayant les mêmes propriétés.
1.4.3 Objets Imbriqués (Composites et Composés)
Il est possible, dans un littéral d’objet, de créer une propriété qui est elle-même un objet. On peut parler de composite pour l’objet qui contient un autre objet, qui est alors un composé.
Figure 1.4 : Illustration du code source 1.11
Code Source 1.11 : (cf. Fig 1.4)
/** @description Litt é ral dé finissant un objet appel é ” produit ” */var produit = { denomination : ”Notebook sous Ubuntu” , prixHT_base : 180.0 ,
tauxTVA : 20.0 ,
/** @description Objet ”nich é” dans un sur?objet ( Options du produit ) */ options : {
processor : ” Intel 4 cores 2.5 Ghz” ,
memory : ”4GB” ,
” prix suppl émentaire HT” : 50.0 ,
/** @description Génère le code HTML des options
* @method getHTML
*/ getHtml : function (){
return this . processor + ” ” + this .memory +
” ( suppl ément : ” + this [ ” prix suppl émentaire HT” ] + ” &euro ;)
} } ,
/** @description Génère le code HTML complet du produit
* @method getHTML
*/ getHtml : function (){ return this . denomination +
”<br/>prix TTC tout compris : ”
+ ( this . prixHT_base + ( this . options [ ” prix suppl émentaire HT” ]
)
*(1.0+ this .tauxTVA/100.0)
+ ” &euro ;<br/>” + this . options . getHtml () + ”<br/>” ;
}
} ;
// appel d ’une mé thode :var codeHTML = ”
” + produit . getHtml () + ”
” ;
// Mise à jour de la vue
document . getElementById(” paragrapheResultat ”) .innerHTML = codeHTML ; ” ;
| | 0.0)
On peut aussi choisir de définir l’objet contenant les options dans une méthode getOptions du composite, qui retourne un objet. La méthode getOptions joue alors un rôle de “fabrique”.
Code Source 1.12 :
/** @description Litt é ral dé finissant un objet appel é ” produit ” */var produit = { denomination : ”Notebook sous Ubuntu” , prixHT_base : 180.0 ,
tauxTVA : 20.0 ,
/** @description Construction d ’un objet dans une mé thode
*/ getOptions : function (){
// Cré ation de l ’ objet option dans la fonction (” fabrique ”)return { processor : ” Intel 4 cores 2.5 Ghz” ,
memory : ”4GB” ,
” prix suppl émentaire HT” : 50.0 ,
/** @description Génère le code HTML des options
* @method getHTML
*/ getHtml : function (){
return this . processor + ” ” + this .memory +
” ( suppl ément : ” + this [ ” prix suppl émentaire HT” ] + ” &euro ;)” ;
}
} ; } ,
/** @description Génère le code HTML complet du produit * @method getHTML
*/ getHtml : function (){ return this . denomination +
”<br/>prix TTC tout compris : ”
+ ( this . prixHT_base
+ ( this . getOptions () [ ” prix suppl émentaire HT” ] | | 0.0) ) *(1.0+ this .tauxTVA/100.0)
+ ” &euro ;<br/>” + this . getOptions () . getHtml () + ”<br/>” ;
}
} ;
// appel d ’une mé thode :var codeHTML = ”
” + produit . getHtml () + ”
” ;
// Mise à jour de la vue
document . getElementById(” paragrapheResultat ”) .innerHTML = codeHTML ;
1.4.4 Constructeur d’Object et mot réservé new
On peut créer un objet via le constructeur Object. Voici un exemple où l’on crée un objet qui représente un produit. On crée ensuite une fonction qui calcule le prix TTC de ce produit après avoir testé l’existence d’attributs.
Code Source 1.13 :
/** @description Instantiation d ’un Objet ” produit ” */var produit = new Object () ; // Ajout dynamique de propri é t és produit . denomination = ”Notebook sous Ubuntu 4 cores 2.0GB” ; produit . prixHT = 180.0 ; produit .tauxTVA = 20.0 ;
/**
* @description Calcule le prix TTC d ’un produit
* @function calculPrixTTC
* @param {Object} prod ? Le produit à traiter
* @param {number} prod . prixHT ? Le prix hors taxe du produit
* @param {number} prod .tauxTVA ? Le taux de TVA à appliquer
* @throws Si les propri é t és du paramètre prod ne sont pas des nombres
*/
var calculPrixTTC = function(prod){ if (”prixHT”in prod && ”tauxTVA”in prod){ return prod . prixHT*(1.0+prod .tauxTVA/100.0) ;
}else{ throw new Error (”Mauvais type de paramètre pour la fonction calculPrixTTC”) ;
}
}
// Géné ration de code HTML
var codeHTML = ”Prix TTC du produit \””+produit . denomination+”\” : ”+ calculPrixTTC ( produit ) ;
// Mise à jour de la vue
document . getElementById(” paragrapheResultat ”) .innerHTML = codeHTML ;Dans la mesure du possible, il est préférable de définir les objets JavaScript par des littéraux car ça peut être plus efficace que la construction dynamique avec le constructeur Object.
1.5 Tableaux (le type Array)
1.5.1 Notion d’Array et construction
Dans les langages classique, un tableau est une séquence d’éléments, contigus en mémoire, avec un accès aux éléments par un indice entier. En JavaScript, les tableaux sont des objets dont les propriétés sont automatiquement nommées avec les chaînes '0', '1', '2'. Ces tableaux possèdent certains avantages des objets, comme par exemple la possibilité d’avoir des éléments de types différents, mais sont significativement plus lents que les tableaux classiques. Un tableau peut être créé par un littéral, entre crochets [ ].