« Tutoriel JavaScript de base » : différence entre les versions

De EduTech Wiki
Aller à la navigation Aller à la recherche
(Annulation des modifications 179495 de Nicolas (discussion))
Balise : Annulation
 
(185 versions intermédiaires par 13 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
{{tutoriel
{{tutoriel
|fait_partie_du_cours=JavaScript
|fait_partie_du_cours=Initiation à la pensée computationnelle avec JavaScript
|fait_partie_du_module=Références JavaScript
|module_précédant=JavaScript dans d'autres environnements
|pas_afficher_sous-page=Non
|pas_afficher_sous-page=Non
|page_precedente=JavaScript
|page_precedente=Références JavaScript
|page_suivante=JQuery
|page_suivante=Tutoriel JavaScript côté client
|statut=à améliorer
|statut=à finaliser
|difficulté=intermédiaire
|difficulté=intermédiaire
|pages_prérequises=JavaScript
|voir_aussi=Computation avec JavaScript
|voir_aussi=JQuery
|cat tutoriels=JavaScript
}}
}}
==Introduction==
==Introduction==
Ce tutoriel présente un survol des caractéristiques principales du langage [[JavaScript]] relatives à l’utilisation « côté client », c’est-à-dire l’utilisation la plus fréquente dans des pages/applications web à l’intérieur d’un navigateur.
Cette page propose un survol sur les éléments fondamentaux du langage JavaScript. Les notions présentées dans cette page sont valables pour tous les environnements dans lesquels un interprète du langage JavaScript est disponible, notamment :
===Rappel de la structure d'une page web===
Avant d'aborder JavaScript, il est utile de rappeler la structure d'une page web qui se compose généralement de trois éléments :


* '''HTML''' : cet élément détermine le contenu de la page, c'est-à-dire les éléments textuels et graphiques affichés à l'écran.
* [[Tutoriel JavaScript côté client | JavaScript côté client]]
* '''CSS''' : cet élément détermine la mise en page, la manière de présenter les éléments HTML de la page. On peut déterminer à travers les CSS les couleurs, les polices, l'alignement des éléments, etc.
* [[Node.js | JavaScript côté serveur]]
* '''JavaScript''' : cet élément ajoute des interactions et des comportements (ou effets) au contenu et/ou à la présentation de la page. Ces phénomènes permettent de modifier la page sans la nécessité d'actualiser le navigateur.


===Présentation de JavaScript===
Pour un aperçu général et plus théorique du langage, voir la page [[JavaScript]]. Pour des novices en programmation, voir d'abord l'[[introduction à la programmation]].
JavaScript est un langage de scripting qui a vécu plusieurs évolutions dans le temps, ce qui complique en quelque sorte son apprentissage parce que le code et les tutoriels présents dans le web varient fortement en fonction de leur date. Non seulement le code a changé dans le temps, mais aussi la "philosophie" de JavaScript. Au début, JavaScript était considéré comme un outil utilisé principalement dans les formulaires web. Aujourd'hui, grâce à l'évolution des navigateurs web, JavaScript est devenu l'outil le plus utilisé pour les interactions client-side des pages web, mais il est également utilisé dans le développement d'applications pour les dispositifs mobiles, dans le développement de logiciels desktop et même dans le développement server-side. Malgré la similarité du nom, Java et JavaScript sont deux langages différents.


===Outils pour le développement et le débug===
=== Conseil de lecture ===
Pour développer en JavaScript seulement deux outils sont strictement nécessaires :


* Un '''navigateur web'''
Cette page présente une grande quantité d'information en relativement peu d'espace. Elle explique principalement les fonctionnalités, mais sans un objectif bien spécifique, ce qui peut décourager surtout les novices. Nous conseillons de lire d'abord les sections '''Introduction''' et '''Syntaxe de JavaScript''', et par la suite d'utiliser cette page comme '''référence croisée''' avec les pages :
* Un '''éditeur de texte'''


Des outils supplémentaires peuvent sans doute rendre le développement plus aisé. Voici une liste de ces outils :
* {{Goblock|[[Computation avec JavaScript]]}}
 
* {{Goblock|[[Tutoriel JavaScript côté client]]}}
* [[Brackets]] : éditeur de texte open-source qui supporte la syntaxe et le complètement automatique du code JavaScript
* {{Goblock|[[Interactivité avec JavaScript]] }}
* [https://developer.chrome.com/devtools Google Chrome Developer Tools] : outils de développement et débug du navigateur Google Chrome
* [https://developer.mozilla.org/en-US/docs/Tools Firefox Developer Tools] : outils de développement et débug du navigateur Firefox


===Console JavaScript===
===Console JavaScript===
Pour contrôler la présence d'erreurs d'une page directement dans un navigateur web ou pour essayer du code, vous pouvez utiliser les Consoles d'erreurs des navigateurs.
Les exemples présentés dans ce tutoriel utilisent des éléments fondamentaux du langage et peuvent donc marcher dans tout environnement JavaScript. La manière la plus simple pour suivre/tester le code présenté est d'utiliser directement la '''Console JavaScript''' disponible dans un navigateur. Il suffit d'ouvrir la Console et de garder en même temps cette page ouverte :


* Internet Explorer : Menu Outils > Outils de développement (ou F12)
* Internet Explorer : Menu Outils > Outils de développement (ou F12)
* Firefox : F12 ou plus de fonctionnalités via l'extension [http://getfirebug.com/ Firebug]
* Firefox : le scratchpad (SHIFT F4), sinon la console (F12) qui permet d'entrer une ligne.
* Chrome : Menu Outils > Console JavaScript (ou F12)
* Chrome : Menu Outils > Console JavaScript (ou F12)
* Safari : D'abord dans les Options > Avancées cocher la case "Afficher le menu Développement dans la barre des menus", puis CTRL+Alt+I ou CTRL+Alt+C
* Safari : D'abord dans les Options > Avancées cocher la case "Afficher le menu Développement dans la barre des menus", puis CTRL+Alt+I ou CTRL+Alt+C
Ligne 46 : Ligne 40 :
La console JavaScript est un endroit très utile pour tester du code JavaScript pour deux raisons :
La console JavaScript est un endroit très utile pour tester du code JavaScript pour deux raisons :


* On peut saisir directement du code dans la console et l'évaluer. Dans l'image suivante, les lignes précédées par > sont des lignes avec du code, et les lignes précédées par <- proposent le résultat de l'évaluation du code.
# On peut saisir directement du code dans la console et l'évaluer. Dans l'image suivante, les lignes précédées par > sont des lignes avec du code, et les lignes précédées par <- proposent le résultat de l'évaluation du code.
[[Fichier:JavaScript console code.png|none|frame|La console du navigateur évalue directement du code.]]
#:[[Fichier:JavaScript console code.png|none|frame|La console du navigateur évalue directement du code.]]
 
#:
 
# On peut communiquer avec la Console JavaScript. Par exemple la notation <code>console.log()</code> permet d'écrire un message dans la Console. Pour ceux qui ont utilisé Flash, cette instruction est similaire à la fonction trace() de Flash. Voici un exemple :
* On peut communiquer avec la Console JavaScript. Par exemple la notation <code>console.log()</code> permet d'écrire un message dans la Console. Pour ceux qui ont utilisé Flash, cette instruction est similaire à la fonction trace() de Flash. Voici un exemple :
#:<source lang="JavaScript">
 
for(var i = 0; i < 5; i++) {
<source lang="HTML5">
    console.log("Cycle actuel : " + i);
<script>
window.onload = function() {
  for(var i = 0; i < 5; i++) {
      console.log("Cycle actuel : " + i);
  }
}
}
</script>
</source>
</source>
Le résultat de ce script dans la console JavaScript est le suivant :
#:Le résultat de ce script dans la console JavaScript est le suivant :
 
#:[[Fichier:JavaScript tutoriel base console log.jpg|cadre|néant|La méthode log() de l'objet Console permet d'afficher des messages dans la console JavaScript.]]
[[Fichier:JavaScript tutoriel base console log.jpg|cadre|néant|La méthode log() de l'objet Console permet d'afficher des messages dans la console JavaScript.]]
 
Une fois terminé la partie de développement, il est mieux d'enlever toute référence à la Console.


==Syntaxe de JavaScript==
==Syntaxe de JavaScript==
Ligne 71 : Ligne 56 :
* Voir [[Introduction à la programmation]] pour un aperçu sur le fonctionnement d'un langage de programmation.
* Voir [[Introduction à la programmation]] pour un aperçu sur le fonctionnement d'un langage de programmation.


JavaScript est un langage de scripting, il permet donc d'écrire des algorithmes qui sont évalués et exécutés par un interprète. Pour que l'interprète puisse comprendre le code source, il faut respecter les règles syntaxiques du langage JavaScript. Ces règles déterminent principalement deux aspects :
JavaScript est un langage de scripting, il permet donc d'écrire des algorithmes qui sont évalués et exécutés par un interprète. (Pour être précis, l'interprète JavaScript est plutôt un hybride avec un compilateur "en temps réel", voir Simpson, 2015). Pour que l'interprète puisse comprendre le code source, il faut respecter les règles syntaxiques du langage JavaScript. Ces règles déterminent principalement deux aspects :


# Qu'est-ce qu'un code JavaScript valide?, car la présence d'erreurs dans le code arrête l'exécution du script;
# '''Le code est-il valide?'''
# Si le code est valide, qu'est-ce qu'il est censé faire en termes de Input/Output?
#:La présence d'erreurs syntaxiques/orthographiques dans le code source arrête l'exécution du script.
# '''Qu'est-ce que le code est censé faire?'''
#: Le code source détermine la logique de l'application en termes de Input/Ouput.


Pour déterminer quel est l'objectif du code, l'interprète JavaScript lit le code et le transforme en instructions (statement en anglais). Les instructions sont une suite d'expressions qui combinent les éléments du langage. Voici ci-dessous une liste des éléments principaux du langage avec leur syntaxe.
Pour déterminer quel est l'objectif du code, l'interprète JavaScript lit le code (de gauche à droite, de haut en bas) et le transforme en instructions. Les instructions sont une suite d'expressions qui combinent des données et des algorithmes. Pour écrire des instructions que l'interprète puisse comprendre et exécuter, il faut combiner les éléments syntaxiques propres au langage : écrire du code source en JavaScript. De suite, nous proposons un premier aperçu sur les éléments principaux de la syntaxe JavaScript. Il ne s'agit que d'un survol pour identifier les éléments dans les exemples de code. Nous conseillons de '''tester directement le code dans votre console JavaScript''' pour une meilleure compréhension.


===Syntaxe générale===
===Syntaxe générale===


JavaScript possède une syntaxe assez flexible par rapport à d’autres langages de programmation, mais il y a néanmoins certaines règles à respecter. De plus, le fait que JavaScript soit assez flexible ne signifie pas qu’un code bien structuré ne présente pas d’avantages ; au contraire, un code qui respectent une cohérence syntaxique de manière stricte sera plus simple à lire, comprendre et modifier par la suite. Voici quelques caractéristiques principales :
JavaScript possède une syntaxe assez flexible par rapport à d’autres langages de programmation, mais il y a néanmoins certaines règles à respecter. De plus, le fait que JavaScript soit assez flexible ne signifie pas qu’un code bien structuré ne présente pas d’avantages ; au contraire, un code qui respecte une cohérence syntaxique de manière stricte sera plus simple à lire, à comprendre et à modifier par la suite. Voici quelques caractéristiques principales :


* JavaScript est un langage « case sensitive », c’est-à-dire qu’il fait distinction entre minuscules et majuscules. Le mot clé pour déclarer une variable (voir plus bas) sera donc <code>var</code> et non pas Var ou VAR ;
* JavaScript est un langage « case sensitive », c’est-à-dire qu’il fait la distinction entre minuscules et majuscules. Le mot clé pour déclarer une variable (voir plus bas) sera donc <code>var</code> et non pas Var ou VAR ;
* JavaScript ne fait pas différence entre un espace ou plusieurs, et il est assez flexibles également avec les retours à la ligne ;
* JavaScript ne fait pas différence entre un ou plusieurs espaces, et il est assez flexible avec les retours à la ligne ;
* Pour délimiter une instruction de code (i.e. un statement) on termine avec un <code> ;</code>
* Pour délimiter une instruction de code (i.e. un statement) on termine avec un <code> ;</code>
* Pour délimiter un bloc de code on utilise les parenthèses graphes  <code>{ … }</code> ; les blocs de code concernent notamment les structures de contrôles, les fonctions et les cycles/boucles (voir plus bas)
* Pour délimiter un bloc de code, on utilise les parenthèses graphes  <code>{ … }</code> ; les blocs de code concernent notamment les structures de contrôle, les fonctions et les cycles/boucles (voir plus bas)


===Commentaire===
===Commentaire===
Il existe deux manières de commenter le code JavaScript selon le nombre de lignes utilisées par le commentaire.


Une seule ligne :
Un commentaire est une partie du code source qui n''''est pas exécutée''' par l'interprète. Son utilité est donc exclusivement pour le(s) développeur(s), par exemple pour :
 
* commencer à écrire en '''pseudo-code''' ce que le vrai code va faire par la suite
* '''documenter le code''' pour d'autres personnes ou en tant que future référence
* communiquer un aspect important ou signaler un problème à résoudre
 
Il existe deux manières de commenter le code JavaScript selon le nombre de lignes utilisées par le commentaire. Une seule ligne :


//Si le code est limité à une seule ligne (c'est-à-dire qu'il n'y a pas de retour à la ligne)
<source lang="JavaScript" line="">
//Si le code est limité à une seule ligne (c'est-à-dire qu'il n'y a pas de retour à la ligne)
</source>


Plusieurs lignes :
Plusieurs lignes :


/*
<source lang="JavaScript" line="">
  * Si le code
/*
  * est sur
Si le code
  * plusieurs lignes
est sur
*/
plusieurs lignes
*/
</source>
Pour faciliter le repère de commentaires sur plusieurs lignes, on utilise souvent cette notation :
 
<source lang="JavaScript" line="">
/*
* Si le code
* est sur
* plusieurs lignes
*/
</source>
 
Tout ce qui se trouve dans un commentaire ne sera tout simplement pas pris en compte par l'interprète, donc les commentaires peuvent avoir une fonction descriptive, mais également représenter une manière pour désactiver une partie du code, ce qui peut être utile notamment en phase de test.


===Variables===
===Variables===
Ligne 109 : Ligne 116 :
# Attribuer une valeur avec le symbole d'affectation <code>=</code>
# Attribuer une valeur avec le symbole d'affectation <code>=</code>


Voici quelques examples:
Voici quelques exemples:


var nomDeLaVariable = "Valeur de la variable";
<source lang="JavaScript">
var autreVariable = 'Autre valeur';
var nomDeLaVariable = "Valeur de la variable";
var variableChiffre = 100;
var autreVariable = 'Autre valeur';
var variableDecimal = 3.14;
var variableChiffre = 100;
var variableDecimal = 3.14;
</source>


Le nom des variables doit observer les règles suivantes :
Le nom des variables doit observer les règles suivantes :


* Ne peut pas être un mot réservé par le langage (voir une liste ici : http://www.w3schools.com/js/js_reserved.asp)
* Ne peut pas être un mot réservé par le langage, voir une [http://www.w3schools.com/js/js_reserved.aspliste proposé par le site W3Schools]
* Peut se composer exclusivement de caractères alphanumériques, underscore (_) et signe du dollar ($)
* Peut se composer exclusivement de caractères alphanumériques (mais évitez les accents), underscore (_) et signe du dollar ($)
* Le premier caractère ne peut pas être un chiffre
* Le premier caractère ne peut pas être un chiffre


//Exemple de variables correctes
Exemples de noms '''acceptés''' :
var monWiki123 = "EduTechWiki";
<source lang="JavaScript">
var $monWiki123 = "EduTech Wiki";
//Exemples de variables correctes
var _____monWiki123 = "EduTechWiki";
var monWiki123 = "EduTechWiki";
var $monWiki123 = "EduTech Wiki";
var _____monWiki123 = "EduTechWiki";
</source>


//Exemple de variables non correctes
Exemples de noms '''non acceptés''' :
var 123wiki = "Faux";
 
var aujourd'hui = "Faux";
<source lang="JavaScript">
//Exemples de variables non correctes
var 123wiki = "Faux";
var aujourd'hui = "Faux";
</source>
 
Même si ce n'est pas une règle, il est cependant de bonne pratique d'utiliser seulement des lettres sans accents, pour le nom des variables mais également en général.


Il est possible de déclarer une variable sans lui assigner une valeur. Dans ce cas la variable x sera "undefined" :
Il est possible de déclarer une variable sans lui assigner une valeur. Dans ce cas la variable x sera "undefined" :


var x;
<source lang="JavaScript">
var x;
</source>


Lorsqu'on veut changer la valeur associée à une variable, on réutilise le même mécanisme d'association (ou affectation) '''sans''' l'élément <code>var</code>, qui sert juste pour la déclaration. Par exemple:
Lorsqu'on veut changer la valeur associée à une variable, on réutilise le même mécanisme d'association (ou affectation) '''sans''' l'élément <code>var</code>, qui sert juste pour la déclaration. Par exemple:


//Déclaration de la variable score
<source lang="JavaScript">
var score = 0;
//Déclaration de la variable score
//Modification de la variable avec association à une nouvelle valeur
var score = 0;
score = 100;
//Modification de la variable avec association à une nouvelle valeur
//Modification de la variable avec modification par rapport à la valeur actuelle
score = 100;
score = score + 100; //score -> 200
//Modification de la variable avec modification par rapport à la valeur actuelle
score = score + 100; //score -> 200
</source>
 
La version ES6 de JavaScript (2015) a introduit deux alternatives pour déclarer des "conteneurs" symboliques qui peuvent être utilisés à la place de <code>var</code>. Il s'agit de :
 
* <code>let</code>
* <code>const</code>
 
==== let ====
 
Pour comprendre le fonctionnement de <code>let</code> il faudrait d'abord comprendre le fonctionnement du scope en JavaScript (voir plus bas dans la page). Pour l'instant on peut se limiter à définir <code>let</code> comme une manière de définir une variable seulement dans le bloc de code où elle a été déclarée.
 
La notation est la même que pour <code>var</code> :
 
<source lang="JavaScript">
let myScopeVar = "I am limited to this scope";
let n = 14;
</source>
 
* Voir [https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Instructions/let let sur MDN]
 
==== const ====
 
Parfois on utilise des variables juste pour leur attribuer une valeur qui ne va jamais changer dans la logique de l'application, ce qui représente un contresens avec le mot même de "variable". Dans ce cas, il faudrait plutôt utiliser une constante, avec le mot clé <code>const</code> :
 
<source lang="JavaScript">
const gradeToPass = 4;
const secondsInAnHour = 60 * 60;
</source>
 
Si on essaie de changer la valeur d'une constante, le compiler de JavaScript va donner une erreur :
 
<source lang="JavaScript">
const gradeToPass = 4;
//On peut toujours essayer...
gradeToPass = 3; //--> ERROR!
</source>
 
===Types de données===
On peut associer différentes valeurs à une variable, on parle dans ce cas du '''type de données'''. En JavaScript, les types de données sont divisés en deux groupes :
 
# Les '''primitives''' : String, Number, Boolean, null et undefined
# Les '''objets''' : object, array et function
 
Voici quelques exemples de données primitives (les objets seront illustrés par la suite):
 
* '''String''' : chaîne de caractères
** <code>var a = "Bonjour"</code>
** <code>var b = 'Hello'</code>
** <code>var c = "Il m'a dit \"Bonjour\" quand je l'ai vu";</code>
**: Si vous voulez utiliser des '''"''' à l'intérieur des '''"''' qui encadrent la valeur, il faut utiliser '''\''' pour le mécanisme de ''escape''
** <code>var d = 'Ajourd\'hui';</code>
**: Même principe que pour le "
** <code>var e = "Mais vous pouvez utiliser l'autre forme à l'intérieur sans problèmes";</code>
**: Dans ce cas on peut utiliser ' à l'intérieur de "...". L'inverse s'applique selon le même principe.
** <code>var f = "Pour faire apparaître un \\ il faut en mettre deux";</code>
**: Vue que le \ est le symbole de ''escape'', si vous voulez l'afficher, il faudra en utiliser deux : le premier pour ''escape'' et le deuxième comme contenu.
 
* '''Number''' : chiffres et décimales
** <code>var a = 12</code>
** <code>var b = 3.14</code>
** <code>var c = -12</code>
**: Les chiffres ne doivent pas être encadrés par des "...", si non ils devient des Stirng (voir plus bas)
   
   
On peut associer à une variable différents types de valeurs (texte, chiffres, ...) mais également des fonctions ou des objets (voir plus bas). Dans le premier cas on parle de données primitives, et dans le deuxième d'objets.
* '''Boolean''' : vrai/faux
** <code>var a = true</code>
** <code>var b = false</code>
**: <code>true</code> et <code>false</code> toujours en minuscules et sans utiliser les "..." autour.
 
* '''null''' et '''undefined''' : variables "vides"
 
Il est possible de tester le type d'une variable à travers la notation <code>typeof</code> suivi par la variable (ou valeur) :
 
typeof 3; //--> "number"
typeof "3"; //--> "string"
typeof true; //--> "boolean"
 
Contrairement à d'autres langages de programmation, les variables en JavaScript ne sont pas liées à un type de valeur spécifique. Il est tout à fait possible de définir une variable et lui associer d'abord une valeur de type "string" et par la suite de l'affecter à une valeur de type "number" ou à tout autre type de valeur.  
 
<source lang="JavaScript">
//Le code suivant est tout à fait valide
var a = "Hello"; //--> a is a string
a = 100; //--> a is a number
a = false; //--> a is a boolean
</source>
 
===Operateurs===
Les opérateurs permettent de manipuler des valeurs, notamment de combiner des variables.  
 
<source lang="JavaScript">
//Concaténation de texte
var a = "Hello";
var b = "world!";
console.log(a + " " + b); //Hello world!


Les types de variables acceptés sont :
//Opérateurs mathématiques
var a = 2 + 3; //5
var b = 10 - 5; //5
var c = 2 * 3; //6
var d = 9 / 3; //3
</source>


* String : chaîne des caractères  (e.g. <code>var a = "Bonjour"</code>)
Il existe également une notation contractée qui permet de modifier la valeur de la même variable :
* Number : chiffres et décimales (e.g. <code>var a = 12</code>)
* Boolean : vrai/faux (e.g. <code>var a = true</code>)
* null et undefined


Il existe également de nombreux types d'objets dont les plus utilisés sont :
<source lang="JavaScript">
var a = 5;
a += 5; //--> a est égale à 10 maintenant, équivalent de a = a + 5;
a *= 10; //--> 100, équivalent de a = a * 10;
a -= 20; //--> 80, équivalent de a = a - 20;
a /= 8; //-->10, équivalent de a = a / 8;
</source>


* Object
Les opérateurs logiques NOT (!), AND (&&) et OR (||), ainsi que les opérateurs de comparaison (==, !==, ...) sont expliqués dans la partie plus approfondie sur les structures de contrôle.
* Array
* Function


===Objets===
===Objets littéraux===
Un objet est un élément qui se compose d'une ou plusieurs associations "clé-valeur". On déclare un objet de cette manière :
Un objet littéral (la notion d'objet sera détaillée plus bas) est un élément qui se compose d'une ou plusieurs associations "clé-valeur" (key-value). On déclare un objet littéral de cette manière :
<source lang="JavaScript">
<source lang="JavaScript">
var monObjet = {
var monObjet = {
    clé1: "valeur",
    key1: "value1",
    clé2: "valeur",
    key2: "value2",
    clé3: "valeur"
    key3: "value3"
}
}
</source>
</source>
Exemples:
Exemples:
<source lang="JavaScript">
<source lang="JavaScript">
var agesAmis = {Jean:20, Julie:25, Jan:23, Jolan:27};
var agesAmis = {Jean:20, Julie:25, Jan:23, Jolan:27};
var sexeAmis = {Jean:"homme", Julie:"femme", Jan:"homme", Jolan:"homme"};
var sexeAmis = {Jean:"homme", Julie:"femme", Jan:"homme", Jolan:"homme"};
</source>
</source>
On peut par la suite récupérer le contenu d'un objet à travers la notation monObjet.clé1, monObjet.clé2, etc.  
On peut par la suite récupérer le contenu d'un objet à travers la notation monObjet.clé1, monObjet.clé2, etc.  
Ligne 181 : Ligne 300 :
Ce type de notation peut être utilisé également pour associer une valeur :
Ce type de notation peut être utilisé également pour associer une valeur :
<source lang="JavaScript">
<source lang="JavaScript">
  monObjet.clé1 = "valeur";
  monObjet.key1= "value1";
monObjet.clé2 = "valeur";
</source>
</source>
Dans le langage lui-même sont présents des objets qui disposent de leurs propres associations clés-valeurs. Par exemple lorsqu'on utilise <code>document.write()</code> on accède à la valeur-méthode "write" de l'objet "document". Cette valeur correspond dans ce cas à une fonction qui ajoute du contenu au document. Les valeurs des objets peuvent en effet représenter des valeurs (texte, chiffres) mais également des fonctions ou même d'autres objets.
 
Avec l'exemple précédent :
<source lang="JavaScript">
var agesAmis = {Jean:20, Julie:25, Jan:23, Jolan:27};
agesAmis.Jean = 35;
</source>
 
Lorsqu'on récupère le contenu de la clé agesAmis.Jean, on obtiendra la nouvelle valeur associée :
<source lang="JavaScript">
> agesAmis.Jean
35
</source>
 
Dans le langage lui-même sont déjà présents des objets (i.e. built-in objects) qui disposent de leurs propres associations clés-valeurs. Par exemple lorsqu'on utilise <code>Math.PI</code> on accède à la '''clé "PI"''' de l''''objet "Math"'''. Cette clé correspond à la valeur 3.141592653589793. Math.PI est directement disponible dans le langage sans la nécessité de le définir. Veuillez cependant noter que, à différence des objets créés "manuellement", certains objets built-in n'acceptent pas que leurs propriétés soient modifiables. Voir la section dédiée aux objets en JavaScript pour plus de détails.


===Array===
===Array===
Ligne 190 : Ligne 321 :


<source lang="JavaScript">
<source lang="JavaScript">
var mesCours = ["STIC I", "STIC II", "STIC III", "STIC IV"];
var mesCours = ["STIC I", "STIC II", "STIC III", "STIC IV"];
</source>
</source>


On peut ensuite récupérer un élément en utilisant la syntaxe "[..]". <code>mesCours[0]</code> veut dire que l'on récupère le premier élément du array. Dans la plupart des langages de programmation, on commence à numéroter à partir de 0.
On peut ensuite récupérer un élément en utilisant la syntaxe "[..]". <code>mesCours[0]</code> veut dire que l'on récupère le premier élément du array. Dans la plupart des langages de programmation, on commence à numéroter à partir de 0.
<source lang="JavaScript">
<source lang="JavaScript">
var STIC_I = mesCours[0];
var STIC_I = mesCours[0];
var La_suite = mesCours[1];
var La_suite = mesCours[1];
</source>
</source>
Dans une console, on peut taper:
Dans une console, on peut taper:
Ligne 206 : Ligne 337 :
</source>
</source>


Les arrays peuvent contenir tout type de données, mêmes des objets. Les arrays d'objets sont en effet des éléments très utile pour faire des listes ou pour simuler des bases des données (lignes/colonnes). E.g.:
Les arrays peuvent contenir tout type de données, mêmes des objets. Les arrays d'objets sont en effet des éléments très utiles pour faire des listes ou pour simuler des bases des données (lignes/colonnes). E.g.:


<source lang="JavaScript">
<source lang="JavaScript">
Ligne 225 : Ligne 356 :
</source>
</source>


En utilisant un cycle <code>for</code> on peut ensuite facilement récupérer tous les éléments dans l'array et utiliser les clés des objets pour identifier les valeurs associées :
===Fonctions===
Une fonction est une sorte de processus qui détermine un résultat final et le rend disponible, un schéma d'actions à accomplir. Une fonction est une première organisation du code et souvent on réutilise une fonction plusieurs fois dans le code. JavaScript permet de déclarer ses propres fonctions de cette manière :
 
<source lang="JavaScript">
function nomDeMaFonction() {
    //Processus de la fonction
}
</source>
 
Les fonctions peuvent accepter des arguments, c'est-à-dire des valeurs qui sont passés à la fonction. La fonction peut ensuite utiliser ces valeurs à l'intérieur de sa logique. Si on veut ajouter des arguments à la fonction, il faut les insérer dans les parenthèses et les séparer par des virgules (arg1, arg2, arg3). Par exemple la fonction suivante affiche à la console la valeur de "nom" passé en argument :


<source lang="JavaScript">
<source lang="JavaScript">
for(var i = 0; i < students.length; i++) {
function afficheLeNom(nom) {
  console.log("L'étudiant " + students[i].name + " est actuellement " + students[i].status + ". Contact: " + students[i].email);
  console.log("Hello " + nom);
}
}
</source>


//--> L'étudiant Student 1 est actuellement active. Contact: student1@tecfa.edu
Pour exécuter cette fonction, il faudra donc l'utiliser de la manière suivante :  
//--> L'étudiant Student 2 est actuellement active. Contact: student2@tecfa.edu
 
<source lang="JavaScript">
afficheLeNom("Batman"); //--> Hello Batman
</source>
</source>


===Fonctions===
Il arrive souvent qu'une fonction soit utilisée pour récupérer le résultat d'une computation et pouvoir l'utiliser dans la logique de l'application. On utilise à ce moment <code>return</code>. Voici un exemple qui utilise l'objet <code>Date</code> pour récupérer le temps actuel en heures et minutes :
Une fonction est une sorte de processus qui détermine un résultat final et le rend disponible, un schéma d'actions à accomplir. Ce processus peut être basé sur des informations initiales qui sont passées à la fonction en tant qu'arguments. L'intérêt des fonctions consiste à les réutiliser plusieurs fois.
 
<source lang="JavaScript">
function whatTimeIsIt() {
  var now = new Date();
  var formatDate = now.getHours() + ":" + now.getMinutes();
 
  //Return the result of the computation
  return formatDate;
}


Il existe des fonctions préétablies dans le langage, comme par exemple la fonction <code>alert()</code> qui affiche à l'écran une boîte contenant un message. JavaScript permet de déclarer également ses propres fonctions de cette manière :
var helloWithTime = "Hello there, it's " + whatTimeIsIt();
console.log(helloWithTime); //--> similaire à "Hello there, it's 10:12"
</source>


function nomDeMaFonction() {
===Structures de contrôle===
    //Processus de la fonction
Les structures de contrôle permettent d'exécuter du code si une ou plusieurs conditions s'avèrent vraies. Les conditions sont testées avec les éléments <code>if</code>, <code>else if</code> et <code>else</code>.
}


Si on veut ajouter des arguments à la fonction, il faut les insérer dans les parenthèses et les séparer par des virgules (arg1, arg2, arg3). Par exemple la fonction suivante affiche dans une boîte alert le nom passé dans l'argument :
Utilisation simplement de <code>if</code> :


function afficheLeNom(nom) {
<source lang="JavaScript">
    alert(nom);
if (exp) {
}
  //Execute code ONLY if exp is true
}
</source>


Pour exécuter cette fonction il faudra donc l'utiliser dans le code de notre page web de la manière suivante : <code>afficheLeNom("Batman")</code>.
Utilisation de <code>if... else</code> :


===Operateurs===
<source lang="JavaScript">
Les opérateurs permettent de manipuler des valeurs.
if (exp) {
  //Execute code ONLY if exp is true
} else {
  //Otherwise execute this part of the code
}
</source>
 
Complexifier avec l'ajout d'une <code>else if</code> (on peut en ajouter autant qu'on le souhaite, même si des chaînes trop longues sont difficiles à lire et à maintenir) :


//Concaténation de texte
<source lang="JavaScript">
var a = "Hello";
var b = "world!";
alert(a + " " + b); //Hello world!


//Opérateurs mathématiques
if (exp1) {
var a = 2 + 3; //5
  //Execute code if exp1 is true
var b = 10 - 5; //5
} else if (exp2) {
var c = 2 * 3 //6
  //Execute code if exp2 is true
var d = 9 / 3; //3
} else {
  //Execute code if neither exp1 nor exp2 are true
}
</source>


Les opérateurs logiques AND (&) et OR (|), ainsi que les opérateurs de comparaison (==, !==, ...) sont expliqués dans la partie sur les structures de contrôle.
Les structures de contrôle évaluent des expressions et déterminent si ces expressions sont vraies ou fausses. Pour ce faire, il y a une transformation (ou coercition) de tout type de valeur en valeur booléen. Voici les règles de coercition :


===Structures de contrôle===
* Une expression est '''fausse''' si sa valeur de retour est :
Les cycles conditionnels permettent d'exécuter du code si une ou plusieurs conditions s'avèrent vraies. Les conditions sont testées à l'aide des éléments <code>if</code>, <code>else if</code> et <code>else</code>.  
** false
** 0
** null
** undefined
** NaN (Not a Number)
** "" (empty string)
*:
* Une expression est '''vraie''' dans tous les autres cas, comme par exemple:
** true
** Tout chiffre (positive ou négative) différente de 0
** Toute suite de caractères
** Un objet
** Un array
** ...


Le code suivant exécute un redirect (window.location) à la version du EduTech Wiki correspondante à la langue, et affiche un message si la langue n'est ni français, ni anglais. Ci-dessous on parle français, mais vous pouvez changer...
Le code suivant affiche dans la console l'URL de la version du EduTech Wiki correspondante à la langue, ou affiche un message si la langue n'est ni français, ni anglais. Ci-dessous on parle français, mais vous pouvez changer...


<source lang="JavaScript">
<source lang="JavaScript">
  var lang = "Français" //  par exemple .....
  var lang = "Français" //  par exemple .....
  if(lang == "Français") {
  if(lang == "Français") {
     window.location = "http://edutechwiki.unige.ch/fr/Accueil";
     console.log("http://edutechwiki.unige.ch/fr/Accueil");
  } else if (lang == "Anglais") {
  } else if (lang == "Anglais") {
     window.location = "http://edutechwiki.unige.ch/en/Main_Page";
     console.log("http://edutechwiki.unige.ch/en/Main_Page");
  } else {
  } else {
     alert("EduTech Wiki n'est pas encore disponible dans votre langue!");
     console.log("EduTech Wiki n'est pas encore disponible dans votre langue!");
  }
  }
</source>
</source>


Comme vous pouvez le voir, la variable lang est testée à l'aide de l'opérateur == qui détermine s'il y a correspondance entre la variable et la valeur. Les opérateurs de comparaison sont les suivants :
Comme vous pouvez le voir, la variable lang est testée à l'aide de l'opérateur <code>==</code> qui détermine s'il y a correspondance entre la variable et la valeur. Les opérateurs de comparaison sont les suivants :


* == détermine si les deux éléments sont similaires dans leurs valeurs
* <code>==</code> détermine si les deux éléments sont similaires
* !== détermine si les deux éléments sont différents dans leurs valeurs
* <code>!=</code> détermine si les deux éléments sont différents
* === détermine si les deux éléments sont similaires dans leurs valeurs et types
* <code>></code>, <code>>=</code>, <code><</code>, <code><=</code> déterminent le rapport des éléments en fonction d'une échelle
* !=== détermine si les deux éléments sont différents dans leurs valeurs et types
* >, >=, <, <= déterminent le rapport des éléments en fonction d'une échelle


Parfois il est nécessaire de tester plusieurs conditions à la fois, c'est-à-dire que plus d'une condition doivent s'avérer vraies au sein du même test. Pour ce faire, on utilise les opérateurs logiques :
Exemples :
 
* & ou AND : implique que les deux conditions liées par cet opérateur soient vraies
* | ou OR : implique que au moins une des deux conditions liées par cet opérateur soit vraie
 
Souvent on utilise deux opérateurs du même type (&& ou ||) à l'intérieur de la même relation pour renforcer le lien par rapport à d'autres opérations logiques.  Pour déterminer quel type d'opération logique doit être exécuté avant les autres on peut également utiliser des parenthèses.
 
Voici quelques exemples :


<source lang="JavaScript">
<source lang="JavaScript">
if(mois == "décembre" && jour == 25) {
    alert("C'est Noël");
}


if(jour == "samedi" || jour == "dimanche") {
var cours = "STIC I";
    alert("C'est le weekend!");
var credits = 6;
}
</source>


Lorsque les conditions à tester sont plusieurs, au lieu d'utiliser plusieurs if, else if et else, on peut utiliser le cycle <code>switch</code> :
if(cours == "STIC I") {
<source lang="JavaScript">
  console.log("This is STIC I");
switch( lang ) {
}
    case "Français":
    window.location = "http://edutechwiki.unige.ch/fr/Accueil";
    break;


    case "Anglais":
if (cours != "ERGO I") {
    window.location = "http://edutechwiki.unige.ch/en/Main_Page";
  console.log("This is not ERGO");
    break;
}


    default:
if (credits < 6) {
    alert("EduTech Wiki n'est pas encore disponible dans votre langue!");
  console.log("You don't have all the required credits yet");
}
}
</source>
</source>
Le command break est nécessaire afin d'arrêter l'exécution du code pour la condition.


===Boucles===
===Boucles===
Les boucles sont des éléments qui permettent de répéter un processus pour un nombre de fois établi (cycle for), ou jusqu'à ce que une certaine condition s'avère (cycle while).
Les boucles sont des éléments qui permettent de répéter un processus pour un nombre de fois établi (cycle for), ou jusqu'à ce qu'une certaine condition s'avère (cycle while).


La fonction <code>for</code> nécessite 3 arguments :  
La fonction <code>for</code> nécessite 3 arguments :  
Ligne 340 : Ligne 496 :
Voici un exemple de cycle qui aura lieu 20 fois :
Voici un exemple de cycle qui aura lieu 20 fois :


for(var i = 0; i < 20; i++) {
<source lang="JavaScript">
    //code à exécuter à chaque fois
for(var i = 0; i < 20; i++) {
}
  //code à exécuter à chaque fois
}
</source>
 
La notation <code>i++</code> est un raccourci pour <code>i = i + 1</code>. Si vous voulez incrémenter votre itération avec plus d'une unité à la fois, il faudra utiliser donc la notation complète :
 
<source lang="JavaScript">
for(var i = 0; i < 50; i = i + 10) {
  console.log(i);
}
</source>
 
Depuis son introduction, dans les cycles de type <code>for</code> '''on utilise de préférence <code>let</code> au lieu de <code>var</code> :'''
 
<source lang="JavaScript">
for(let i = 0; i < 10; i++) {
  console.log(i);
}
</source>


Le cycle <code>while</code> évalue une condition et exécute le cycle jusqu'à ce que cette condition soit vraie. Ceci implique implicitement qu'un changement doit s'avérer à l'intérieur du cycle afin que cette condition soit fausse à un certain point, sinon le cycle ne s'arrêterait jamais. Voici le même résultat du cycle for vu plus haut dans le texte, mais avec la notation while :
Le cycle <code>while</code> évalue une condition et exécute le cycle jusqu'à ce que cette condition soit vraie. Ceci implique implicitement qu'un changement doit s'avérer à l'intérieur du cycle afin que cette condition soit fausse à un certain point, sinon le cycle ne s'arrêterait jamais. Voici le même résultat du cycle for vu plus haut dans le texte, mais avec la notation while :


var i = 0;
<source lang="JavaScript">
while (i < 20) {
var i = 0;
    //code à exécuter à chaque fois
while (i < 20) {
    i++;
    //code à exécuter à chaque fois
}  
    i++;
}  
</source>


La notation i++ à la fin du code ajoute une unité à la variable i, de cette manière la condition évaluée dans le cycle while sera fausse après 20 passages, et par conséquent le cycle while s'arrêtera. Il existe également la possibilité d'utiliser le cycle do... while qui contrairement au simple cycle while s'exécute au moins la première fois, même si la condition évaluée est fausse. Par exemple ce code affichera une fois la boîte d'alerte :
La notation i++ à la fin du code ajoute une unité à la variable i, de cette manière la condition évaluée dans le cycle while sera fausse après 20 passages, et par conséquent le cycle while s'arrêtera. Il existe également la possibilité d'utiliser le cycle <code>do... while</code> qui contrairement au simple cycle while s'exécute au moins la première fois, même si la condition évaluée est fausse. Par exemple ce code affichera une fois la boîte d'alerte :


do {
<source lang="JavaScript">
    alert("Une fois seulement");
do {
} while (1 == 2);
    console.log("Une fois seulement");
} while (1 == 2);
</source>


La boucle <code>for ... in</code> permet de boucler sur les propriétés énumérables d'un objet.
La boucle <code>for ... in</code> permet de boucler sur les propriétés énumérables d'un objet.
<source lang="javascript">
<source lang="javascript">
var myObj = {x:20, y:30, nounours:40};  
var myObj = {x:20, y:30, nounours:40};  
for (var chaine in myObj)  
for (var chaine in myObj) {  
{  
     console.log (chaine + "=" + myObj[chaine]);  
     console.log (chaine + "=" + myObj[chaine]);  
}
}
Ligne 376 : Ligne 553 :
La boucle <code>for each ...in </code> (JS 1.6) permettait d'itérer sur les valeurs des propriétés. Elle est replacée par l'instruction <code>for ... of </code> dans la dernière version 6 de ECMAScript). Cette dernière est plus versatile et parcourt tous les objets sur lesquels on peut itérer dans toutes les structures.
La boucle <code>for each ...in </code> (JS 1.6) permettait d'itérer sur les valeurs des propriétés. Elle est replacée par l'instruction <code>for ... of </code> dans la dernière version 6 de ECMAScript). Cette dernière est plus versatile et parcourt tous les objets sur lesquels on peut itérer dans toutes les structures.


==Les fonctions en JavaScript==
==Comprendre JavaScript==
Comme on l'a vu brièvement dans la syntaxe de base, les fonctions sont des ensembles d'instructions qui forment un processus. Toutes les instructions qui se trouvent à l'intérieur de la fonction seront exécutées lorsque la fonction sera utilisée. La "vie" d'une fonction se caractérise par deux phases :


* Une '''phase de définition''' dans laquelle le fonctionnement interne de la fonction est établi (i.e. ce que la fonction est censée faire)
Dans cette section nous proposons un survol des éléments clés qui permettent de comprendre le fonctionnement de JavaScript en tant que langage de programmation. Des éléments théoriques illustrés dans l'[[introduction à la programmation]] seront utilisés en fonction des particularités du langage.
* Une '''phase d'invocation''' (i.e. d'utilisation) de la fonction dans un contexte où son fonctionnement interne est utile à la logique de programmation


Il existe néanmoins la possibilité en JavaScript de combiner les deux phases, dans ce cas on parle de fonction anonyme ou immédiate (voir plus bas dans la section).
{{bloc important | Certains aspects abordés dans cette section son très abstraits et une compréhension immédiate n'est pas possible. }}


===Définition d'une fonction===
Pour une introduction plus souple et ciblée voir {{Goblock | [[Computation_avec_JavaScript#Principe_technique_de_la_computation_avec_JavaScript|Principe technique de la computation avec JavaScript]]}}
Pour définir une fonction il faut la nommer. On peut définir une fonction une seule fois, donc chaque fonction doit avoir un nom unique. La syntaxe pour définir une fonction est la suivante :
=== Le code source ===


function nomDeLaFonction(arguments) {
Grâce aux éléments de la syntaxe de JavaScript illustrés plus haut dans la page, il est possible de composer le code source d'un programme ou d'une application en JavaScript. JavaScript est un langage hybride qui est à la fois compilé et interprété : l'interprète JavaScript compile le code source juste avant son exécution (i.e. ''Just-In-Time Compilation''). Cela signifie que tout le code JavaScript est d'abord lu, du haut vers le bas, et de gauche vers la droite, et compilé pour être ensuite exécuté. Ce mécanisme est assez complexe et pour bien le maîtriser, c'est-à-dire pour ne pas rencontrer des mauvaises surprises lors de l'écriture du code source, il est nécessaire de comprendre quelques principes.
    //Instructions
}


Il existe une syntaxe alternative pour déclarer une fonction à travers une variable:
==== Éléments symboliques et littéraux ====


var maFonction = function(arguments) {
Le code source en JavaScript se compose de deux types d'éléments :
    //Instructions
}


Les deux types de déclarations sont pratiquement équivalent, si ce n'est pour quelques détails très techniques.
* Les éléments '''symboliques''', représentés par les variables, les fonctions, etc.
* Les éléments '''littéraux''', représentés par des valeurs spécifiques associés surtout aux variables


Une fonction accepte pas d'arguments, un ou plusieurs arguments. Les arguments sont des références à des valeurs qui sont externes à la fonction et qui seront utilisées à l'intérieur. Si la fonction nécessite plusieurs arguments, il faudra les séparer par une virgule.
Le code source est un mélange de deux types d'éléments. Voici un exemple :


À l'intérieur d'une fonction on peut utiliser tout le code JavaScript qu'on peut utiliser en dehors. Il faut juste faire attention au "scope" des variables. En effet, les variables que l'on définit à l'extérieur d'une fonction seront disponibles aussi à l'intérieur d'une fonction, mais les variables déclarées à l'intérieur d'une fonction seront disponibles seulement à l'intérieur de la fonction elle-même. Voici un exemple :
var a = 10;
var b = a + 5;
var c = a + 5;


<source lang="JavaScript">
Dans ce simple bout de code, <code>a</code> est un élément symbolique qui est associé à une valeur littérale de type Number (10). Ensuite, b est un autre élément symbolique qui est associé à l'élément symbolique <code>a</code> (10 à ce moment) auquel on ajoute une autre valeur littérale de type Number (5). Enfin, <code>c</code> est un autre élément symbolique qui est affecté de la même manière que <code>b</code>
var dispoPartout = "Je suis disponible aussi dans les fonctions";


function alertMesVariables() {
L'affectation des variables <code>b</code> et <code>c</code> présuppose que l'élément symbolique <code>a</code> existe déjà, ce qui est vrai dans ce cas, car on l'a déclaré et affecté à la valeur littéral 5 dans la première ligne. Si on modifie l'ordre des instructions, par contre, il se passe quelque chose de différent par rapport à ce que l'on pourrait s'attendre :
    var dispoIci = "Je suis disponible seulement dans cette fonction";
    alert(dispoPartout + " " + dispoIci);
}


var executerFonction = alertMesVariables();//boite avec les deux messages affichées
var b = a + 5;
var a = 10;
var c = a + 5;


console.log(dispoPartout); //Le message de la variable dispoPartout sera affiché dans la console
Si on exécute ce bout de code, on peut s’apercevoir qu'on n'obtient pas un message d'erreur qui nous informe que <code>a</code> n'existe pas, mais si on demande quelle est la valeur de <code>b</code>, on obtient <code>NaN</code> (i.e. ''Not a Number''), tandis que si on demande la valeur de <code>c</code> on obtient 15. Cela s'explique par un mécanisme de JavaScript appelé '''''hoisting''''' et qui détermine que la déclaration, mais pas l'affectation (i.e. l'association à une valeur, littéral ou symbolique), d'une variable est remontée aux début du code. Le deuxième bout de code est en réalité compilé de cette manière :
console.log(dispoIci);//La variable dispoIci n'est pas définie --> Erreur dans la console
</source>


===Invocation d'une fonction===
var b; //--> b est undefined
Pour invoquer une fonction, c'est-à-dire exécuter les instructions contenues à l'intérieur de la fonction à un moment donné dans le code, il faut simplement écrire le nom de la fonction et éventuellement passer les arguments nécessaires à son fonctionnement interne.
var a; //--> a est undefined
var c; //--> c est undefined
b = a + 5; //--> undefined + 5 --> NaN
a = 10;
c = a + 5; //--> 15


nomDeMaFonction(arguments);
En d'autres termes, tous les éléments symboliques du code source (ou d'un scope, voir plus bas) sont déclarés au début du code compilé, n'importe à quelle ligne ils ont été définis dans le code source, mais leur affectation est effectuée en respectant l'ordre du code source.


Voici quelques examples de déclaration et invocation:
Pour cette raison, et pour des raisons liées au '''scope''' illustré plus bas, il est de bonne pratique de déclarer et, si possible, affecter toujours les variables en haut du code :  


<source lang="JavaScript">
* en haut du script pour des variables ou constantes qui sont utilisé par tout dans la logique de l'application ;
//Déclaration
* en haut du bloc de code d'une fonction si elles sont utilisées seulement à l'intérieur de celle-ci.
function printCoursName() {
  console.log('STIC I');
}
//Invocation
printCoursName(); //--> STIC I dans la console


//Déclaration
==== Modification de l'état d'une application ====
var printCoursGrade = function() {
  console.log(6);
}
//Invocation
printCoursGrade(); //--> 6 dans la console
</source>


===Retour d'une fonction===
Un autre aspect important dans la programmation est la distinction entre instructions qui modifient ou ne modifient pas l'état d'une application.  
Les instructions d'une fonction sont censées aboutir à un certain résultat qui peut être une action, telle qu'afficher une boîte d'alerte, mais également fournir le résultat d'une manipulation des données dans l'endroit du code où cette fonction a été invoquée. Pour renvoyer un résultat on utilise l'instruction <code>return</code>. Cette fonction détermine que la fonction a exécuté son "rôle" et que le processus à son intérieur est terminé.  


function addition(a, b) {
{{bloc important |
    var total = a + b;
L'état d'une application (en anglais on utilise le terme ''state'') concerne la valeur à un moment données de tout les éléments symboliques disponibles dans l'application.
    return total;
}}
}


Cette fonction renvoie le résultat d'une addition entre les deux arguments de la fonction. On peut utiliser plusieurs notations return dans la même fonction, par exemple dans le cadre d'un cycle conditionnel. On exploite dans ce cas le fait que cette instruction termine l'exécution du code à l'intérieur d'une fonction.
Un exemple d'une instruction qui ne modifie pas l'état de l'application est la suivante :


  function controlerMoyenne(note) {
  5 + 5;
    var message = "Examen réussi";
    if(note >= 4) {
          return message;
    } else {
          message = "Examen échoué";
    }
    alert(message);
}


L'alerte de cette fonction sera déclenchée seulement si la note est inférieure à 4 même si elle se trouve en dehors de la structure de contrôle, parce que si la note est supérieure à 4, le return arrêtera l'exécution de la fonction et donc l'alerte ne sera pas prise en compte.
JavaScript sait interpréter cette instruction et renvoyer le résultat <code>10</code>. Cependant, cette instruction n'a pas d'effet sur l'état de l'application car :


===Fonctions anonymes===
# Il n'existe pas d'éléments symboliques dans l'instruction ;
JavaScript permet de créer des fonctions qui n'ont pas de nom dans la perspective d'une utilisation immédiate et non répétée. Les fonctions anonymes sont souvent utilisées en tant qu'arguments d'autres fonctions (voir également les fonctions de callback plus bas). Par exemple la fonction <code>setTimeout()</code> de l'objet window accepte deux arguments :
# Par conséquent, le résultat de cette instruction n'est pas stocké dans la "mémoire" du programme et n'apporte donc pas aucune différence par rapport à l'état actuel.


# Une fonction à exécuter
Par contre, si on insère des éléments symbolique dans le code, on peut créer des instructions qui modifient l'état de l'application et qui, par conséquent, peuvent entraîner des conséquences dans tous les endroits de l'application qui font référence à ces éléments symbolique :
# Un temps en millisecondes avant que la fonction soit déclenchée


Voici comment une fonction anonyme peut être passée en tant que premier argument :
var result = 5 + 5;


setTimeout(function() { alert("Message après 3 secondes"); }, 3000);
À ce moment nous avons :


Cette notation est équivalente à :
# Déclaré une variable qui s'appelle <code>result</code>, ce qui a comme conséquence de stocker un élément symbolique dans la mémoire du programme ;
# Demandé à JavaScript d’exécuter l'addition 5 + 5 et de stocker le résultat dans l'élément symbolique <code>result</code> que nous avons défini ;


function messageApres3secondes() {
Imaginons que la variable result se réfère au résultat d'un quiz où il faut obtenir au moins 9 points pour passer à l'étape successive. Grâce au changement de l'état de cette variable, on peut imaginer d'autres changements conséquentes comme le changement du niveau de difficulté, l'obtention d'un badge de renforcement, etc.
    alert("Message après 3 secondes");
}
setTimeout(messageApres3secondes, 3000);


===Arguments dans une fonction===
On peut illustrer le concept de modification de l'état avec un exemple plus complexe qui utilise des arrays (i.e. des listes, voir également plus bas). JavaScript met à disposition la méthode <code>sort()</code> qu'on peut utiliser pour trier un array :
Les fonctions de JavaScript acceptent des arguments (i.e. paramètres) qui sont optionnels. Ces arguments sont utilisés à l'intérieur du corpus de la fonction. Il y a deux manières pour récupérer un argument à l'intérieur de la fonction :


# L'argument est spécifié dans la définition de la fonction et à l'intérieur il est utilisé avec le nom de la référence
<source lang="JavaScript">
# L'argument n'est pas spécifié dans la définition et il est récupéré grâce à l'array <code>arguments</code> qui associe un index à partir de 0 à chaque argument passé par référence
var courses = ["STIC I", "ERGO I", "VIP I"];
var firstCoursBeforeSort = courses[0]; //--> "STIC I"
courses.sort();
console.log(courses); //--> ["ERGO I", "STIC I", "VIP I"]
var firstCourseAfterSort = courses[0]; //--> "ERGO I"
</source>


Voici un exemple pour chaque modalité :
La méthode <code>sort()</code> a comme conséquence de modifier l'ordre des éléments, car après son exécution les éléments de l'array <code>courses</code> sont triés par ordre alphabétique.


//1.
Au contraire, la méthode <code>join()</code>, qui permet de faire une concaténation des éléments d'un array, ne change pas l'état de l'array :
function addition(a, b) {
    return a + b;
}
//2.
function addition() {
    return arguments[0] + arguments[1];
}


La deuxième méthode est particulièrement utile si on ne sait pas à l'avance combien d'arguments seront passés à une fonction. Par exemple on peut configurer notre fonction addition() afin qu'elle calcule la somme des arguments indépendamment de leur nombre :
<source lang="JavaScript">
courses.join(); //--> "ERGO I,STIC I,VIP I"
console.log(courses); //--> ["ERGO I", "STIC I", "VIP I"]
</source>


function addition() {
Si on voulait garder trace de la concaténation des éléments, il faudra donc utiliser un autre élément symbolique et l'affecter au résultat de la méthode join :
    var numArgs = arguments.length;
    var total = 0;
    for(var i=0; i < numArgs; i++) {
          total += arguments[i];
    }
    return total;
}
var monTotal = addition(11,23,45,21,97);


===Les fonctions récursives===
<source lang="JavaScript">
var coursesConcatenated = courses.join(); //--> "ERGO I,STIC I,VIP I"
</source>


Il arrive parfois que pour solutionner un problème, le programmeur doive créer une fonction que l'on appelle récursive. Il est possible de programmer une fonction récursive dans presque tous les languages de programmation, donc en Javascript aussi.
=== Le scope ===


Qu'est-ce qu'est une fonction récursive ?
Pour comprendre le fonctionnement de JavaScript il faut comprendre le '''scope'''. Lorsque l'interprète JavaScript rencontre un élément symbolique (e.g. une variable) dans le code source, il faut qu'il sache à quel endroit aller pour récupérer sa valeur actuelle. Exemple :


Il s'agit d'une fonction qui s'appelle elle-même. C'est à dire, dans le corps de la fonction, on fait appelle à cette même fonction. Résoudre un problème par la récursivité est particulièrement adapté lorsque le problème en question peut se découper en "sous problèmes".
<source lang="JavaScript" line="">
var language = "PHP"
//No I changed my mind
language = "HTML5";
console.log(language); //The value must be looked up at line 3, not line 1
//I changed my mind once again
language = "JavaScript";
console.log(language); //The value must be looked up at line 6, not line 3 nor line 1
</source>


Ci-dessous un exemple permettant de calculer une suite de Fibonacci à l'aide d'une fonction récursive :
Dans cet exemple le mécanisme est assez simple parce que toutes ces variables appartiennent au même bloc de code. Mais dès qu'on utilise des éléments qui créent leurs propres blocs de code, les choses sont plus compliquées.
<source lang="JavaScript">
function fibo(n){
  if (n < 2) return n; // cas simple
  return fibo(n-2) + fibo(n-1); // cas complexe - gestion du sous-problème
}
</source>
En principe, une fonction récursive à toujours la même structure. On gère en premier lieu le cas simple qui ne nécessite pas l'appel de la fonction. Ensuite, on gère le ou les sous-problème(s) plus complexe, en appelant la fonction elle-même.


===Les fonctions de callback===
==== Le scope et les fonctions ====


Une fonction de callback est une fonction qui est passée en tant qu'argument d'une autre fonction et qui reçoit de cette fonction un ou plusieurs arguments. De manière sémantique, on peut qualifier une fonction de callback de la manière suivante : lorsque la fonction A a été exécutée et donne le résultat X, exécute la fonction B avec l’argument X. Pour obtenir ce processus, la fonction B est passé en tant qu’argument de la fonction A. Voici le code :
Les variables que l'on définit à l'extérieur d'une fonction seront disponibles aussi à l'intérieur d'une fonction, mais les variables déclarées à l'intérieur d'une fonction seront disponibles seulement à l'intérieur de la fonction elle-même. Voici un exemple :


<source lang="JavaScript">
<source lang="JavaScript">
//Déclaration de la fonction principale (A)
var dispoPartout = "Je suis disponible aussi dans les fonctions";
function A(callback) {
 
  //Produire un résultat X
function logMesVariables() {
  var X = 100;
    var dispoIci = "Je suis disponible seulement dans cette fonction";
  //Invoquer la fonction de callback avec l'argument X en paramètre
    console.log(dispoPartout);
  callback(X);
    console.log(dispoIci);
}
}


//Déclaration de la fonction de callback (B)
logMesVariables(); //--> OK!, affiche les deux messages
function B(X) {
  console.log(X);
}


//Utilisation des deux fonctions A et B (en callback)
console.log(dispoPartout); // OK!, le message de la variable dispoPartout sera affiché dans la console
A(B); //--> 100 à la console
console.log(dispoIci);// ERROR!, la variable dispoIci n'existe pas dans ce scope, elle est limitée à la fonction
</source>
</source>


Dans cet exemple, le recours à une fonction de callback n'est pas très utile, car on pourrait obtenir le même résultat de manière plus simple. Toutefois, cet exemple montre le principe fondamental des fonctions de callback : le fait qu’elles sont exécutées à un moment donné dans l’exécution d’une autre fonction. Pour cette raison, les fonctions de callback sont souvent utilisées lorsqu’on ne peut pas, à l’avance, déterminer à quel moment se termine l’exécution d’une autre fonction. Ce principe est à la base de la programmation asynchrone, car l’exécution du code dépend du déclenchement d’une autre fonction qui est faite de manière décalée. On utilise souvent les fonctions de callback avec les requêtes asynchrones de type « AJAX » qui permettent notamment d’obtenir des informations d’une autre page, à travers une requête http, sans que la page principale soit mise à jour. Dans ce cas, la fonction de callback est utile pour déterminer qu’est-ce qu’il faut faire avec le contenu récupéré de manière asynchrone, lorsqu’il sera disponible. Voici le mécanisme d'une fonction de callback (sans le code AJAX):
L'image suivante montre le même principe de manière plus abstraite :
 
[[Fichier:TutoJS-base scope.png|700px|vignette|néant|Les différentes ''scopes'' selon le "niveau" du code.]]
 
Une chose à laquelle il faut faire attention concerne le fait qu'une fonction JavaScript se "souvient" du scope dans lequel elle a été déclarée, quelque soit le scope dans lequel elle sera utilisée. Un exemple permettra de clarifier ce passage :


<source lang="JavaScript">
<source lang="JavaScript">
function getInfoFromInternet(successCallback, errorCallback) {
//Global scope
   data = //Get some data from another page, e.g. a JSON object
var country = "Switzerland";
   if(data) {
var capital = "Bern";
    successCallback(data);
 
   } else {
function printCountry() {
     errorCallback(error)
   //Function scope
   console.log(country);
}
 
function printCountryAndCapital() {
  //Function scope
  var country = "Italy";
  var capital = "Rome";
 
   function printCapital() {
     console.log(capital);
   }
   }
  printCountry();
  printCapital();
}
}


function successCallback(data) {
printCountryAndCapital();
  //Do something with the data, e.g. populating the DOM
}


function errorCallback(error) {
/**
  //Do something with the error, e.g. pop up an alert
* Output :
}
* Switzerland
* Rome
*/
</source>
</source>


==Objets en JavaScript==
On pourrait s'attendre que ce code donne "Italy" et "Rome", car les deux variables qui se trouvent à l'intérieur de la fonction <code>printCountryAndCapital()</code> ont ces valeurs. La différence concerne où les deux fonctions <code>printCountry()</code> et <code>printCapital()</code> ont été déclarées :
===Définition d'un objet===
 
Comprendre les objets en JavaScript équivaut à comprendre le langage lui-même, car pratiquement tout est un objet en JavaScript : les types de données (String, Number, Array, …) sont des objets, l’élément « document » utilisé pour accéder aux différents éléments d’une page web est un objet, et ainsi de suite. Par conséquent, la définition d’un objet doit forcément être assez générale pour prendre en compte toutes les différentes applications des objets :
* <code>printCountry()</code> a été déclarée dans le scope global et donc lorsqu'elle cherche une variable, elle la cherche dans le global scope où <code>var country = "Switzerland"</code>
* <code>printCapital()</code> a été déclarée à l'intérieur du scope de la fonction printCountryAndCapital(), où <code>var capital = "Rome"</code>
 
Voici une représentation graphique qui explique ce principe :
 
[[Fichier:TutoJS-base scope and closure.png|700px|vignette|néant|JavaScript se "souvient" du scope dans lequel les variables et les fonctions ont été déclarées, ce qui peut provoquer des comportements inattendus si on ne comprend pas le principe.]]
 
==== Le scope et les variables : var vs. let ====


* '''Un objet est un élément qui contient d’autres éléments, même d'autres objets.'''
On peut comprendre le fonctionnement du scope également à travers la différence entre <code>var</code> et <code>let</code> illustrée dans cet exemple :


Les éléments contenus dans un objet peuvent être de deux types :
<source lang="JavaScript">
var everywhere = "I am a var";
let here = "I am a let";


# '''Propriétés''' : c’est l’équivalent des '''variables''' dans un objet, car une propriété n’est qu’une valeur associée à un objet.
console.log(everywhere, here); //--> I am a var & I am a let
# '''Méthodes''' : c’est l’équivalent des '''fonctions''' dans un objet, car une méthode permet d’exécuter une certaine action sur un objet, souvent en relation avec ces propriétés.


Voyons tout de suite un exemple. Vu que pratiquement tout est un objet en JavaScript, prenons une simple suite de caractères (i.e. string).
if (true) {
    var everywhere = "I have changed";
    let here = "I have changed too";
}


var phrase = "Ceci n’est pas un Wiki" ;
console.log(everywhere, here); //--> I have changed & I am a let
</source>


La variable phrase est maintenant un objet de type String, un objet qui fait partie du langage JavaScript de base, et donc les propriétés et les méthodes sont accessibles à tout endroit dans le code. Voici deux exemples :
La différence concerne le fait que var et let ont un effet différent à l'intérieur d'un autre bloc de code, dans ce cas un bloc de type if() :


console.log(phrase.length) ; //22
* var évalue le scope "supérieur" ou se trouve une autre variable avec le même nom et donc remplace sa valeur
console.log(phrase.toUpperCase()) ; //CECI N'EST PAS UN WIKI
* let agit seulement sur le bloc de code dans lequel elle se trouve, et par conséquent crée une deuxième conteneur symbolique qui s'appelle "here", sans aucun lien avec le "here" du scope supérieur


On vient d’utiliser une propriété (i.e. length) et une méthode (i.e. toUpperCase()) associés à un objet de type String. De plus, on vient également d'utiliser la méthode log() de l'objet console pour afficher le contenu dans le navigateur web - tout est un objet! Pour mieux comprendre encore cette idée, on aurait même pu tout simplement utiliser la propriété et la méthode directement avec la suite de caractères, sans utiliser une variable :
===Conversion de type de données===


"Ceci n'est pas un Wiki".length ;
JavaScript est un langage ''non-typé'', c'est-à-dire que chaque variable peut être associée à tout type de donnée. Pour cette raison, il est parfois nécessaire de modifier le type de donnée associé à une variable ou contrôler qu'une variable est associée à un type de donnée spécifique, par exemple être sûr que le score d'un jeu soit bien de type Number. La modification du type de données est surtout utile lorsque certains inputs sont déterminés directement par l'utilisateur, notamment dans le cadre de [[Tutoriel JavaScript côté client|JavaScript côté client]] La modification du type de donnée est appelée '''conversion''' est peut se faire de deux manières :
"Ceci n'est pas un Wiki".toUpperCase() ;


L’accès aux propriétés et méthodes d’un objet se fait normalement à travers une notation « par points ». Vu qu’une propriété est une variable, pour y accéder il faut tout simplement ajouter son nom après l’objet et le point :
# "Manuellement", à travers des fonctions (ou raccourcis) mis à disposition des développeurs par le langage ;
# Automatiquement par l'interprète JavaScript


* <code>Objet.propriété</code>
La manière la plus sûre de faire une conversion est de la déclarer explicitement au niveau du code, cela permet d'éviter des conversions automatiques (voir plus bas) par JavaScript qui peuvent être assez difficiles à comprendre pour des néophytes. La conversion "manuelle" peut se faire de différentes manières, voici de suite quelques exemples :
Au contraire, une méthode étant une fonction, il faut ajouter également les deux parenthèses.
* <code>Objet.méthode()</code>


Cette notation peut être "enchaînée", par exemple la notation suivante permet d'associer à la variable monTexte le contenu d'une balise HTML avec id="mon-id", c’est-à-dire la '''propriété ''innerHTML''''' de l’'''objet ''element''''' récupéré avec la '''méthode ''getElementById(id)''''' de l’'''objet ''document'''''. 
====De String à Number====
var monTexte = document.getElementById("mon-id").innerHTML


JavaScript met à disposition des développeurs trois types d’objets différents :
Une des conversions les plus utiles est celle qui permet de passer d'une donnée de type String à Number. Cela permet d'éviter, par exemple, des comportements de ce type :


# Les '''objets globaux''' du langage de base (i.e. « '''native objects''' ») : il s’agit d’objet constitutifs du langage lui-même et qui sont par conséquent accessibles dans n’importe quel endroit dans le code et indépendamment de l’utilisation de JavaScript côté client ou serveur dans une page web, dans une application mobile, logiciel desktop, etc.
"3" + "9" //--> "39" (String)
# Les '''objets mis à disposition par l’environnement''' : il s’agit d’objets qui dépendent directement de l’endroit dans lequel le code est interprété. La plupart du temps, ceci correspond au navigateur internet de l’utilisateur lui-même, qui met donc à disposition des objets tels que window ou document (voir plus bas dans la page).
# Les '''objets personnalisés''' : il s’agit d’objets que le développeur définit lui-même selon les nécessités particulières à l’application


Une autre manière de différencier les objects concerne la possibilité de les modifier, car certains objects (surtout les objects natifs et certains objets environnementales) sont "read-only", c'est-à-dire qu'il n'est pas possibile de modifier les méthodes et les propriétés d'un objet. Par exemple la propriété PI de l'objet Math contient une approximation du nombre PI. Cette propriété ne peut pas être modifiée, même si on essaie de l'associer à une autre valeur:
On peut forcer le type de donnée en Number avec la fonction <code>Number()</code> :


<source lang="JavaScript">
Number("3") + Number("9") //--> 12 (Number)
//Valeur de base
Math.PI; //--> 3.141592653589793


//Essayer d'associer une autre valeur
Veuillez faire attention à ce que chaque chiffre doit être d'abord converti en Number, sinon on n'obtient pas le résultat attendu :
Math.PI = 2; //--> 2 (cela parrait marcher, mais...)


//Afficher à nouveau la propriété
Number("3" + "9") //--> 39 (Number)
Math.PI; //--> 3.141592653589793 (read-only value)
</source>


Au contraire, la propriété location de l'objet environnemental window du navigateur web, qui détermine l'URL de la fenêtre, peut être modifié, ce qui implique un changement d'URL de la page. E.g.
Un raccourci pour la conversion String -> Number consiste tout simplement à ajouter un + avant la valeur en String :


<source lang="JavaScript">
var a = "10";
window.location = "http://tecfa.unige.ch/"; //--> le navigateur va charger la homepage de TECFA car la propriété est modifiable
var b = "5";
</source>
var c = +a + +b; //--> 15


===Objets globaux (Native Objects)===
D'autres manières pour passer de String à Number sont :
Les objets disponibles dans le langage de base constituent les bases de l’API du langage lui-même, c’est-à-dire les propriétés et les méthodes que le langage considère utile pour définir les algorithmes nécessaires à manipuler les données dans une application. Voici de suite une liste non exhaustive de certains de ces objets (pour la liste complète : consulter par exemple la [https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux documentation Mozilla]).
====String====
L'objet String permet d'exécuter des manipulations sur des chaînes de caractères. Voici un exemple pour la méthode <code>toUpperCase()</code> qui transforme les lettres en majuscules.


var msg = "Bonjour";
* <code>parseInt()</code> qui permet de récupérer un chiffre entier depuis du texte : <code>parseInt("1CHF") //--> 1</code>.
  msg.toUpperCase(); //BONJOUR
* <code>parseFloat()</code> qui permet de récupérer un chiffre décimal : <code>parseFloat("1.457cm"); //--> 1.457</code>


* Voir les [http://www.w3schools.com/jsref/jsref_obj_string.asp références de l'objet String]
Veuillez noter que cette fonction marche seulement si le string commence par un chiffre;


====Number====
====De Number à String====
L'objet Number permet d'exécuter des manipulations sur des nombres. Voici un exemple pour la méthode <code>toFixed()</code> qui transforme un chiffre en caractère avec une précision décimale fixée.
Parfois il est utile de passer d'un Number à un String. Pour une conversion simple, on peut utiliser <code>String()</code> :


  var num = 6.749737898732;
  String(100) //--> "100" (String)
var numPrint = num.toFixed(2); //6.75


* Voir les [http://www.w3schools.com/jsref/jsref_obj_number.asp références de l'objet Number]
Pour des conversions plus complexes (et utiles) il existe des méthodes qui peuvent être ajoutées à travers la notation par points (voir la section consacrée aux Objets plus bas dans cette page) :


====Math====
var longDecimal = 123.456789
L'objet Math permet d'exécuter des manipulations mathématiques sur des chiffres. Voici un exemple pour trouver un nombre aléatoire entre 1 et 100 :
longDecimal.toFixed(1); //--> "123.5"
longDecimal.toFixed(2); //--> "123.46"
longDecimal.toFixed(5); //--> "123.45679"


var randomNumber = Math.floor((Math.random() * 100) + 1);
Veuillez noter que ces méthodes n'affectent pas la valeur originale de la variable, c'est-à-dire que <code>longDecimal</code> sera toujours 123.456789.


* Voir les [http://www.w3schools.com/jsref/jsref_obj_math.asp références de l'objet Math]
====Conversion en valeur Boolean====


====Date====
La conversion en valeur Boolean (i.e. true or false) est normalement faite de manière automatique, surtout dans le cadre des structures de contrôle (voir plus haut). On peut en tout cas forcer la conversion en utilisant <code>Boolean()</code> :
L'objet Date permet d'exécuter des manipulations sur les dates. La gestion des dates n'est pas simple en JavaScript. Par exemple la méthode <code>getMonth()</code> qui identifie le mois de l'année en chiffres ne propose pas les mois de 1 à 12, mais plutôt de 0 à 11. Donc le mois 10 n'est pas octobre comme on pourrait s'imaginer, mais plutôt novembre. Voici un exemple pour obtenir le jour du mois (de 1 à 31) :


  var d = new Date();
  Boolean("STIC I"); //--> true
  var aujourdhui = d.getDate();
  Boolean(0); //--> false


* Voir les [http://www.w3schools.com/jsref/jsref_getdate.asp références de l'objet Date]
Un raccourcis, intéressant plutôt d'un point de vue logique que pratique, permet de transformer toute valeur en Boolean en utilisant la double négation :


===Objets personnalisés===
var s = "STIC I";
JavaScript permet de créer ses propres objets avec les propriétés et méthodes souhaitées. Les propriétés sont représentées par des données, tandis que les méthodes par des fonctions.
var booleanS = !!s; //--> true


====Définition d'un objet====
====Conversion automatique====
La définition d'un objet peut se faire de différentes manières. Les notations suivantes définissent le même objet appelé Cours :
//1.
var Cours = {nom: "STIC I", periode: "Automne", nombreExercices: "8"};
//2.
var Cours = {}; //Aussi var Cours = new Object();
Cours.nom = "STIC I";
Cours.periode: "Automne";
Cours.nombreExercices: "8";


Les noms des propriétés ne doivent pas suivre la notation des variables, mais s'ils ne la suivent pas, il faut les insérer entre guillemets comme les valeurs :
Si aucune instruction n'est donnée pour la conversion de type de données, JavaScript utilise des règles internes qui sont plutôt difficile à comprendre et que nous n'allons pas illustrer dans cette page. La conversion automatique a lieu en particulier dans deux conditions :


var Cours = { nomRespecte: "STIC I", "nom-ne-respecte-pas": "STIC I"}
# Lorsqu'on utilise un opérateur pour associer deux données (ou plus) de types différents
# Lorsqu'on utilise des structures de contrôles qui transforment automatiquement des instructions ou des valeurs en Boolean (voir plus haut)


On peut associer à un objet aussi des méthodes, encore une fois de différentes manières dont le résultat est équivalent :
Voici quelques exemples de conversion automatique du premier type :


  //1.
  "10" + 10; //--> 1010 car le 10 est converti en String "10"
  var Cours = {};
  "10" - 10; //--> 0 car le "10" est converti en Number 10
Cours.nom = "STIC I";
  "2" + true; //--> "2true" car le true est converti en String "true"
  Cours.afficherNom = function () { return "STIC I" };
  2 - true; //--> 1 car true est converti en Number 1
//2.
  "10" * "10"; //--> 100 car les deux String "10" sont d'abord converties en Number 10
function afficherNomDuCours () {
  10 + [2,3]; //--> "102,3" car le Number 10 est converti en String "10" et l'array [2,3] en String "2,3"
    return "STIC I";
  }
var Cours = {};
  Cours.nom = "STIC I";
  Cours.afficherNom = afficherNomDuCours;


====Utilisation des objets====
==Les structures de contrôle==
Une fois définit l'objet, on peut l'utiliser facilement à travers la notation "par points" pour propriétés dont le nom respecte la notation des variables ou les méthodes. Pour les noms des propriétés qui ne respectent pas la nomination des variables, il faudra utiliser la notation "à Array". Voici des exemples :


var Cours = { nomRespecte: "STIC I", "nom-ne-respecte-pas": "STIC I"};
Dans la partie sur la syntaxe, nous avons vu les aspects principaux des structures de contrôle avec un exemple <code>if... else if... else</code>. Dans cette section, nous allons approfondir ces aspects.
Cours.maMethode = function () { console.log("Je suis une méthode de l'objet Cours"); };
var nomDuCours1 = Cours.nomRespecte;
var nomDuCours2 = Cours["nom-ne-respecte-pas"];
var ecrireDansConsole = Cours.maMethode();//Il faut utiliser les parenthèses


====L'élément this dans les Objets====
=== Vrai ou faux pour JavaScript ===
Parfois il est nécessaire d'accéder à d'autres propriétés ou méthodes d'un objet à l'intérieur de l'objet lui-même. Dans ce cas, l'objet est représenté par la notation <code>this</code>. Voici un exemple illustratif :


var Cours = {};
D'abord, nous allons approfondir ce qui est considéré vrai ou faux en JavaScript, notamment en relation avec les types de données et les transformations automatiques qu'on a vu dans la section "Comprendre JavaScript".
Cours.nom = "STIC I";
Cours.afficheLeNom = function () { alert(this.nom) };
var afficher = Cours.afficheLeNom();


====Définir des objects prototypes====
Pour montrer quelques exemples nous allons créer une fonction <code>assert()</code> qui évalue une expression et renvoie à la console un message "I am true" ou "I am false".
Les notations qu’on a vues plus haut pour définir un objet sont utiles pour définir un seul objet de ce type, ce qu’on appelle une « instance » de l’objet. Il est également possible de créer plusieurs instances d’un objet, pour ce faire il faut le définir à travers une fonction « constructrice », qui crée des objets prototypes. Voici un exemple pour créer deux instances d’un objet « Tutoriel » :


<source lang="JavaScript">
<source lang="JavaScript">
function Tutoriel(argument, niveau) {
//Définir la fonction assert
   this.argument = argument;
function assert(exp) {
   this.niveau = niveau;
   //Contrôler si l'expression est vraie (équivaut à exp == true)
   this.printTutorielInfo = function () {
   if(exp) {
     return 'Tutoriel de niveau ' + this.niveau + ' sur ' + this.argument;
    console.log("I am true");
   } else {
     console.log("I am false");
   }
   }
}
}
var tutorielJavaScriptBase = new Tutoriel('JavaScript', 'intermédiare');
var tutorielNodeJs = new Tutoriel('Node.js', 'avancé');


console.log(tutorielJavaScriptBase.printTutorielInfo()); // --> Tutoriel de niveau intermédiare sur JavaScript
//Exemples
console.log(tutorielNodeJs.printTutorielInfo()); // --> Tutoriel de niveau avancé sur Node.js
assert(true); //--> I am true
assert(false); //--> I am false
assert(0.0001); //--> I am true
assert(1 - 1); //--> I am false
assert({ name: "Student 1", email : "student1@tecfa.edu" }); //--> I am true
assert(null); //--> I am false
assert([]); //--> I am true
assert(""); //--> I am false
assert(" "); //--> I am true
assert(8 * "a"); //--> (NaN) I am false
</source>
</source>


L’objet Tutoriel fonction correctement, mais son fonctionnement interne peut être amélioré, car à présent chaque fois qu’on crée une instance de cet objet, le navigateur doit créer trois éléments :
Vous pouvez identifier dans cette liste l'utilisation de la notation <code>'''!'''</code> (NOT) pour définir la négation. Le <code>!</code> peut être utilisé également pour transformer une valeur dans son contraire suivant les règles de conversion booléenne décrites plus haut.
 
!true; //--> false
!false; //-->true
!6; //--> false
!0; //--> true


# La propriété argument
Voici quelques exemples ('''faites attention au fait qu'un chiffre entre guillemets devient une suite de caractères''') :
# La propriété niveau
# La méthode pour récupérer les infos sur le Tutoriel


De ces trois éléments, la méthode est commune à toute instance de l’objet, car elle se limite à fournir les deux propriétés qui différencient les différents tutoriels. Pour éviter que cette méthode soit créée pour chaque instance, on peut exploiter la propriété « prototype » commune à tout objet. Cette propriété permet d’ajouter une propriété ou une méthode communs à toute instance du même objet. Dans le cas du tutoriel, on peut effacer la fonction printTutorielInfo() à l’intérieur de la fonction constructrice, et la déclarer en tant que méthode prototype :
* 6 == 6 //--> true
* 6 == "6" //--> true
* 6 === "6" //--> false
* 6 != "6" //--> false
* 6 !== "6" //--> true
* 6 === !6; //--> false
* 6 !== !6 //--> true
* "a" < "b" //--> true
* "A" < "a" //--> true
* "B" < "a" //--> true
* 1 > "A" //--> false


<source lang="JavaScript">
=== Tester plusieurs conditions à la fois ===
function Tutoriel(argument, niveau) {
Parfois il est nécessaire de tester plusieurs conditions à la fois, c'est-à-dire que plus d'une condition doivent s'avérer vraies au sein du même test. Pour ce faire, on utilise les opérateurs logiques :
  this.argument = argument;
  this.niveau = niveau;
}


Tutoriel.prototype.printTutorielInfo = function () {
* <code>'''&&'''</code> équivaut à ET (AND) : implique que les deux conditions liées par cet opérateur soient vraies
  return 'Tutoriel de niveau ' + this.niveau + ' sur ' + this.argument;
* <code>'''||'''</code> équivaut à OU /OR) : implique qu'au moins une des deux conditions liées par cet opérateur soit vraie
}
var tutorielJavaScriptBase = new Tutoriel('JavaScript', 'intermédiare');
var tutorielNodeJs = new Tutoriel('Node.js', 'avancé');


console.log(tutorielJavaScriptBase.printTutorielInfo()); // --> Tutoriel de niveau intermédiare sur JavaScript
'''Il ne faut pas confondre les opérateurs logiques && et || (double) avec les opérateurs "bitwise" & et | (simple), dont l'utilisation n'est pas illustrée dans cette page.'''
console.log(tutorielNodeJs.printTutorielInfo()); // --> Tutoriel de niveau avancé sur Node.js
</source>


Ce type de programmation à objects peut être très utile par exemple pour les jeux. Voici un exemple incomplet de comment un object "Monster" pourrait se présenter. D'abord, on définit la fonction constructrice qui accepte trois paramètres: (1) le type de monstre, (2) sa position X, et (3) sa position Y:
Voici quelques exemples :


<source lang="JavaScript">
<source lang="JavaScript">
//Définir la fonction constructrice des Monstres, avec les éléments particuliers à chaque instance.
if(mois == "décembre" && jour == 25) {
function Monster(name, x, y) {
    console.log("C'est Noël");
  this.name = name;
}
  this.x = x;
 
  this.y = y;
if(jour == "samedi" || jour == "dimanche") {
}
    console.log("C'est le weekend!");
}
</source>
</source>


Ensuite, on définit les propriétés et les méthodes communes à toute instance qui permettent de faire bouger le monstre et de le tuer. On crée également une fonction qui fourni des informations sur l'état du monstre à un certain moments dans le jeu:
=== Utiliser switch ===


<source lang="JavaScript">
Lorsque les conditions à tester sont plusieurs, au lieu d'utiliser plusieurs if, else if et else, on peut utiliser le cycle <code>switch</code> :
//Définir les propriétés et les méthodes communes à toute instance d'un monstre.
Monster.prototype.health = 100;
Monster.prototype.isAlive = true;
Monster.prototype.isHit = function (damage) {
  this.health -= damage;
  if(this.health <= 0) {
    this.isAlive = false;
  }
}
Monster.prototype.moveUp = function () {
  this.y += 10;
}
Monster.prototype.moveDown = function () {
  this.y -= 10;
}
Monster.prototype.moveRight = function () {
  this.x += 10;
}
Monster.prototype.moveLeft = function () {
  this.x -= 10;
}
Monster.prototype.printInfo = function () {
  if(!this.isAlive) {
    return "Le " + this.name + " a été tué!";
  }
  return "Le " + this.name + " se trouve aux coordonnées [" + this.x + ":" + this.y + "] et il lui manque " + this.health + " avant de disparaître.";
}
</source>


Maintenant on peut simuler le jeu en créant deux monstres:
<source lang="JavaScript">
<source lang="JavaScript">
//Simulation du jeu avec deux monstres, un Dragon et un Goblin.
switch( lang ) {
var firstMonster = new Monster('Dragon', 0, 0);
    case "Français":
firstMonster.moveLeft();
    console.log("http://edutechwiki.unige.ch/fr/Accueil");
firstMonster.moveUp();
    break;
firstMonster.isHit(50);
console.log(firstMonster.printInfo()); // --> Le Dragon se trouve aux coordonnées [-10:10] et il lui manque 50 avant de disparaître.


var secondMonster = new Monster('Goblin', 25, -15);
    case "Anglais":
secondMonster.moveDown();
    console.log("http://edutechwiki.unige.ch/en/Main_Page");
secondMonster.isHit(5);
    break;
console.log(secondMonster.printInfo()); // --> Le Goblin se trouve aux coordonnées [25:-25] et il lui manque 95 avant de disparaître.


firstMonster.moveUp();
    default:
firstMonster.moveLeft();
    console.log("EduTech Wiki n'est pas encore disponible dans votre langue!");
firstMonster.isHit(60);
}
console.log(firstMonster.printInfo()); // --> Le Dragon a été tué!
</source>
</source>


==JavaScript et le navigateur web==
Le command <code>break</code> est nécessaire afin d'arrêter l'exécution du code pour la condition.


L'avantage de JavaScript côté client consiste dans le fait que les navigateurs web disposent d'un "moteur" qui permet d'évaluer le code JavaScript et l'exécuter à chaque fois qu'une page web, contenant du code JavaScript, est téléchargée par l'utilisateur. Ceci est possible surtout grâce à deux phénomènes :
==Les fonctions en JavaScript==
Comme on l'a vu brièvement dans la syntaxe de base, les fonctions sont des ensembles d'instructions qui forment un processus. Toutes les instructions qui se trouvent à l'intérieur de la fonction seront exécutées lorsque la fonction sera utilisée. La "vie" d'une fonction se caractérise par deux phases :


# '''L'inclusion de code JavaScript dans des pages HTML''' ;
* Une '''phase de définition''' dans laquelle le fonctionnement interne de la fonction est établi (i.e. ce que la fonction est censée faire)
# '''L'existance d'un objet global <code>window</code> qui permet à JavaScript d'interagir avec le navigateur web.'''
* Une '''phase d'invocation''' (i.e. d'utilisation) de la fonction dans un contexte où son fonctionnement interne est utile à la logique de programmation


===Utilisation du code JavaScript dans une page HTML===
Il existe néanmoins la possibilité en JavaScript de combiner les deux phases, dans ce cas on parle de fonction anonyme ou immédiate (voir plus bas dans la section).
Il existe trois manières différentes d'utiliser du code JavaScript dans une page web :


# '''Fichier externe''' : le code est écrit dans un fichier avec extension .js
===Définition d'une fonction===
# '''Code "inline"''' : le code est écrit directement dans la page web elle-même
Pour définir une fonction il faut la nommer. On peut définir une fonction une seule fois, donc chaque fonction doit avoir un nom unique. La syntaxe pour définir une fonction est la suivante :
# '''Attribut des balises (déconseillé)''' : le code est écrit dans des attributs des balises des éléments HTML de la page. Cette option, utilisée souvent dans le passé, est aujourd'hui fortement déconseillée et ne sera par conséquent pas illustrée dans ce tutoriel.


Les trois différents manières peuvent être utilisées en même temps, il n'est pas nécessaire de choisir une seule manière pour toute la page.
<source lang="JavaScript">
function nomDeLaFonction([arguments optionnels]) {
    //Instructions
}
</source>
Il existe une syntaxe alternative pour déclarer une fonction à travers une variable:


====Fichier externe====
<source lang="JavaScript">
Dans le cas d'utilisation d'un fichier externe, ce fichier doit être créé avec l'extension .js. Dans ce fichier doit être contenu seulement du code JavaScript. Le code peut commencer dès la première ligne, il ne faut pas déclarer le type de fichier par exemple à travers une balise XML.
var maFonction = function([arguments optionnels]) {
  //Instructions
}
</source>


Pour rendre disponible le code d'un fichier externe dans une page web, il faut inclure le lien au fichier dans la balise HTML <code>script</code> et plus précisément à travers l'attribut '''src'''. Voici un exemple :
Les deux types de déclarations sont pratiquement équivalent, si ce n'est pour quelques détails très techniques.  


<script src="dossier/fichier.js"></script>
Une fonction accepte entre zéro et plusieurs arguments. Les arguments sont des références à des valeurs externes passées à la fonction pour être utilisées à l'intérieur. Si la fonction nécessite plusieurs arguments, il faudra les séparer par une virgule.


Veuillez noter que la balise <code>script</code> doit être fermée avec la balise de clôture même si à l'intérieur d'une balise avec attribut src il ne faut pas insérer de code.  
===Invocation d'une fonction===
Pour invoquer une fonction, c'est-à-dire exécuter les instructions contenues à l'intérieur de la fonction à un moment donné dans le code, il faut simplement écrire le nom de la fonction et éventuellement passer les arguments nécessaires à son fonctionnement interne.  


Le lien au fichier .js peut être relative ou absolu. Le mauvais pointage d'un fichier externe est une des raisons les plus communes d'erreur dans le code JavaScript et il est par conséquent la première chose à contrôler en cas de problèmes.
<source lang="JavaScript">
nomDeMaFonction([arguments optionnels]);
</source>


On utilise des fichiers externes souvent dans ces conditions :
Voici quelques exemples de déclaration et invocation:


* Le même fichier contient du code qui est utilisé dans plusieurs pages d'un site, ce qui évite la nécessité de l'écrire dans toutes les pages. De cette manière, une modification au code doit se faire à un seul endroit et sera automatiquement activé dans toutes les pages.
<source lang="JavaScript">
* Le fichier est une bibliothèque JavaScript
//Déclaration
* Il y a beaucoup de code écrit
function printCoursName() {
  console.log('STIC I');
}
//Invocation
printCoursName(); //--> STIC I dans la console


====Code inline====
//Déclaration
Une autre manière très utilisée d'inclure du code JavaScript consiste à écrire le code directement à l'intérieur de la balise <code>script</code>. Dans ce cas, il ne faut pas déclarer l'attribut src. Voici un exemple :
var printCoursGrade = function() {
  console.log(6);
}
//Invocation
printCoursGrade(); //--> 6 dans la console
</source>


<script>
alert("Bonjour!");
</script>


La balise script peut contenir seulement du code JavaScript. Dans des exemples sur le web vous pouvez parfois trouver des balises script qui présentent aussi l'attribut type="text/javascript". Cet attribut n'est plus nécessaire car tout navigateur considère automatiquement le code inséré dans cette balise comme du code JavaScript.
===Arguments dans une fonction===
Les fonctions de JavaScript acceptent des arguments (i.e. paramètres) qui sont optionnels. Ces arguments sont utilisés à l'intérieur du corpus de la fonction. Il y a deux manières pour récupérer un argument à l'intérieur de la fonction :


On utilise du code "inline" souvent dans ces conditions :
# L'argument est spécifié dans la définition de la fonction et à l'intérieur il est utilisé avec le nom de la référence
# L'argument n'est pas spécifié dans la définition et il est récupéré grâce à l'array <code>arguments</code> qui associe un index à partir de 0 à chaque argument passé par référence


* Le code doit être exécuté précisément à cet endroit dans la page, par exemple parce qu'il ajoute du texte ou des éléments HTML.
Voici un exemple pour chaque modalité :
* Le code est spécifique à une seule page du site est le code n'a pas de probabilité d'être utilisé ailleurs
* Le code est court
* Le code sert à configurer des options ou initialiser une bibliothèque JavaScript


====Placement de la balise script====
<source lang="JavaScript">
Un élément auquel il faut faire attention est le placement de la balise <code>script</code> dans la page HTML. Il faut en effet tenir compte de la manière progressive de charger une page des navigateurs web. Avec le code JavaScript on fait souvent référence à des éléments du DOM (i.e. des balises HTML contenu dans la page). Il faut faire attention dans ces cas à ce que cet élément soit déjà disponible au navigateur. Un exemple illustre cette problématique....
//1.
function additionWithArguments(a, b) {
    console.log(a + b);
}
//2.
function additionWithoutArguments() {
    console.log(arguments[0] + arguments[1]);
}


Nous allons récupérer le texte d'un paragraphe avec id="mon-texte" avec la fonction <code>document.getElementById("mon-texte").innerHTML</code> ; et ensuite nous utiliserons la fonction <code>document.write()</code> pour écrire ce contenu. En d'autres termes, le comportement attendu de la page est d'obtenir deux fois exactement le même texte.  Les deux exemples du code suivant sont exactement les mêmes, mais dans un cas, la balise <code>script</code> est positionnée avant le paragraphe, et dans l'autre cas après.
//L'invocation est similaire pour les deux cas
additionWithArguments(5, 5); //--> 10
additionWithoutArguments(10, 10); //--> 20
</source>


<syntaxhighlight lang="HTML5">
La deuxième méthode est particulièrement utile si on ne sait pas à l'avance combien d'arguments seront passés à une fonction. Par exemple on peut configurer notre fonction addition() afin qu'elle calcule la somme des arguments indépendamment de leur nombre :
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Untitled Document</title>
</head>
<body>
<script>
var texte = document.getElementById("mon-texte").innerHTML;
document.write(texte);
</script>
<p id="mon-texte">Bonjour!</p>


</body>
<source lang="JavaScript">
</html>
function addition() {
</syntaxhighlight>
    var numArgs = arguments.length;
    var total = 0;
    for(var i=0; i < numArgs; i++) {
          total += arguments[i];
    }
    console.log(total);
}
addition(11,23,45,21,97); //--> 197
</source>


Si le code est avant le paragraphe, le script n'a pas accès à l'élément du DOM qui correspond au paragraphe. Donc aucun texte ne sera écrit par la fonction <code>write()</code>.  
===Retour d'une fonction===
Les instructions d'une fonction sont censées aboutir à un certain résultat qui peut être une action, par exemple afficher un message à la console, mais également fournir le résultat d'une manipulation des données dans l'endroit du code où cette fonction a été invoquée. Pour renvoyer un résultat on utilise l'instruction <code>return</code>. Cette instruction détermine que la fonction a exécuté son "rôle" et que le processus à son intérieur est terminé.  


<source lang="HTML5">
<source lang="JavaScript">
<!doctype html>
function addition(a, b) {
<html>
    var total = a + b;
<head>
    return total;
    <meta charset="UTF-8">
}
    <title>Untitled Document</title>
</head>
<body>
<p id="mon-texte">Bonjour!</p>
<script>
var texte = document.getElementById("mon-texte").innerHTML;
document.write(texte);
</script>
</body>
</html>
</source>
</source>


Au contraire, si le code est placé après le paragraphe, son contenu sera réécrit par le script et apparaîtra donc à l'écran.  
Cette fonction renvoie le résultat d'une addition entre les deux arguments de la fonction. On peut utiliser plusieurs notations return dans la même fonction, par exemple dans le cadre d'un cycle conditionnel. On exploite dans ce cas le fait que cette instruction termine l'exécution du code à l'intérieur d'une fonction.  


Même s'il existe des fonctions pour déclencher le code seulement une fois que toute la structure du DOM a été chargée dans le navigateur (e.g. window.onload), il est une bonne pratique d'inclure les balises <code>script</code> juste avant la balise de clôture <code>/body</code> :
<source lang="JavaScript">
function controlerMoyenne(note) {
    if(note < 4) {
          return;
    }
    console.log("Yeah!!");
}
controlerMoyenne(4.5); //--> Yeah!! s'affiche
controlerMoyenne(3.75); //--> Pas de Yeah!!
</source>


<source lang="HTML5">
Le "return" d'une fonction est généralement utilisé pour que la valeur renvoyée soit intégrée dans la logique de l'application, par exemple en tant qu'affectation d'une variable :
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Untitled Document</title>
</head>
<body>


<script>
<source lang="JavaScript">
//Mon code est mieux ici!
//Définition d'une fonction d'addition
</script>
function addition(a, b) {
</body>
    var total = a + b;
</html>
    return total;
</source>
}


===L'objet global window===
var totalPointsUser = addition(addition(23, 25), addition(21, 30));
JavaScript dépend de l'environnement dans lequel il est exécuté à la fois pour afficher les résultats des expressions (i.e. le output), mais également pour recevoir des inputs. Dans JavaScript côté client, cet environnement est représenté par le navigateur web et la communication I/O entre JavaScript et le navigateur web se fait à travers l'objet global <code>window</code>. Plus concrètement cela signifie que :
var totalPointsComputer = addition(addition(27, 20), addition(25, 25));


# JavaScript peut "intercepter" tous les événements qui concerne la fenêtre du navigateur comme par exemple les clicks, les changements d'URL, le scolling de la page, etc.
//Guess who won ;)
# JavaScript peut modifier certaines propriétés de la fenêtre, y compris son contenu.
if(totalPointsUser > totalPointsComputer) {
  console.log("You won!");
}
</source>


Les deux opérations sont possible justement grâce à l'objet global <code>window</code> qui, en tant qu'objet, possède des propriétés et des méthodes. Comprendre l'objet global window peut contribuer à bien comprendre le langage, car en réalité tout le code source écrit en JavaScript côté client peut se diviser en deux catégories :
===Les fonctions récursives===


# Le code qui exploite les propriétés et méthodes mises à disposition par l'objet window
Il arrive parfois que pour solutionner un problème, le programmeur doive créer une fonction que l'on appelle récursive. Il est possible de programmer une fonction récursive dans presque tous les langages de programmation, donc en Javascript aussi.  
# Le code qui ajoute des propriétés (e.g. des variables) ou des méthodes (e.g. des fonctions) à l'objet global window


En effet, lorsqu'on déclare une variable, ce que nous sommes en train de faire c'est tout simplement d'ajouter une propriété avec le nom de la variable à l'objet global window. En d'autres termes, les deux lignes de code suivantes sont équivalentes :
Qu'est-ce qu'est une fonction récursive ?


var cours = "STIC I";
Il s'agit d'une fonction qui s'appelle elle-même. C'est à dire, dans le corps de la fonction, on fait appel à cette même fonction. Résoudre un problème par la récursivité est particulièrement adapté lorsque le problème en question peut se découper en "sous problèmes".
window.cours = "STIC I";


Le même principe s'applique aux fonctions :
Ci-dessous un exemple permettant de calculer une suite de Fibonacci à l'aide d'une fonction récursive :
 
<source lang="JavaScript">
function addTwo(x) {
function fibo(n){
  return x + 2;
  if (n < 2) return n; // cas simple
  return fibo(n-2) + fibo(n-1); // cas complexe - gestion du sous-problème
  }
  }
addTwo(4); // -> 6
</source>
window.addTwo(7); --> 9
En principe, une fonction récursive à toujours la même structure. On gère en premier lieu le cas simple qui ne nécessite pas l'appel de la fonction. Ensuite, on gère le ou les sous-problème(s) plus complexe, en appelant la fonction elle-même.


En raison du fait que tout appartient à l'objet window, on peut éviter de le déclarer à chaque fois. Le même principe s'applique aux propriétés et méthodes déjà disponibles. Par example la fonction <code>alert()</code> - qui affiche une boîte popup avec un message - est en réalité la méthode <code>window.alert()</code>.
===Les fonctions de callback===


De suite une liste non exhaustive des propriétés et méthodes déjà disponible avec l'objet window, pour une liste exhaustive voir la [http://www.w3schools.com/jsref/obj_window.asp référence de l'objet Window sur W3Schools].
Une fonction de callback est une fonction qui est passée en tant qu'argument d'une autre fonction et qui reçoit de cette fonction un ou plusieurs arguments. De manière sémantique, on peut qualifier une fonction de callback de la manière suivante : lorsque la fonction A a été exécutée et donne le résultat X, exécute la fonction B avec l’argument X. Pour obtenir ce processus, la fonction B est passé en tant qu’argument de la fonction A. Voici le code :


=== Les boîtes popup de JavaScript ===
<source lang="JavaScript">
Pour le débutant, créer quelques simples boîtes popup permet se lancer dans la programmation. On peut par exemple poser une question à un utilisateur et ensuite la traiter, puis afficher le résultat.
//Déclaration de la fonction principale (A)
function A(callback) {
  //Produire un résultat X
  var X = 100;
  //Invoquer la fonction de callback avec l'argument X en paramètre
  callback(X);
}


JavaScript possède 3 sortes de boîtes popup :
//Déclaration de la fonction de callback (B)
function B(X) {
  console.log(X);
}


# Les boîtes d'alerte
//Utilisation des deux fonctions A et B (en callback)
# Les boîtes de confirmation
A(B); //--> 100 à la console
# Les fenêtres de saisies.
</source>


Vous pouvez structurer votre message dans vos boites en insérant '\n' à la fin de vos phrases. Cela permettra de revenir à la ligne.
On peut imaginer d'ajouter une troisième fonction C(X) à cet exemple pour montrer une autre fonction de callback :


alert ('Première ligne.\n Deuxième ligne.')
<source lang="JavaScript">
//Déclaration de la fonction principale (A)
function A(callback) {
  //Produire un résultat X
  var X = 100;
  //Invoquer la fonction de callback avec l'argument X en paramètre
  callback(X);
}


[[Fichier:Alert.jpg|thumb|right|300px]]
//Déclaration de la fonction de callback (B)
function B(X) {
  console.log(X);
}


==== Les boites d'alerte ====
//Déclaration de la fonction de callback (C)
function C(X) {
Elles affichent un message. Elles servent généralement à donner un message à un utilisateur ou à indiquer un message d'erreur. La boîte d'alerte contient un bouton 'Ok'.
  console.log(X + 100);
}


Il faut utiliser la fonction <code>alert()</code>, c'est-à-dire l'équivalent de <code>window.alert()</code>
//Utilisation des deux fonctions A et B (en callback)
 
A(B); //--> 100 à la console
<source lang="JavaScript">
A(C); //--> 200 à la console
<html>
    <head>
        <script type="text/javascript">
            function gagné()
            {
                alert("Bravo vous avez trouvé");
            }
        </script>
    </head>
    <body>
        <input type="button" onclick="gagné()" value="Trouver">
    </body>
</html>
</source>
</source>


[[Fichier:Confirm.jpg||thumb|right|300px|centré]]
Dans cet exemple, le recours à une fonction de callback n'est pas très utile, car on pourrait obtenir le même résultat de manière plus simple. Toutefois, cet exemple montre le principe fondamental des fonctions de callback : le fait qu’elles sont exécutées à un moment donné dans l’exécution d’une autre fonction. Pour cette raison, les fonctions de callback sont souvent utilisées lorsqu’on ne peut pas, à l’avance, déterminer à quel moment se termine l’exécution d’une autre fonction. Ce principe est à la base de la programmation asynchrone, car l’exécution du code dépend du déclenchement d’une autre fonction qui est faite de manière décalée. On utilise souvent les fonctions de callback avec les requêtes asynchrones de type « [[AJAX]] » qui permettent notamment d’obtenir des informations d’une autre page, à travers une requête http, sans que la page principale soit mise à jour. Dans ce cas, la fonction de callback est utile pour déterminer qu’est-ce qu’il faut faire avec le contenu récupéré de manière asynchrone, lorsqu’il sera disponible. Voici le mécanisme d'une fonction de callback (sans le code AJAX):


====Les boîtes de confirmation====
<source lang="JavaScript">
//Déclaration de la fonction principale
function getInfoFromInternet(successCallback, errorCallback) {
  data = //Get some data from another page, e.g. a JSON object
  if(data) {
    successCallback(data);
  } else {
    errorCallback(error)
  }
}


La fonction <code>confirm()</code> affiche une boite de confirmation. L'utilisateur a alors le choix entre 'OK' et 'annuler'.
//Définition de deux fonctions qui sont utilisées en callback
function populateDOM(data) {
  //Do something with the data, e.g. populating the DOM
}


<source lang="JavaScript">
function showError(error) {
<html>
  //Do something with the error, e.g. pop up an alert
    <head>
}
        <script type="text/javascript">
            function confirmer()
            {
                var reponse=confirm("Continuer l'operation en cours ?");
                if (reponse==true)
                {
                    alert("Vous avez cliqué sur OK");
                }
                else
                {
                    alert("Vous avez cliqué sur Annuler");
                }
            }
        </script>
    </head>
    <body>
        <input type="button" onclick="confirmer()" value="Choix" />
    </body>
</html>


//Invocation de la fonction principale avec callbacks
getInfoFromInternet(populateDOM, showError);
</source>
</source>


====Les fenêtres de saisie====
===Fonctions à exécution immédiate (IIFE)===
Un dernier type de fonction que vous pouvez rencontrer dans du code JavaScript concerne les fonctions à exécution immédiate, ou ''Immediately-invoked function expression'' (IIEF). Comme le nom l'indique, il s'agit de fonctions qui sont exécutées directement lorsqu'elles sont déclarées. On utilise souvent cette notation pour éviter des conflits de scope (voir plus haut), car toutes les variables et fonctions déclarées à l'intérieur d'une IIFE sont limitées au scope de la fonction.


Il est possible de créer une fenêtre pour saisir une valeur grâce à la fonction <code>prompt()</code>. La fonction prend deux paramètres : le premier est l'invitation à saisir du texte et le second propose un texte par défaut.
Il y a différentes manières pour écrire une IIFE (voir par exemple la page sur [https://en.wikipedia.org/wiki/Immediately-invoked_function_expression les IIFE sur Wikipedia]). Voici l'une des plus utilisées:
 
Après avoir entré une valeur, l'utilisateur peut cliquer sur 'ok' ou sur 'annuler.  
 
'''Exemple''' : ici quand l'utilisateur clic sur 'Ok' la valeur saisie est indiqué dans la fenêtre d'alerte ensuite.


<source lang="JavaScript">
<source lang="JavaScript">
<html>
(function () {
    <head>
    //Contenu de la IIFE
        <script type="text/javascript">
    console.log("Immediate")}
            function saisir()
)();
            {
                var reponse=prompt("Identification, veuillez saisir votre prenom","mon prenom");
                //si la réponse est non nul ou vide - donc l'utilisateur a appuyé sur ok
                if (reponse!=null && reponse!="")
                {
                    alert("Votre prenom est :"+reponse);
                }  
                //autre cas : si l'utilisateur clic sur 'Annuler'
                else {
                    alert("Operation interrompue")
                }
            }
        </script>
    </head>
    <body>
        <input type="button" onclick="saisir()" value="Saisir mon prenom" />
    </body>
</html>
</source>
</source>
[[Fichier:Prompt.jpeg|400px|centré]]
[[Fichier:Prompt2.jpeg|400px|centré]]


===Les fonctions liées au temps===
===Les fonctions liées au temps===


Grâce à l'objet global window il est possibile d'exécuter du code en fonction du temps, plus spécifiquement :
JavaScript permet également d'exécuter du code en fonction du temps, plus spécifiquement grâce aux fonctions :


* <code>setTimeout()</code> permet d'exécuter du code une seule fois après une période de temps définie ;
* <code>setTimeout()</code> permet d'exécuter du code une seule fois après une période de temps définie ;
Ligne 1 071 : Ligne 1 182 :
  setTimeout(function,milliseconds, [param1,param2,...]);
  setTimeout(function,milliseconds, [param1,param2,...]);


Les paramètres sont optionnels, tandis que la fonction à exécuter et le temps en milliseconds sont obligatoires. Voici un example qui affiche une boite d'alerte après 5 seconds (i.e. 5 * 1000 milliseconds) :
Les paramètres sont optionnels, tandis que la fonction à exécuter et le temps en millisecondes sont obligatoires. Voici un exemple qui affiche un message dans la console après 5 secondes (i.e. 5 * 1000 milliseconds) :


  var afficherApres5seconds = setTimeout(function () { alert("Message"); }, 5000);
  var afficherApres5seconds = setTimeout(function () {  
  console.log("Message");  
}, 5000);


Il est également possibile de définir d'abord une fonction et ensuite passer son nom comme référence dans la fonction setTimeout() :
Il est également possible de définir d'abord une fonction et ensuite passer son nom comme référence dans la fonction setTimeout() :


  function alertMessage() {
  function printMessage() {
   alert("Message");
   console.log("Message");
  }
  }
  var afficherApres5seconds = setTimeout(alertMessage, 5000);
  var afficherApres5seconds = setTimeout(printMessage, 5000);


Associer la fonction setTimeout() à une variable est utile si on veut annuler l'exécution de la fonction avant que la période de temps définie avec la notation :
Associer la fonction setTimeout() à une variable est utile si on veut annuler l'exécution de la fonction avant que la période de temps définie avec la notation :
Ligne 1 088 : Ligne 1 201 :
En ajoutant cette ligne de code à l'exemple précédent, la fonction alertMessage() ne sera pas déclenchée :
En ajoutant cette ligne de code à l'exemple précédent, la fonction alertMessage() ne sera pas déclenchée :


  function alertMessage() {
  function printMessage() {
   alert("Message");
   console.log("Message");
  }
  }
  var afficherApres5seconds = setTimeout(alertMessage, 5000);
  var afficherApres5seconds = setTimeout(printMessage, 5000);
  clearTimeout(afficherApres5seconds);
  clearTimeout(afficherApres5seconds);


====setInterval()====
====setInterval()====
La fonction <code>setInterval</code> est similaire à setTimeout() si ce n'est pour le fait que le code sera exécutée chaque X milliseconds. La syntaxe reste par contre la même :
La fonction <code>setInterval</code> est similaire à setTimeout() si ce n'est pour le fait que le code sera exécuté chaque X millisecondes. La syntaxe reste par contre la même :


  setInterval(function,milliseconds, [param1,param2,...]);
  setInterval(function,milliseconds, [param1,param2,...]);


Voici un exemple qui affiche dans la console un message chaque 3 seconds (sans arrêt si la page ne sera pas fermée ou après changement de URL) :
Voici un exemple qui affiche dans la console un message chaque 3 secondes (sans arrêt si la page ne sera pas fermée ou après changement de URL) :


  var chaque3seconds = setInterval(function () { console.log("...encore 3 seconds"); }, 3000);
  var chaque3seconds = setInterval(function () {  
  console.log("...encore 3 seconds");  
}, 3000);


Pour limiter les cycles on peut utiliser un conteur et utiliser la fonction <code>clearInterval</code> direcement à l'intérieur de la fonction invoquée par setInterval() :
Pour limiter les cycles on peut utiliser un conteur et utiliser la fonction <code>clearInterval</code> directement à l'intérieur de la fonction invoquée par setInterval() :


  var count = 0;
  var count = 0;
Ligne 1 114 : Ligne 1 229 :
  }, 2000);
  }, 2000);


== DOM ==
==Arrays en JavaScript==
Les arrays (ou tableaux en français) sont des éléments très utilisés en programmation, c'est pourquoi JavaScript met à disposition des propriétés et méthodes spécifiques pour les manipuler. Rappelons d’abord qu’un array est une liste indexée d’éléments. Ces éléments peuvent être de tout type : des suites de caractères, des chiffres, mêmes des objets, des fonctions ou d’autres arrays (dans ce cas on aura donc des arrays emboités). JavaScript permet de mixer différents types de données à l’intérieur du même array, voici un exemple :


==== 1. Qu'est-ce que le DOM? ====
<source lang="JavaScript">
Le Modèle Objet de Document, ou <abbr>DOM</abbr>, <span lang="en">Document Object Model</span> est un outil permettant l'accès aux documents <code>HTML</code> et <code>XML</code>. Il permet deux choses au développeur :
var mixed = ['Hello', 3, true, { name: "Student 1", email: "student1@tecfa.edu"}, [1, 2, 3, 4]];
* Il fournit une représentation structurée du document ;
</source>
* Il codifie la manière dont un script peut accéder à cette structure.
Il s'agit donc essentiellement d'un moyen de lier une page Web, par exemple, à un langage de programmation ou de script.


Il est à remarquer que le DOM ne désigne pas une application particulière, ou bien un produit spécifique ou une présentation propriétaire d'une page Web ou, plus généralement, un document écrit dans un langage de balisage (comme <code>XML</code> par exemple). Il s'agit d'une interface qui permet de standardiser les moyens d'accès à un document balisé, notamment une page Web. Toutes les propriétés et méthodes ainsi que tous les événements disponibles pour le développeur pour manipuler et créer des pages dynamiques sont organisés sous forme de hiérarchies d'objets. Le présent cours va donner les bases permettant d'aborder ce riche domaine.
Pour faciliter la lecture d'un array on peut utiliser des espaces et des retours à la ligne :
<source lang="JavaScript">
var mixed = [
  "Hello",
  3,
  true,
  {
    name: "Student 1",
    email: "student1@tecfa.edu"
  },
  [
    1,
    2,
    3,
    4
  ]
];
</source>


Il existe maintenant des bibliothèques de scripts comme jQuery, Prototype, MooTools ou dōjō, qui offrent des solutions « clé en main » pour le développement d'interfaces évoluées. Néanmoins, pour les exploiter au mieux, il est souvent nécessaire d'analyser leur code.
En termes d'indexes cet array correspond à:


>Retour à la <abbr>TdM</abbr>
* mixed[0] --> "Hello"
* mixed[1] --> 3
* mixed[2] --> true
* mixed[3] --> Object {name: "Student 1", email: "student1@tecfa.edu"}
* mixed[4] --> [1, 2, 3, 4]


==== 2. Conception de l'arborescence ====
Veuillez noter que dans les cas des deux derniers éléments de cette array, on peut enchaîner la notation pour identifier des éléments à l'intérieur respectivement d'un objet ou d'un array emboîté:


===== a. Qu'est-ce qu'un nœud? =====
* Objet: mixed[3].name --> "Student 1"
Un langage de marquage comme <code>HTML</code> ou tout autre langage basé sur <code>XML</code> peuvent être schématisés comme une arborescence hiérarchisée. Les différentes composantes d'une telle arborescence sont désignées comme étant des nœuds. L'objet central du modèle DOM est pour cette raison l'objet <code>node</code> (<span lang="en">node</span> = nœud). Il existe différents types de nœuds. Dans un document <code>HTML</code> ordinaire, il existe dans tous les cas trois types de nœud importants qu'il nous faut distinguer : les nœuds-élément, les nœuds-attribut, et les nœuds-texte.
* Array emboité : mixed[4][0] --> 1


===== b. Un premier exemple =====
On peut modifier le contenu d'un array en associant à un index donné une nouvelle valeur :
Pour comprendre, examinons la construction <code>HTML</code> simple suivante :


<h1 class="centre">Bonjour<nowiki></h1></nowiki> 
<source lang="JavaScript">
var a = [10,20,30,40];


Dans cette construction, il y a un nœud-élément, à savoir le nœud-élément de l'élément <code>h1</code>. De plus, il y a un nœud-attribut, à savoir celui de l'attribut <code>align</code>, et enfin il y a ce qu'on appelle des « données en caractères », que l'on trouve à deux endroits : à savoir une fois comme contenu de l'élément <code>h1</code>, et une fois pour l'affectation de valeur à l'attribut <code>class</code>. Ces données en caractères représentent elles-mêmes des nœuds, à savoir des nœuds texte (pour plus de détails, il est nécessaire de se reporter à la définition des éléments et attributs dans un cours de <code>XML</code> ).
a[1] = 25;
a[3] = 50;


===== c. Un deuxième exemple, plus complexe =====
console.log(a); //--> [10, 25, 30, 50]
Un autre exemple de construction peut aider à mieux comprendre :
</source>


<h1 class="centre">Bonjour <nowiki><i>tout le monde</i>&nbsp;!</h1></nowiki> 
On peut utiliser cette notation également pour ajouter des éléments à un array. Si l'index que nous spécifions est plus grand du dernier index existant, l'array sera rempli d'éléments "undefined" jusqu'à l'index spécifié :


Dans cet exemple est ajouté le marquage en italique du groupe de mots « tout le monde ». Il est important de comprendre maintenant à quoi ressemble la hiérarchie des nœuds.
<source lang="JavaScript">
//Définir un array avec 2 éléments
var a = [10, 20];
 
//Ajouter un troisième élément, donc à l'index 2
a[2] = 30;
 
console.log(a); //--> [10, 20, 30]


L'élément <code>h1</code>, d'après les règles du DOM, possède trois nœuds enfants et un nœud associé : les nœuds enfants sont le nœud texte avec le mot « Bonjour » suivi d'un espace, le nœud élément de l'élément <code>i</code>, enfin le nœud texte est constitué de la chaîne de caractères "&amp;nbsp;!". L'attribut <code>class</code> dans la balise ouvrante <code><nowiki><h1></nowiki></code> n'est pas, par contre, un nœud enfant mais un nœud associé. Le nœud attribut a toutefois lui-même un nœud enfant, à savoir, la valeur affectée (<code>centre</code>). Même le nœud de type élément <code>i</code> a, à son tour, un nœud enfant, à savoir, le nœud de type texte de son contenu de caractères, donc les mots « tout le monde ».
//Ajouter un élément à un index supérieur à 3 (qui serait le "next in line")
a[4] = 100;


Tous les nœuds de cette arborescence sont accessibles et manipulables -y compris les propriétés des feuilles de style.
console.log(a); //--> [10, 20, 30, undefined × 1, 100]
</source>
 
Veuillez cependant noter qu'il existe des méthodes plus flexibles pour manipuler les arrays (illustrés par la suite).
===Itération dans les Arrays===
En tant que liste indexée, il est souvent utile de pouvoir récupérer tous les éléments de la liste l’un après l’autre : on parle dans ce cas d’itération. Il existe plusieurs méthodes pour itérer un array en JavaScript. L’un des plus fréquents correspond à l’utilisation d’un cycle <code>for</code> avec une variable qui détermine :
# La condition d’entrée qui correspond à 0 car les indices commencent à partir de ce chiffre ;
# Une condition de sortie, qui correspond au nombre d’éléments contenu dans l’array. On peut récupérer cette information grâce à la propriété <code>.length</code>
# Une condition d’incrémentation de la variable qui est tout simplement un incrément de +1 car les indices des arrays sont automatiquement séquentiels.
Voici un exemple :
 
<source lang="JavaScript">
var a = ["STIC I", "STIC II", "STIC III", "STIC IV"];


>Retour à la <abbr>TdM</abbr>
for(let=0; i< a.length; i++) {
  console.log(a[i]);
}
</source>


==JavaScript et le DOM==
Veuillez faire attention au fait que la condition de sortie du cycle est '''<''' et non pas <=. Cela est dû au fait que les indices des arrays commencent à 0. Donc le cycle <code>for</code> doit s'arrêter à '''length - 1'''. Autrement dit, dans le cas de l'array d'exemple qui contient 4 éléments :
Une des fonctionnalités les plus utilisées de JavaScript est sa capacité d'interagir dynamiquement avec le DOM, c'est-à-dire la structure hiérarchique des balises HTML d'une page web. C'est notamment grâce à la manipulation des éléments du DOM qui s'avèrent les interactions sur une page : apparition d'un message, déplacement d'un élément d'un endroit à un autre, changement de la taille d'une police, du couleur, etc.


Ces manipulations sont possibles grâce à l'objet document qui fait partie de l'objet global window (voir plus haut dans la page). Les propriétés, méthodes ainsi que les événements associés à cet objet permettent de manipuler le DOM.  
* a.length = 4
* Les indices seront donc a[0], a[1], a[2], a[3]
* Le cycle for doit partir à 0 et s'arrêter à 3, c'est à dire à i < a.length


* Voir les [http://www.w3schools.com/jsref/dom_obj_document.asp références de l'objet Document]
JavaScript met également à disposition une méthode associé directement aux array pour l'itération, la méthode <code>forEach()</code>. Cette méthode accepte comme argument une '''fonction de callback''' (voir plus haut dans la page) à laquelle sont passés trois arguments :


===Manipulation des éléments du DOM===
# La valeur de l'élément courant dans le cycle d'itération
====Trouver un élément====
# L'index de l'élément courant dans le cycle d'itération
Trois méthodes permettent d'identifier un élément dans la structure du document :
# L'array lui-même qui est itéré


* <code>document.getElementById(''id élément'')</code> : identifie un élément avec l'attribut id="..."
Voici un exemple :
* <code>document.getElementsByTagName(''nom de la balise'')</code> : identifie un ou plusiuers éléments avec le nom de la balise
* <code>document.getElementsByClassName(''une ou plusieurs classes'')</code> : identifie un ou plusieurs éléments avec l'attribut class="..."


Une méthode plus générale est également disponible à travers les méthodes :
<source lang="JavaScript">
//Définir un array
var a = ["STIC I", "STIC II", "STIC III", "STIC IV"];


* <code>document.querySelector(''css selector'')</code>  : cette méthode accepte des identifiants plus complexes par rapports aux trois méthodes vues plus haut dans la page, mais elle est également plus flexible, car elle permet d'identifier les éléments grâce aux selecteurs [[CSS]]. Cette méthode identifie le premier élément qui respecte les critères du selecteur.
//Définir une fonction qui sera utilité en tant que callback, veuillez noter qu'on n'est pas forcé à utiliser les 3 arguments
* <code>document.querySelectorAll(''css selector'')</code> : même principe, mais le résultat est un array avec tous les éléments qui respectent le critère de sélection.
function doSomething(element, index) {
  console.log("The element with index " + index + " has the following value: " + element);
}


Voici quelques exemples d'utilisation :
//Invoquer l'itération
a.forEach(doSomething);
</source>


document.querySelectorAll("a.external") //cette méthode identifie toutes les balises a avec classe "external"
Le résultat à la console sera le suivant:
document.querySelectorAll("h1,h2,h3") //cette méthode identifie toutes les titres de h1 à h3


Cette fonction peut également être utilisée à l'intérieur des éléments du DOM :
The element with index 0 has the following value: STIC I
The element with index 1 has the following value: STIC II
The element with index 2 has the following value: STIC III
The element with index 3 has the following value: STIC IV


var monParagraphe = document.getElementById("monTexte");
Parfois l'itération dans un array peut servir pour transformer les éléments de l'array selon un algorithm donné. On utilise dans ces cas la méthode <code>map()</code> qui accepte une fonction de callback avec les mêmes arguments de la méthode <code>forEach()</code>. La différence consiste dans le fait que la fonction <code>map()</code> transforme chaque élément passé à travers la fonction de callback. Voici un exemple qui transforme un array de note sur base 6 en notes sur base 20 :
monTexte.querySelector("span").innerHTML = "Nouveau texte du span";


Ce code identifie le premier élément span à l'intérieur du paragraphe avec id="monTexte" et change le contenu textuel.
<source lang="JavaScript">
//Définir les notes sur base 6
var grades_6 = [4.5, 5.25, 3.75, 6, 4.75, 5.5];


====Modifier un élément====
//Définir la fonction qui transforme les notes en base 20
On peut modifier différentes caractéristiques d'un élément une fois identifié dans le document par exemple à travers ces propriétés :
function transform20(element) {
  return Math.round(element * 20 / 6);
}


* <code>''element''.innerHTML</code> : modifie le contenu de la balise de l'élément sélectionné
//Obtenir un array avec toutes les notes en base 20
* <code>''element''.''attribute''</code> : modifie un attribut de la balise de l'élément sélectionné
var grades_20 = grades_6.map(transform20);
* <code>''element''.style.''property''</code> : modifie les propriétés de style de la balise de l'élément sélectionné


====Ajouter ou supprimer un élément====
console.log(grades_20); //--> [15, 18, 13, 20, 16, 18]
On peut ajouter des éléments qui n'existent pas dans la structure de base du document ou supprimer des éléments existants. Exemples :
</source>


* <code>document.createElement()</code> : définit un nouvel élément HTML
===Ajouter/enlever des éléments d'un Array===
* <code>document.appendChild()</code> : ajoute un élément à la structure existante
Une autre fonctionnalité très utile avec la liste consiste dans la possibilité d'ajouter ou enlever des éléments. Pour ce faire, JavaScript met à disposition différents méthodes :
* <code>document.replaceChild()</code> : remplace un élément existant par un autre élément
* <code>document.removeChild()</code> : supprime un élément présent dans la structure


====Exemples de manipulation====
* <code>push()</code> : ajoute un élément à la fin d'une liste
* <code>pop()</code> : enlève le dernier élément d'une liste
* <code>unshift()</code> : ajoute un élément au début d'une liste
* <code>shift()</code> : enlève le premier élément au début d'une liste


Dans la page suivante, 4 types de manipulation ont lieu lorsque la page a été chargée. L'expression <code>window.onload = function () { ....}</code> associe directement une fonction anonyme (sans nom) qui sera exécutée lorsque la page charge:
Voici quelques exemples de manipulations :


<source lang="JavaScript">
<source lang="JavaScript">
<!doctype html>
var a = ["STIC I", "ERGO I", "VIP I", "COMEL I"];
<html>
 
<head>
//Ajouter le cours BASES à la fin de l'array
    <meta charset="UTF-8">
a.push("BASES"); //--> retourne 5, le nouveau nombre d'éléments contenus
    <title>JavaScript - exemple de manipulation du DOM</title>
 
</head>
console.log(a); //--> ["STIC I", "ERGO I", "VIP I", "COMEL I", "BASES"];
<body>
 
//Ajouter le cours "METHODO" au début de la liste
<h1>JavaScript - exemple de manipulation du DOM</h1>
a.unshift("METHODO"); //-> retourne 6, le nouveau nombre d'éléments contenus
 
console.log(a); //--> ["METHODO", "STIC I", "ERGO I", "VIP I", "COMEL I", "BASES"];


<p id="p1">Premier paragraphe.</p>
//Enlever le dernier cours de la liste
<p id="p2">Deuxième paragraphe.</p>
a.pop(); //--> retourne "BASES", la valeur de l'élément enlevé
<p id="p3">Troisième paragraphe</p>
<p>Quatrième paragraphe.</p>
<div>Je ne suis pas un paragraphe!</div>


<script>
//Enlever le premier cours de la liste
a.shift(); //--> retourne "METHODO", la valeur de l'élément enlevé


window.onload = function() {
console.log(a) //--> on est révenus à l'array initiale ["STIC I", "ERGO I", "VIP I", "COMEL I"]
  //1. On remplace le texte du premier paragraphe
  var p1 = document.getElementById("p1");
  p1.innerHTML = "Le texte du premier paragraphe a été modifié par JavaScript";
  //2. On ajoute une image au deuxième paragraphe
  var p2 = document.getElementById("p2");
  var image = document.createElement("img");
  image.src = "http://lorempixel.com/200/200/abstract";
  p2.appendChild(image);
  //3. On supprime le troisième paragraphe
  var p3 = document.getElementById("p3");
  document.getElementsByTagName("body")[0].removeChild(p3);
  //4. On change la couleur du texte des paragraphes
  var pp = document.getElementsByTagName("p");
  for(var i = 0; i < pp.length; i++) {
    document.getElementsByTagName("p")[i].style.color = "#F00";
  }
}
</script>
</body>
</html>
</source>
</source>


Les manipulations 1. et 2. ne nécessitent pas d'explication supplémentaire, tandis que la 3. et la 4. sont un peu plus complexes. Il faut considérer en effet que la méthode <code>getElementsByTagName()</code> renvoie un array d'éléments, c'est-à-dire un groupe d'éléments avec un indice (voir plus haut dans la page pour les Array). On identifie un élément d'un Array avec la notation nomDuArray[indice].
Veuillez noter que ces types de manipulations mettent automatiquement à jour la liste des indices dans l'array, e.g. :


Dans la manipulation 3. nous avons identifié d'abord la balise body car il s'agit de la balise "parent" du paragraphe 3 qu'on veut supprimer. Bien qu'il n'y ait généralement qu'une seule balise body, la méthode <code>getElementsByTagName()</code> renvoie néanmoins un Array, dont le premier et seul élément est notre balise body. Vu que les indices des Array commence à 0, pour identifier notre élément body nous devons ajouter l'indice [0] à la méthode <code>getElementsByTagName("body")</code>.
<source lang="JavaScript">
var a = ["STIC II", "STIC III"];


Le même principe concerne la manipulation 4., dans laquelle le Array contient par contre plusieurs éléments. Pour changer chaque élément, il faut par conséquent un cycle. Nous avons créé ce cycle à l'aide de la fonction for et nous avons déclaré en tant que fonction de sortie la propriété length de l'Array lui-même. Cette propriété identifie le nombre d'éléments présents dans l'Array.
console.log(a[0]); //--> "STIC II";


[http://codepen.io/mafritz/pen/vNRVxw Tester cet exemple]
//Ajouter un élément au début de la liste
a.unshift("STIC I");


Ce type de manipulation est plutôt complexe, raison pour laquelle des bibliothèques JavaScript (e.g. [[jQuery]]) offrent des méthodes plus faciles pour accéder aux éléments du DOM.
console.log(a[0]); //--> "STIC I";
console.log(a[1]); //--> "STIC II";
</source>


===Événements du DOM===
En considération du fait qu'un array en JavaScript peut contenir tout type de données, la méthode <code>push()</code> peut être utilisée pour ajouter des objets à un array. Voici un exemple :
Les événements du DOM permettent d'identifier l'interaction de l'utilisateur avec la page, par exemple à travers les mouvements de la souris, les touches du clavier, etc. Les événements concernent également les éléments eux-mêmes, par exemple dans le cas de l'objet window ou encore des éléments d'un formulaire.  


* Voir les [http://www.w3schools.com/jsref/dom_obj_event.asp références des Événements du DOM]
<source lang="JavaScript">
//Définir un array vide
var students = [];


====L'événement onload====
//Définir une fonction qui ajoute un nouveau étudiant à l'array
L'événement <code>onload()</code> est déclenché lorsqu'un élément (ou tout le DOM) a été téléchargé dans le navigateur web.
function addStudent(name, email, status) {
Une notation qui est très utilisée et qui, par contre, nécessite de déclarer explicitement l'objet window concerne l'événement onload :
  //Créer un nouveau objet avec les valeurs passées en tant qu'arguments
  var newStudent = {
    name : name,
    email : email,
    status : status
  };
  //Ajouter l'objet à l'array
  students.push(newStudent);
}


* <code>window.onload()</code> : permet de déclencher du code une fois que la page a été chargée dans le navigateur. Il faut être attentif au fait que cette fonction peut être déclarée seulement une fois dans chaque page. Si plusieurs déclarations de window.onload sont disponibles dans la même page, seulement celle déclarée en dernière sera exécutée.
//Ajouter un étudiant
addStudent('Student 1', 'student1@tecfa.edu', 'active');


<script>
console.log(students) //--> Un élément dans l'array;
window.onload = alert("Je ne serais pas affiché");
window.onload = alert("Je serais affiché");
</script>


Un autre problématique relative à cette fonction concerne le fait que l'événement onload s'avère lorsque tous les éléments du DOM ont bien été chargés, y compris images, feuilles de style, etc. Ceci peut parfois retarder le déclenchement de l'événement et par conséquent toutes les éléments interactifs associés à cet événements ne seront pas disponibles.
//Ajouter un autre étudiant
addStudent('Student 2', 'student2@tecfa.edu', 'active');


L'événement <code>onload()</code> peut être également associé à d'autres éléments du DOM internes ou externes, comme par exemple les images, les iframes, etc.
console.log(students) //--> Deux éléments dans l'array;
</source>


====Événements liés à la souris====
Il existe également la méthode <code>splice()</code> qui permet de faire des manipulations à tout endroit dans la liste (pas seulement au début ou à la fin). Voir la documentation MDN pour plus de détails : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
Parmi les événements les plus utilisés dans l'interaction avec le DOM, il y a sans doute les événements liés aux mouvements et clicks de la souris. Voici une liste non exhaustive de ces événements :


* <code>click</code> : l'événement est déclenché avec un click de la souris
===Autres manipulations utiles===
* <code>mouseover</code> : l'événement est déclenché lorsque la souris passe sur l'élément
Les méthodes mises à disposition de JavaScript pour manipuler des arrays sont nombreuses, vous pouvez vous référez à la documentation MDN pour une liste exhaustive et très technique (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) ou à la liste W3School (http://www.w3schools.com/jsref/jsref_obj_array.asp). De suite nous illustrons quelques méthodes qui pourraient être utiles de manière générale.
* <code>mouseout</code> : l'événement est déclenché lorsque la souris quitte un élément


Pour attribuer un événement à un élément il faut procéder ainsi :
* '''<code>join()</code>'''


# '''Identifier l'élément dans la structure du DOM''' (voir plus haut dans cette page)
Cette méthode permet de joindre des éléments d'un array dans une suite de caractères avec un élément de séparation qui peut être spécifié. Si aucun élément de séparation n'est spécifié, les éléments seront séparés par une virgule e.g. :
# '''Spécifier un événement déclencheur''' à travers une des notations disponibles (e.g. document.getElementById("mon-bouton").onclick)
# '''Associer à cet événement un "event handler"''' (gestionnaire d'événement), c'est-à-dire le processus (normalement une '''fonction''') qui doit se mettre en marche lorsque l'événement se produit


Il y a deux manières d'associer un événement à un élément :
<source lang="JavaScript">
var a = ["STIC I", "STIC II", "STIC III", "STIC IV"];


*Utiliser la '''propriété de l'événement''' qui se compose de "on" + événement (élément.onclick, élément.onmouseover, élément.onmouseut, ...) à la quelle on associe une fonction :
console.log(a.join()); //--> STIC I,STIC II,STIC III,STIC IV
** <code>élément.'''on'''événement = function () { ... }</code>
console.log(a.join(", ")); //--> STIC I, STIC II, STIC III, STIC IV
*Utiliser la '''méthode addEventListener''' qui prévoit deux arguments : l'événement et la fonction à exécuter :
console.log(a.join("___")); //--> STIC I___STIC II___STIC III___STIC IV
**<code>élément.addEventListener(événement, fonction)</code>
</source>


Le gestionnaire d'événement peut être une fonction déjà définie ou anonyme. Il faut cependant faire attention au fait qu'un gestionnaire d'événement est une référence à la fonction et non pas l'exécution de la fonction elle-même. En d'autres termes, il ne faut pas utiliser les parenthèses dans un gestionnaire d'événement :
* '''<code>filter()</code>'''


function faireQuelqueChose() {
Cette méthode permet de déterminer dans une liste quels sont les éléments qui respectent un certain critère, donné par une fonction de callback. Dans l'exemple suivant nous allons créer un nouveau array qui inclut exclusivement les notes suffisantes (>= 4) d'un élève.
    //code
}
mon-element.mon-evenement = faireQuelqueChose; //OK!
mon-element.mon-evenement = faireQuelqueChose(); //Faux, de cette manière la fonction sera exécutée de toute manière, sans attendre l'événement déclencheur


Veuillez par contre noter que si l'on associe comme gestionnaire une méthode d'un objet, alors il faudra de toute manière insérer les parenthèses.
<source lang="JavaScript">
//Liste de toutes les notes
var grades = [4, 3.75, 2.5, 5.5, 6];


var o = {}:
//Définir la fonction de filtre
o.faireQuelqueChose = function () {
function isEnough(element) {
  //code
  return element >= 4;
}
}
mon-element.mon-evenement = o.faireQuelqueChose; //Faux
 
mon-element.mon-evenement = o.faireQuelqueChose(); //OK!
//Liste des notes suffisantes
var gradesGt4 = grades.filter(isEnough);


On peut également utiliser une fonction anonyme en tant que gestionnaire d'événement :
console.log(gradesGt4); //--> [4, 5.5, 6]
</source>


mon-element.mon-evenement = function() {
* '''<code>every()</code>'''
    console.log("L'événement a eu lieu");
}


Enfin, il est possible d'utiliser la méthode<code>élément.addEventListener(événement, gestionnaire)</code> au lieu de la notation élément.événement = gestionnaire. Cette méthode à l'avantage de pouvoir s'ajouter à des gestionnaires d'événements déjà déclarés sur le même élément, sans les annuler (mais ne s'applique pas à window.onload). Voici un exemple pour illustrer ce principe qui se réfère au click sur un bouton :
Cette méthode permet d'évaluer si tous les éléments dans une liste respectent ou pas un critère donné par une fonction de callback. Cette fonction retourne true si tous les éléments respectent le critère ou false si au moins un élément ne respecte pas. Dans cet exemple on peut évaluer si un élève n'a reçu que des notes suffisantes (>= 4).


<source lang="JavaScript">
<source lang="JavaScript">
<button id="myBtn">Button</button>
//Définir la liste des notes
<script>
var grades = [4, 4.25, 5.5 , 6, 5.25, 4.75, 4.5];
var myBtn = document.getElementById("myBtn");


//1. Utilisation de onclick
//Définir la fonction pour le critère
myBtn.onclick = function () {
function isEnough(element) {
   console.log("Événement 1");
   return element >= 4;
}
}
myBtn.onclick = function () {
 
   console.log("Événement 2");
//Définir si l'élève n'a que des notes suffisantes
if(grades.every(isEnough)) {
   console.log("Congratulations!");
} else {
  console.log("You have at least one exam to retake");
}
}
</source>
Le résultat de cet exemple sera "Congratulations!" car toutes les notes de l'array grades sont >= 4. La méthode <code>some()</code> est similaire, si ce n'est pour le fait qu'elle sera true si au moins un élément respecte le critère de la fonction de callback.
* '''<code>sort()</code>'''


//-> Si on click sur myBtn, on verra dans la console seulement "Événement 2";
Cette méthode permet de trier les éléments d'un array. Elle accepte en option une fonction de callback qui permet de déterminer le critère pour trier les éléments. Si aucune fonction n'est passé, le trie sera fait selon le critère de grandeur selon lequel 1 < 2, a < b, A < a, etc. Exemple:


//2. Utilisation de addEventListener
<source lang="JavaScript">
myBtn.addEventListener("click", function () {
var a = [1, "Banana", 3, "apple", 0.5];
  console.log("Événement 1");
});
myBtn.addEventListener("click", function () {
  console.log("Événement 2");
});


//-> Si on click sur myBtn, cette fois-ci, on verra dans la console les deux messages.
console.log(a.sort()); //-> [0.5, 1, 3, "Banana", "apple"]
</script>
</source>
</source>


Voici un exemple avec des commentaires pour résumer les différentes utilisations des événements liés à la souris :
Si, par contre, on veut créer des critères de classement plus complexes, nous allons exploiter le fait que cette fonction accepte deux paramètres a et b qui représentent deux éléments de l'array à comparer. La méthode sort() va automatiquement faire toutes les comparaisons possibles entre les éléments de l'array et détermine l'ordre selon la valeur retournée par la fonction de comparaison :
* Si la valeur retournée est mineur de 0, alors a < b
* Si la valeur retournée est égale à 0, alors a == b
* Si la valeur retournée est majeur de 0, alors a > b
 
Voici un exemple: imaginons un concours dans lequel on demande aux participants de deviner le nombre de cantons en Suisse (y compris le 1/2 cantons). On veut donc trier les réponses en fonction qu'elles s'approchent le plus du chiffre 26. Pour ce faire on compare la différence absolue entre 26 et a avec la différence absolue entre 26 et b :


<source lang="JavaScript">
<source lang="JavaScript">
<!doctype html>
//Définir les réponses
<html>
var r = [21, 44, 26, 29, 6, 15, 26, 3];
<head>
    <meta charset="UTF-8">
    <title>JavaScript - événements liés à la souris</title>
</head>
<body>
  <h1>JavaScript - événements liés à la souris</h1>
  <button id="mon-bouton">Cliquez ici</button>
  <span id="feedback"></span>
  <script>
  //Déclarer une fonction en cas d'événement click
  function showFeedbackClick() {
    document.getElementById("feedback").innerHTML = "J'ai cliqué sur le bouton";
  }


  //Définir une fonction en cas d'événement mouseover
//Définir la fonction de classification
  function showFeedbackOver() {
function compare(a, b) {
    document.getElementById("feedback").innerHTML = "La souris se trouve sur le bouton";
  return Math.abs(26 - a) - Math.abs(26 - b);
  }
}


  //Identifier le bouton dans le DOM
console.log(r.sort(compare)); //--> [26, 26, 29, 21, 15, 44, 6, 3]
  var monBouton = document.getElementById("mon-bouton");
 
  //Trois manières différentes d'associer une fonction à un événement :
  //1. Événement click avec association d'une fonction, sans ()!
  monBouton.onclick = showFeedbackClick
  //2. Événement mouseover avec méthode addEventListener();
  monBouton.addEventListener("mouseover", showFeedbackOver);
  //3. Événement mouseout avec fonction anonyme
  monBouton.onmouseout = function() {
    document.getElementById("feedback").innerHTML = "La souris n'est plus sur le bouton";
  }
  </script>
</body>
</html>
</source>
</source>


[http://codepen.io/mafritz/pen/NGzpEo Tester cet exemple]
On aurait pu écrire la même fonction de comparaison de la manière suivante :


Pour annuler un gestionnaire d'événement, il suffit de le redéclarer null sa propriété d'événement (e.g. <code>mon-élément.mon-événement = null</code>) ou d'utiliser la méthode <code>élément.removeEventListener()</code>.
<source lang="JavaScript">
function compare(a, b) {
  var diff_a = Math.abs(26 - a);
  var diff_b = Math.abs(26 - b);


Il existe une méthode plus souple pour définir un gestionnaire d'événement et que l'on retrouve aussi dans ActionScript.
  if(diff_a < diff_b) {
    return -1;
  } else if (diff_a == diff_b) {
    return 0;
  } else {
    return 1;
  }
}
</source>
 
On peut utiliser la fonction de comparaison même avec des arrays d'objets. Imaginons l'exemple précédente avec le nom du participant associé à sa réponse :


Dans l'exemple suivant,la fonction <code>start()</code> sera exécutée dès que la page charge, ceci à cause de l'instruction <code>window.onload = start;</code> qui associe à l'événement "onload" le nom d'une fonction qu'il faut exécuter. Rien de neuf. Par contre, la gestion du 2ème événement se fait différemment.
<source lang="JavaScript">
<source lang="JavaScript">
<!DOCTYPE html>
//Définir les réponses des participants
<html>
var r = [
  <head>
  {
      <title>Event handling</title>
    name : 'Participant 1',
      <script type = "text/javascript">
    guess : 21
        window.onload = start;
  },
        // var my_para_button  ="";
  {
    name : 'Participant 2',
    guess : 26
  },
  {
    name : 'Participant 3',
    guess : 12
  }
];
 
//Modifier la fonction de comparaison pour prendre en compte juste la propriété guess de l'élément
function compare(a, b) {
  return Math.abs(26 - a.guess) - Math.abs(26 - b.guess);
}


function start() {
//Utiliser une fonction pour imprimer les résultats
  // put an event handler on the div box
function printResult(element, index) {
  var my_para_button = document.getElementById("box");
  var rank = index + 1;
  my_para_button = addEventListener("click", modifyText);
  console.log(rank + ". " + element.name + " with answer " + element.guess);
        }
}


function modifyText() {
//Imprimer l'ordre des participants en utilisant la fonction forEach()
  // get the box
r.sort(compare).forEach(printResult);
  var my_content = document.getElementById("content");
  my_content.innerHTML = "That was so good";
}
      </script>
  </head>
  <body>
      <div id="box">
        <p style="background-color:yellow" id="content">CLICK ME !</p>
      </div>
  </body>
</html>
</source>
</source>
Source: http://tecfa.unige.ch/guides/js/ex-intro/event-handler.html


La fonction ''start'' ajoute un gestionnaire d’événement au bouton ''my_para_button'' en utilisant la méthode <code>addEventListener ("click", modifyText); </code>. Le premier argument, "click", identifie le type d’événement, et le deuxième donne le nom de la fonction.
Le résultat à la console sera le suivant :


===L'élément this dans le DOM===
1. Participant 2 with answer 26
Lorsqu'une fonction est associée à un élément du DOM, cet élément est disponible à l'intérieur de la fonction elle-même, à travers l'élément <code>this</code>. Ceci permet de ne pas avoir à identifier à nouveau l'élément dans le DOM. Voici un exemple qui modifie le label d'un bouton et le désactive après le click :
2. Participant 1 with answer 21
3. Participant 3 with answer 12
 
* <code>'''map()'''</code>
 
La méthode <code>map()</code> permet de transformer tous les éléments d'un array à travers la même fonction, sans modifier l'array original.


<source lang="JavaScript">
<source lang="JavaScript">
<!doctype html>
var originalArray = [1,2,3,4,5,6];
<html>
 
<head>
var transformedArray = originalArray.map(function(element) {
    <meta charset="UTF-8">
  return element * 10;
    <title>JavaScript - this</title>
});
</head>
//Transformed array -> [10, 20, 30, 40, 50, 60]
<body>
  <h1>JavaScript - this</h1>
  <button id="mon-bouton">Cliquez ici</button>
  <script>
    var monBouton = document.getElementById("mon-bouton");
    monBouton.onclick = function() {
      //Changer le label du bouton
      this.innerHTML = "J'ai cliquez sur le bouton";
      //Désactiver le bouton
      this.disabled = "disabled";
    }
  </script>
</body>
</html>
</source>
</source>


L'élément <code>this</code> peut être très utile lorsqu'on genère plusieurs éléments dynamiquement pour associer un comportement à chaque élément. Voici un exemple similaire au précédent, mais dans lequel 5 boutons sont créés avec la fonction <code>document.createElement("button")</code>. Chaque bouton créé est associé ensuite à un événement de type <code>onclick</code>, à l'intérieur du quel on fait référence au bouton avec l'élément <code>this</code> :
* <code>'''indexOf()'''</code>
 
La méthode <code>indexOf(search)</code> cherche s'il existe un élément qui correspond à l'argument. S'il le trouve, la méthode renvoie le numéro de l'index (à partir de 0), autrement -1.


<source lang="JavaScript">
<source lang="JavaScript">
var list = document.getElementById("btnList");
var courses = ["STIC I", "STIC II", "STIC III", "STIC IV"];
for(var i = 1; i <= 5; i++) {
 
  var btn = document.createElement("button");
var areYouThere = courses.indexOf("STIC II"); //--> 1
  btn.innerText = "Cliquez sur le bouton " + i;
var areYouNotThere = courses.indexOf("ERGO I"); //--> -1
  btn.onclick = function () {
    this.innerText = "J'ai cliqué sur ce bouton";
    this.disabled = "disabled";
  }
  list.appendChild(btn);
}
</source>
</source>


[http://codepen.io/mafritz/pen/OyZJvx Tester cet exemple et l'exemple précédent]
==Objets en JavaScript==
===Définition d'un objet===
Comprendre les objets en JavaScript équivaut à comprendre le langage lui-même, car pratiquement tout est un objet en JavaScript : les types de données (String, Number, Array, …) sont des objets, l’élément « document » utilisé pour accéder aux différents éléments d’une page web est un objet, et ainsi de suite. Par conséquent, la définition d’un objet doit forcément être assez générale pour prendre en compte toutes les différentes applications des objets :
 
* '''Un objet est un élément qui contient d’autres éléments, même d'autres objets.'''
 
Les éléments contenus dans un objet peuvent être de deux types :
 
# '''Propriétés''' : c’est l’équivalent des '''variables''' dans un objet, car une propriété n’est qu’une valeur associée à un objet.
# '''Méthodes''' : c’est l’équivalent des '''fonctions''' dans un objet, car une méthode permet d’exécuter une certaine action sur un objet, souvent en relation avec ces propriétés.
 
Voyons tout de suite un exemple. Vu que pratiquement tout est un objet en JavaScript, prenons une simple suite de caractères (i.e. string).


===JavaScript et CSS===
var phrase = "Ceci n’est pas un Wiki" ;
====Utiliser les propriétés de style====
Javascript permet de modifier non seulement la structure du DOM, mais également les propriétés de style des éléments. Il est possible de modifier toutes les déclarations de style disponibles dans un fichier CSS à travers la notation :


''élément''.style.''propriété'' = "nouvelle valeur";
La variable phrase est maintenant un objet de type String, un objet qui fait partie du langage JavaScript de base, et donc les propriétés et les méthodes sont accessibles à tout endroit dans le code. Voici deux exemples :


Par exemple le code suivant modifie la couleur du texte d'un élément du DOM avec id="mon-paragraphe" :
console.log(phrase.length) ; //22
console.log(phrase.toUpperCase()) ; //CECI N'EST PAS UN WIKI


document.getElementById("mon-paragraphe").style.color = "#F00";
On vient d’utiliser une propriété (i.e. length) et une méthode (i.e. toUpperCase()) associés à un objet de type String. De plus, on vient également d'utiliser la méthode log() de l'objet console pour afficher le contenu dans le navigateur web - tout est un objet! Pour mieux comprendre encore cette idée, on aurait même pu tout simplement utiliser la propriété et la méthode directement avec la suite de caractères, sans utiliser une variable :


Les changements de style peuvent être appliqués à tout moment dans le code et être donc associés, par exemple, à des événements (voir plus haut dans la page).
"Ceci n'est pas un Wiki".length ;
"Ceci n'est pas un Wiki".toUpperCase() ;


====Utiliser les classes====
L’accès aux propriétés et méthodes d’un objet se fait normalement à travers une notation « par points ». Vu qu’une propriété est une variable, pour y accéder il faut tout simplement ajouter son nom après l’objet et le point :
JavaScript permet également de manipuler les noms de class des éléments. La manière la plus simple consiste à utiliser la propriété <code>className</code> pour lire ou définir la class d'un élément :


//Lire
* <code>Objet.propriété</code>
var maClasse = ''élément''.className; // --> e.g. active
Au contraire, une méthode étant une fonction, il faut ajouter également les deux parenthèses.
//Définir
* <code>Objet.méthode()</code>
''élément''.className = 'active'


Il faut noter que la propriété className se réfère à tout le l'attribut HTML. Voici un élément HTML qui a plusieurs classes :
Cette notation peut être "enchaînée", par exemple la notation suivante permet transorm la phrase "Ceci n'est pas un Wiki" en majuscules et extrait les 4 premiers caractères :


<source lang="HTML5">
"Ceci n'est pas un Wiki".toUpperCase().substr(0,4) //--> CECI
<div id="myDiv" class="class1 class2 class3">Mon div</div>
 
</source>
JavaScript met à disposition des développeurs trois types d’objets différents :
 
# Les '''objets globaux''' du langage de base (i.e. « '''native objects''' ») : il s’agit d’objet constitutifs du langage lui-même et qui sont par conséquent accessibles dans n’importe quel endroit dans le code et indépendamment de l’utilisation de JavaScript côté client ou serveur dans une page web, dans une application mobile, logiciel desktop, etc.
# Les '''objets mis à disposition par l’environnement''' : il s’agit d’objets qui dépendent directement de l’endroit dans lequel le code est interprété (voir [[Tutoriel JavaScript côté client]] ou [[Node.js]])
# Les '''objets personnalisés''' : il s’agit d’objets que le développeur définit lui-même selon les nécessités particulières à l’application


Et voici le résultat de quelques opérations avec JavaScript
Une autre manière de différencier les objets concerne la possibilité de les modifier, car certains objets (surtout les objets natifs et certains objets environnementales) sont "read-only", c'est-à-dire qu'il n'est pas possible de modifier les méthodes et les propriétés d'un objet. Par exemple la propriété PI de l'objet Math contient une approximation du nombre PI. Cette propriété ne peut pas être modifiée, même si on essaie de l'associer à une autre valeur:


<source lang="JavaScript">
<source lang="JavaScript">
var myDiv = document.getElementById("myDiv");
//Valeur de base
var classes = myDiv.className; // --> class1 class2 class3
Math.PI; //--> 3.141592653589793
//Ajouter une quatrième class
 
myDiv.className = classes + " class4"; // --> class1 class2 class3 class4
//Essayer d'associer une autre valeur
//Remplacer avec une seule class
Math.PI = 2; //--> 2 (cela parrait marcher, mais...)
myDiv.className = "class99"; --> class99
 
//Afficher à nouveau la propriété
Math.PI; //--> 3.141592653589793 (read-only value)
</source>
</source>


Pour faciliter la gestion de plusieurs classes sur le même élément, JavaScript met à disposition la propriété <code>classList</code> qui possède plusieurs méthodes ([http://www.w3schools.com/jsref/prop_element_classlist.asp voir la liste complète]) parmi lesquelles on trouve :
===Objets globaux (Native Objects)===
Les objets disponibles dans le langage de base constituent les bases de l’API du langage lui-même, c’est-à-dire les propriétés et les méthodes que le langage considère utile pour définir les algorithmes nécessaires à manipuler les données dans une application. Voici de suite une liste non exhaustive de certains de ces objets (pour la liste complète : consulter par exemple la [https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux documentation Mozilla]).
====String====
L'objet String permet d'exécuter des manipulations sur des chaînes de caractères. Voici quelques exemples :
 
var msg = "Bonjour";
msg.toUpperCase(); //BONJOUR
msg.substr(3, 7); //jour
msg.replace("jour", "soir"); //Bonsoir
 
* Voir les [http://www.w3schools.com/jsref/jsref_obj_string.asp références de l'objet String]


* <code>''élément''.classList.add(''class'', [''class''])</code> : permet d'ajouter une ou plusieurs nouvelles classes à l'élément
====Number====
* <code>''élément''.classList.remove(''class'', [''class''])</code> : permet d'enlever une ou plusieurs classes à l'élément
L'objet Number permet d'exécuter des manipulations sur des nombres. Voici un exemple pour la méthode <code>toFixed()</code> qui transforme un chiffre en caractère avec une précision décimale fixée.


Les deux codes suivants sont donc équivalents :
var num = 6.749737898732;
num.toFixed(2); //6.75


<source lang="JavaScript">
Curiosité: vous pouvez utiliser cette méthode pour tester empiriquement l'un des problèmes les plus répandue dans la gestion des nombres décimal par des systèmes computationnels binaires :
var myDiv = document.getElementById("myDiv");
 
var division = 1 / 10; //--> on s'attend à 0.1;
division.toFixed(20); //--> mais au fond... "0.10000000000000000555"


//Avec className
Les chiffres décimales sont en réalité des approximations, dans la pluspart des cas assez précises, mais qui parfois peuvent donner des problèmes.
var classes = myDiv.className; // --> class1 class2 class3
myDiv.className = classes + " class4"; // --> class1 class2 class3 class4


//Avec classList
* Voir les [http://www.w3schools.com/jsref/jsref_obj_number.asp références de l'objet Number]
myDiv.classList.add("class4"); // --> class1 class2 class3 class4
</source>


Une autre méthode utile associée à la propriété <code>classList</code> est la méthode <code>toggle()</code> qui :
====Math====
L'objet Math permet d'exécuter des manipulations mathématiques sur des chiffres. Voici deux exemples pour trouver un nombre aléatoire entre 1 et 100 :


# Ajoute une classe si la classe n'est pas associée à l'élément
var randomNumber = Math.floor((Math.random() * 100) + 1);
# Enlève une classe si la classe est déjà associée à l'élément
var randomNumber = Math.round((Math.random() * 100) + 1);


[http://codepen.io/mafritz/pen/OyZzpw Tester un exemple]
* <code>Math.random()</code> renvoie un nombre au hasard entre [0;1[.
* <code>Math.floor(x)</code> renvoie le plus grand entier inférieur ou égal à x.
* <code>Math.round(x)</code> renvoie le plus grand entier supérieur ou égal à x.


===JavaScript et les formulaires===
Ceux-ci peuvent pour être utiles si vous souhaitez prendre au hasard un objet dans un [[#Array|Array]] :
Même si JavaScript ne se limite plus simplement à ces tâches, la manipulation des formulaires et des éléments des formulaires (e.g. champs de texte, etc.) restent des fonctionnalités très utilisées (et utiles). JavaScript peut en effet identifier le contenu des éléments des formulaires et utiliser se contenu dans sa logique de programmation pour apporter des changements à la page. Par exemple la propriété .value permet d'identifier le contenu d'un champ de texte :


var maValeur = document.getElementById("mon-champ-de-texte").value;
<source lang="JavaScript">
var myFruits = ["pomme", "poire", "fraise", "framboise"];
var myFruitsDrawn = new Array(myFruits.length - 1); // création d'un array de taille 4 - 1 (un array commence à l'objet 0)


Cette notation, comme toute propriété, peut être utilisé aussi pour modifier le contenu d'un champ.
function chooseRandom(i) {
i = Math.round(Math.random()*(myFruits.length - 1));
if (myFruitsDrawn.indexOf(myFruits[i]) === -1) // indexOf(x) renvoie l'index de myFruitsDrawn où se trouve l'objet x, sinon renvoie -1 (ici on l'utilise pour checker si l'objet à la position i de l'array myFruits ne se trouve pas déjà dans myFruitsDrawn)
{
  return (i);
}
return (-1)
}


window.onload = function() {
function displayRandomFruits(){
    document.getElementById("mon-champ-de-texte").value = "Nouvelle valeur";
var i = -1
 
while (i === -1)
{
  i = chooseRandom(i);
  }
  }
myFruitsDrawn.push(myFruits[i]); // push(x) 'pousse' x dans l'array myFruitsDrawn
myFruits.splice(i,1); // splice(x) coupe myFruits en position i de 1 objet, c'est-à-dire on enlève l'élément qui a été précédemment push
return (myFruitsDrawn[myFruitsDrawn.length - 1]); // la fonction retourne un fruit choisi au hasard et qui n'a pas déjà été choisi !
}
</source>
* Voir les [http://www.w3schools.com/jsref/jsref_obj_math.asp références de l'objet Math]


Voici un exemple qui utilise l'événement onchange pour suggérer une valeur combiné du prénom et nom d'une personne. Si le champ complet est modifié, néanmoins, aucune suggestion ne sera plus faite.
====Date====
L'objet Date permet d'exécuter des manipulations sur les dates. La gestion des dates n'est pas simple en JavaScript. Par exemple la méthode <code>getMonth()</code> qui identifie le mois de l'année en chiffres ne propose pas les mois de 1 à 12, mais plutôt de 0 à 11. Donc le mois 10 n'est pas octobre comme on pourrait s'imaginer, mais plutôt novembre. Voici un exemple pour obtenir le jour du mois (de 1 à 31) :
 
var d = new Date();
var aujourdhui = d.getDate();
 
* Voir les [http://www.w3schools.com/jsref/jsref_getdate.asp références de l'objet Date]
 
===Objets personnalisés===
JavaScript permet de créer ses propres objets avec les propriétés et méthodes souhaitées. Les propriétés sont représentées par des données, tandis que les méthodes par des fonctions.
 
====Définition d'un objet====
La définition d'un objet peut se faire de différentes manières. Les notations suivantes définissent le même objet appelé Cours :


<source lang="JavaScript">
<source lang="JavaScript">
<!doctype html>
//1.
<html>
var Cours = {
<head>
     nom: "STIC I",
     <meta charset="UTF-8">
     periode: "Automne",
     <title>JavaScript - formulaires</title>
    nombreExercices: "8"
</head>
};
<body>
 
<h1>JavaScript - formulaires</h1>
//2.
Prénom : <input type="text" id="prenom"><br>
var Cours = {}; //Aussi var Cours = new Object();
Nom : <input type="text" id="nom"><br>
Cours.nom = "STIC I";
Nom complet : <input type="text" id="nom-complet"><br>
Cours.periode: "Automne";
<script>
Cours.nombreExercices: "8";
  var prenom = document.getElementById("prenom");
  var nom = document.getElementById("nom");
  var nomComplet = document.getElementById("nom-complet");
  function suggererNomComplet() {
    nomComplet.value = nom.value + ", " + prenom.value;
  }
  prenom.onchange = suggererNomComplet;
  nom.onchange = suggererNomComplet;
  nomComplet.onchange = function() {
    prenom.onchange = null;
    nom.onchange = null;
  }
</script>
</body>
</html>
</source>
</source>


[http://codepen.io/mafritz/pen/PPeodJ Tester cet exemple]
Les noms des propriétés ne doivent pas suivre la notation des variables, mais s'ils ne la suivent pas, il faut les insérer entre guillemets comme les valeurs :
 
var Cours = {
    nomRespecte: "STIC I",
    "nom-ne-respecte-pas": "STIC I"
}


====Validation des formulaires====
On peut associer à un objet aussi des méthodes, encore une fois de différentes manières dont le résultat est équivalent :
Un autre cadre d'utilisation de JavaScript concerne la validation des formulaires avant qu'ils soient soumis au serveur (i.e. avec actualisation de la page). Cette fonction est désormais partiellement prise en charge par les attributs [[HTML5]] tels que "required", mais il y néanmoins des validations plus complexes qui nécessitent du codage JavaScript.


Dans la structure du DOM, JavaScript peut identifier des champs d'un formulaire de plusieurs manières. On peut utiliser la méthode getElementById() et attribuer à chaque champ un id univoque, ce qui est probablement la manière plus sûre. Sinon, JavaScript identifie les formulaires et ses champs à travers un Array qui se construit sur l'attribut name du formulaire et des champs :
<source lang="JavaScript">
//1. avec une fonction anonyme
var Cours = {};
Cours.nom = "STIC I";
Cours.afficherNom = function () {
    return "STIC I"
};


<source lang="HTML5">
//2. Définir la fonction à l'avance
  <form name="mon-formulaire">
  function afficherNomDuCours () {
     <input type="texte" name="mon-champ1">
     return "STIC I";
    <input type="texte" name="mon-champ2">
}
  </form>
var Cours = {};
Cours.nom = "STIC I";
  Cours.afficherNom = afficherNomDuCours;
</source>
</source>


Le form peut être identifié à travers la notation <code>document.forms['mon-formulaire']</code> tandis que les champs respectivement avec :
====Utilisation des objets====
Une fois définit l'objet, on peut l'utiliser facilement à travers la notation "par points" pour propriétés dont le nom respecte la notation des variables ou les méthodes. Pour les noms des propriétés qui ne respectent pas la nomination des variables, il faudra utiliser la notation "à Array". Voici des exemples :


* <code>document.forms['mon-formulaire']['mon-champ1']</code>
<source lang="JavaScript">
* <code>document.forms['mon-formulaire']['mon-champ2']</code>.
var Cours = {
    nomRespecte: "STIC I",
    "nom-ne-respecte-pas": "STIC I"
};
Cours.maMethode = function () {
    console.log("Je suis une méthode de l'objet Cours");
};
var nomDuCours1 = Cours.nomRespecte;
var nomDuCours2 = Cours["nom-ne-respecte-pas"];
Cours.maMethode(); //Il faut utiliser les parenthèses
</source>


Il est également possible d'utiliser la notation "par point", au lieu des parenthèses carrées, si le nom du champ respecte la notation correcte pour les variables JavaScript.  
====L'élément this dans les Objets====
Parfois il est nécessaire d'accéder à d'autres propriétés ou méthodes d'un objet à l'intérieur de l'objet lui-même. Dans ce cas, l'objet est représenté par la notation <code>this</code>. Voici un exemple illustratif :


Voici un simple exemple de validation pour montrer brièvement le mécanisme. Le code JavaScript contrôle que le champ email ne soit pas vide et que les conditions ont été acceptées à travers le checkbox.  
<source lang="JavaScript">
var Cours = {};
Cours.nom = "STIC I";
Cours.afficheLeNom = function () {
    console.log(this.nom)
};
Cours.afficheLeNom(); //--> STIC I
</source>
 
====Définir des objets prototypes====
Les notations qu’on a vues plus haut pour définir un objet sont utiles pour définir un seul objet de ce type, ce qu’on appelle une « instance » de l’objet. Il est également possible de créer plusieurs instances d’un objet, pour ce faire il faut le définir à travers une fonction « constructrice », qui crée des objets prototypes. Voici un exemple pour créer deux instances d’un objet « Tutoriel » :


<source lang="JavaScript">
<source lang="JavaScript">
<!doctype html>
function Tutoriel(argument, niveau) {
<html>
   this.argument = argument;
<head>
   this.niveau = niveau;
    <meta charset="UTF-8">
   this.printTutorielInfo = function () {
    <title>JavaScript - formulaires</title>
     return 'Tutoriel de niveau ' + this.niveau + ' sur ' + this.argument;
</head>
<body>
<h1>JavaScript - formulaires</h1>
<form name="mon-formulaire">
  Email : <input name="email" type="text"><br>
  <input type="checkbox" name="conditions"> J'accepte les conditions d'inscription<br>
  <input type="submit" value="Envoyer">
</form>
<script>
   var monForm = document.forms["mon-formulaire"];
  var monEmail = monForm["email"];
   var mesConditions = monForm["conditions"];
   monForm.onsubmit = function() {  
     if (monEmail.value !== "" && mesConditions.checked) {
      //Le formulaire sera soumis au serveur et la page actualisée
      return true;
    } else {
      window.alert("Vous devez insérer votre email et accepter les conditions");
      //Le retour false fait ainsi que le formualire ne soit pas soumis et la page pas actualisée
      return false;
    }
   }
   }
</script>
}
</body>
var tutorielJavaScriptBase = new Tutoriel('JavaScript', 'intermédiare');
</html>
var tutorielNodeJs = new Tutoriel('Node.js', 'avancé');
 
console.log(tutorielJavaScriptBase.printTutorielInfo()); // --> Tutoriel de niveau intermédiare sur JavaScript
console.log(tutorielNodeJs.printTutorielInfo()); // --> Tutoriel de niveau avancé sur Node.js
</source>
</source>


== La sécurité avec JavaScript ==
L’objet Tutoriel fonction correctement, mais son fonctionnement interne peut être amélioré, car à présent chaque fois qu’on crée une instance de cet objet, le navigateur doit créer trois éléments :
La sécurité en JavaScript n'est pas à négliger car de nombreux exploits existent et sont assez facilement mis en place.
Avant de commencer à lire ce qui suit, il est important de savoir que le JavaScript est interprété du coté de la machine du client (et non pas du coté du serveur).


=== Pourquoi il ne faut pas faire confiance à Javascript si vous êtes propriétaire d’un site web ===
# La propriété argument
# La propriété niveau
# La méthode pour récupérer les infos sur le Tutoriel


Pour comprendre, il suffit de regarder cet exemple qui peut être trouvé sur le site de certains novices.
De ces trois éléments, la méthode est commune à toute instance de l’objet, car elle se limite à fournir les deux propriétés qui différencient les différents tutoriels. Pour éviter que cette méthode soit créée pour chaque instance, on peut exploiter la propriété « prototype » commune à tout objet. Cette propriété permet d’ajouter une propriété ou une méthode communes à toute instance du même objet. Dans le cas du tutoriel, on peut effacer la fonction printTutorielInfo() à l’intérieur de la fonction constructrice, et la déclarer en tant que méthode prototype :


Exemple :
<source lang="JavaScript">
function Tutoriel(argument, niveau) {
  this.argument = argument;
  this.niveau = niveau;
}


<syntaxhighlight lang="javascript">
Tutoriel.prototype.printTutorielInfo = function () {
  function Login(){
  return 'Tutoriel de niveau ' + this.niveau + ' sur ' + this.argument;
            var password=document.login.password.value;
}
            if (password=="kztYq8") {
var tutorielJavaScriptBase = new Tutoriel('JavaScript', 'intermédiare');
                window.location="bravo.htm";
var tutorielNodeJs = new Tutoriel('Node.js', 'avancé');
            }
            else
            {
                window.location="dommage.htm";
            }
        }
</syntaxhighlight>


Vous l'aurez compris, le mot de passe est défini en clair dans le code source de la page.  
console.log(tutorielJavaScriptBase.printTutorielInfo()); // --> Tutoriel de niveau intermédiare sur JavaScript
Tout le monde y a accès. L'URL censée être protégée par le mot de passe est aussi disponible et accessible sans le mot de passe!
console.log(tutorielNodeJs.printTutorielInfo()); // --> Tutoriel de niveau avancé sur Node.js
Ayez toujours en tête que ce que vous écrivez en javascript est accessible à tout le monde.
</source>


=== Vérifier du côté client et du côté serveur ===
Ce type de programmation à objets peut être très utile par exemple pour les jeux. Voici un exemple incomplet de comment un objet "Monster" pourrait se présenter. D'abord, on définit la fonction constructrice qui accepte trois paramètres: (1) le type de monstre, (2) sa position X, et (3) sa position Y:
Ce qu'on a vérifié du coté client avec le JavaScript n'est pas fiable et doit être revérifié du coté serveur (avec du PHP par exemple).
En effet, en désactivant simplement le JavaScript, on peut passer outre les contrôles d'un formulaire.


=== Attaques de Cross-site scripting (XSS) ===
<source lang="JavaScript">
Lors de la création d'une application ou d'un site avec JavaScript, il faut savoir que les attaques XSS existent et sont encore couramment utilisées.  
//Définir la fonction constructrice des Monstres, avec les éléments particuliers à chaque instance.
En résumé, l'attaque consiste à injecter des scripts dans la réponse d'une application, ce qui permet de récupérer les données sensibles de l'application et de les envoyer sur le serveur de la personne qui est à l'origine de l'attaque. Il existe deux types d'attaque XSS:
function Monster(name, x, y) {
  this.name = name;
  this.x = x;
  this.y = y;
}
</source>


'''La reflectected XSS (non permanente) :'''
Ensuite, on définit les propriétés et les méthodes communes à toute instance qui permettent de faire bouger le monstre et de le tuer. On crée également une fonction qui fournit des informations sur l'état du monstre à un certain moments dans le jeu:
L'attaquant injecte des scripts dans une application web pour que ceux-ci soient exécutés du coté client. L'attaque n'est pas stockée dans l'application et ne laisse aucune trace sur le serveur. Pour exploiter cette faille (XSS), l'ingénierie sociale doit être utilisée afin de tromper la "future" victime. L'attaquant va fournir une URL piégée à sa victime (via mail par exemple), lorsque la victime clique sur l'URL piégée, une requête contenant du code malicieux (scripts) est envoyé vers le serveur (officiel). Le code malveillant va alors s'exécuter sur la page renvoyé par le serveur (officiel), ce qui donne à l'attaquant le contrôle dessus. Celui-ci pourra ensuite, à partir de l'application, récupérer des données sur la victime, comme par exemple sa session ou ses cookies et les recevoir directement sur son serveur. Cela lui permettra de réaliser des actions au nom de l'utilisateur ou de lui voler des informations privées.


Exemple vidéo (anglais) : [https://www.youtube.com/watch?v=2b0VD4_rg8Q ICI]
<source lang="JavaScript">
//Définir les propriétés et les méthodes communes à toute instance d'un monstre.
Monster.prototype.health = 100;
Monster.prototype.isAlive = true;
Monster.prototype.isHit = function (damage) {
  this.health -= damage;
  if(this.health <= 0) {
    this.isAlive = false;
  }
}
Monster.prototype.moveUp = function () {
  this.y += 10;
}
Monster.prototype.moveDown = function () {
  this.y -= 10;
}
Monster.prototype.moveRight = function () {
  this.x += 10;
}
Monster.prototype.moveLeft = function () {
  this.x -= 10;
}
Monster.prototype.printInfo = function () {
  if(!this.isAlive) {
    return "Le " + this.name + " a été tué!";
  }
  return "Le " + this.name + " se trouve aux coordonnées [" + this.x + ":" + this.y + "] et il lui manque " + this.health + " avant de disparaître.";
}
</source>


'''La persistent XSS (permanente) :'''
Maintenant on peut simuler le jeu en créant deux monstres:
Contrairement au premier type d'attaque, celle-ci consiste à injecter le code malicieux directement dans le système de stockage de l'application Web. Pour que la faille puisse être exploitée, l'application doit générer ses réponses via ces données stockées. Elle est souvent utilisée sur des forums qui sont mal sécurisés. Ceux-ci stockent les messages des utilisateurs dans des bases de donnée. Si un message contient un code malicieux, à chaque fois qu'un utilisateur affichera la page du forum contenant le message qui présente le code malicieux, celui-ci sera exécuté. Cette attaque est donc beaucoup plus dévastatrice puisqu'elle touche potentiellement tous les utilisateurs.  
<source lang="JavaScript">
//Simulation du jeu avec deux monstres, un Dragon et un Goblin.
var firstMonster = new Monster('Dragon', 0, 0);
firstMonster.moveLeft();
firstMonster.moveUp();
firstMonster.isHit(50);
console.log(firstMonster.printInfo()); // --> Le Dragon se trouve aux coordonnées [-10:10] et il lui manque 50 avant de disparaître.


Exemple vidéo (anglais) : [https://www.youtube.com/watch?v=OVLz6RgOjIY ICI]
var secondMonster = new Monster('Goblin', 25, -15);
secondMonster.moveDown();
secondMonster.isHit(5);
console.log(secondMonster.printInfo()); // --> Le Goblin se trouve aux coordonnées [25:-25] et il lui manque 95 avant de disparaître.


====Comment se protéger contre les attaques XSS====
firstMonster.moveUp();
 
firstMonster.moveLeft();
Il existe plusieurs moyens de se protéger, la NSA a d'ailleurs rédigé un bon [https://www.nsa.gov/ia/_files/factsheets/xss_iad_factsheet_final_web.pdf document] à ce propos.
firstMonster.isHit(60);
 
console.log(firstMonster.printInfo()); // --> Le Dragon a été tué!
Afin d'éviter que des personnes malveillantes puissent injecter du code malveillant, les administrateurs réseaux doivent traiter les informations que les personnes envoient, une fois qu'elles sont parvenues au serveur et les retraiter lors de leur envoi au navigateur. Des fonctions PHP existent afin de traiter les données envoyées via JavaScript comme "htmlentities", qui convertit tous les caractères éligibles en entités HTML et strip_tags, qui suppriment les balises HTML et PHP d'une chaîne. L'une dans l'autre permet déjà une protection de base efficace (mais pas infaillible) contre ce genre d'attaque qui exploite le JavaScript. Des mesures supplémentaires peuvent être mises en place comme l'utilisation de pare-feux applicatifs qui détectent les informations suspectes envoyées au serveur. Du coté des utilisateurs, il ne faut jamais cliquer sur un lien dont la provenance est douteuse et toujours accéder aux sites via l'URL officielle. Ils peuvent aussi utiliser des extensions comme par exemple "NoScript" sur Firefox, qui offre une bonne protection de base contre ce genre de vulnérabilité.
</source>


=== Références ===
==Références==
* http://www.leblogduhacker.fr/la-securite-avec-javascript/
* Simpson, K. (2015). You Don’t Know JS: Up & Going. O’Reilly Media. Surtout chapitres 1 et 2. Disponible également en version gratuite (non éditée) [https://github.com/getify/You-Dont-Know-JS/blob/master/up%20&%20going/README.md#you-dont-know-js-up--going sous ce lien].
* https://fr.wikipedia.org/wiki/Cross-site_scripting
* Haverbeke, M. (2015). [http://eloquentjavascript.net/ Eloquent JavaScript. A modern Introduction to Programming]. Second Edition. San Francisco, CA: no starch press. Chapitres 1 à 10
* https://fr.wikipedia.org/wiki/Injection_de_code_dans_les_applications_web#Cross-site_scripting_.28XSS.29
* Mozilla Developer Network. [https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide Guide JavaScript]


[[Category: JavaScript]]
[[Catégorie:JavaScript]]
[[Category:Ressources STIC]]

Dernière version du 20 août 2024 à 11:14

Initiation à la pensée computationnelle avec JavaScript
Module: Références JavaScript ◀▬
◀▬▬▶
à finaliser intermédiaire
2024/08/20
Voir aussi
Catégorie: JavaScript

Introduction

Cette page propose un survol sur les éléments fondamentaux du langage JavaScript. Les notions présentées dans cette page sont valables pour tous les environnements dans lesquels un interprète du langage JavaScript est disponible, notamment :

Pour un aperçu général et plus théorique du langage, voir la page JavaScript. Pour des novices en programmation, voir d'abord l'introduction à la programmation.

Conseil de lecture

Cette page présente une grande quantité d'information en relativement peu d'espace. Elle explique principalement les fonctionnalités, mais sans un objectif bien spécifique, ce qui peut décourager surtout les novices. Nous conseillons de lire d'abord les sections Introduction et Syntaxe de JavaScript, et par la suite d'utiliser cette page comme référence croisée avec les pages :

Console JavaScript

Les exemples présentés dans ce tutoriel utilisent des éléments fondamentaux du langage et peuvent donc marcher dans tout environnement JavaScript. La manière la plus simple pour suivre/tester le code présenté est d'utiliser directement la Console JavaScript disponible dans un navigateur. Il suffit d'ouvrir la Console et de garder en même temps cette page ouverte :

  • Internet Explorer : Menu Outils > Outils de développement (ou F12)
  • Firefox : le scratchpad (SHIFT F4), sinon la console (F12) qui permet d'entrer une ligne.
  • Chrome : Menu Outils > Console JavaScript (ou F12)
  • Safari : D'abord dans les Options > Avancées cocher la case "Afficher le menu Développement dans la barre des menus", puis CTRL+Alt+I ou CTRL+Alt+C
  • Opera: Menu Page > Outils de Développement > Opera Dragonfly (ou CTRL+Shift+I)
Console des erreurs en Google Chrome

La console JavaScript est un endroit très utile pour tester du code JavaScript pour deux raisons :

  1. On peut saisir directement du code dans la console et l'évaluer. Dans l'image suivante, les lignes précédées par > sont des lignes avec du code, et les lignes précédées par <- proposent le résultat de l'évaluation du code.
    La console du navigateur évalue directement du code.
  2. On peut communiquer avec la Console JavaScript. Par exemple la notation console.log() permet d'écrire un message dans la Console. Pour ceux qui ont utilisé Flash, cette instruction est similaire à la fonction trace() de Flash. Voici un exemple :
    for(var i = 0; i < 5; i++) {
        console.log("Cycle actuel : " + i);
    }
    
    Le résultat de ce script dans la console JavaScript est le suivant :
    La méthode log() de l'objet Console permet d'afficher des messages dans la console JavaScript.

Syntaxe de JavaScript

JavaScript est un langage de scripting, il permet donc d'écrire des algorithmes qui sont évalués et exécutés par un interprète. (Pour être précis, l'interprète JavaScript est plutôt un hybride avec un compilateur "en temps réel", voir Simpson, 2015). Pour que l'interprète puisse comprendre le code source, il faut respecter les règles syntaxiques du langage JavaScript. Ces règles déterminent principalement deux aspects :

  1. Le code est-il valide?
    La présence d'erreurs syntaxiques/orthographiques dans le code source arrête l'exécution du script.
  2. Qu'est-ce que le code est censé faire?
    Le code source détermine la logique de l'application en termes de Input/Ouput.

Pour déterminer quel est l'objectif du code, l'interprète JavaScript lit le code (de gauche à droite, de haut en bas) et le transforme en instructions. Les instructions sont une suite d'expressions qui combinent des données et des algorithmes. Pour écrire des instructions que l'interprète puisse comprendre et exécuter, il faut combiner les éléments syntaxiques propres au langage : écrire du code source en JavaScript. De suite, nous proposons un premier aperçu sur les éléments principaux de la syntaxe JavaScript. Il ne s'agit que d'un survol pour identifier les éléments dans les exemples de code. Nous conseillons de tester directement le code dans votre console JavaScript pour une meilleure compréhension.

Syntaxe générale

JavaScript possède une syntaxe assez flexible par rapport à d’autres langages de programmation, mais il y a néanmoins certaines règles à respecter. De plus, le fait que JavaScript soit assez flexible ne signifie pas qu’un code bien structuré ne présente pas d’avantages ; au contraire, un code qui respecte une cohérence syntaxique de manière stricte sera plus simple à lire, à comprendre et à modifier par la suite. Voici quelques caractéristiques principales :

  • JavaScript est un langage « case sensitive », c’est-à-dire qu’il fait la distinction entre minuscules et majuscules. Le mot clé pour déclarer une variable (voir plus bas) sera donc var et non pas Var ou VAR ;
  • JavaScript ne fait pas différence entre un ou plusieurs espaces, et il est assez flexible avec les retours à la ligne ;
  • Pour délimiter une instruction de code (i.e. un statement) on termine avec un  ;
  • Pour délimiter un bloc de code, on utilise les parenthèses graphes { … } ; les blocs de code concernent notamment les structures de contrôle, les fonctions et les cycles/boucles (voir plus bas)

Commentaire

Un commentaire est une partie du code source qui n'est pas exécutée par l'interprète. Son utilité est donc exclusivement pour le(s) développeur(s), par exemple pour :

  • commencer à écrire en pseudo-code ce que le vrai code va faire par la suite
  • documenter le code pour d'autres personnes ou en tant que future référence
  • communiquer un aspect important ou signaler un problème à résoudre

Il existe deux manières de commenter le code JavaScript selon le nombre de lignes utilisées par le commentaire. Une seule ligne :

//Si le code est limité à une seule ligne (c'est-à-dire qu'il n'y a pas de retour à la ligne)

Plusieurs lignes :

/*
Si le code
est sur
plusieurs lignes
*/

Pour faciliter le repère de commentaires sur plusieurs lignes, on utilise souvent cette notation :

/*
 * Si le code
 * est sur
 * plusieurs lignes
*/

Tout ce qui se trouve dans un commentaire ne sera tout simplement pas pris en compte par l'interprète, donc les commentaires peuvent avoir une fonction descriptive, mais également représenter une manière pour désactiver une partie du code, ce qui peut être utile notamment en phase de test.

Variables

La déclaration d'une variable se fait de cette manière :

  1. Déclarer qu'il s'agit d'une variable avec l'élément var
  2. Choisir le nom de la variable (voir plus bas pour les règles)
  3. Attribuer une valeur avec le symbole d'affectation =

Voici quelques exemples:

var nomDeLaVariable = "Valeur de la variable";
var autreVariable = 'Autre valeur';
var variableChiffre = 100;
var variableDecimal = 3.14;

Le nom des variables doit observer les règles suivantes :

  • Ne peut pas être un mot réservé par le langage, voir une proposé par le site W3Schools
  • Peut se composer exclusivement de caractères alphanumériques (mais évitez les accents), underscore (_) et signe du dollar ($)
  • Le premier caractère ne peut pas être un chiffre

Exemples de noms acceptés :

//Exemples de variables correctes
var monWiki123 = "EduTechWiki";
var $monWiki123 = "EduTech Wiki";
var _____monWiki123 = "EduTechWiki";

Exemples de noms non acceptés :

//Exemples de variables non correctes
var 123wiki = "Faux";
var aujourd'hui = "Faux";

Même si ce n'est pas une règle, il est cependant de bonne pratique d'utiliser seulement des lettres sans accents, pour le nom des variables mais également en général.

Il est possible de déclarer une variable sans lui assigner une valeur. Dans ce cas la variable x sera "undefined" :

var x;

Lorsqu'on veut changer la valeur associée à une variable, on réutilise le même mécanisme d'association (ou affectation) sans l'élément var, qui sert juste pour la déclaration. Par exemple:

//Déclaration de la variable score
var score = 0;
//Modification de la variable avec association à une nouvelle valeur
score = 100;
//Modification de la variable avec modification par rapport à la valeur actuelle
score = score + 100; //score -> 200

La version ES6 de JavaScript (2015) a introduit deux alternatives pour déclarer des "conteneurs" symboliques qui peuvent être utilisés à la place de var. Il s'agit de :

  • let
  • const

let

Pour comprendre le fonctionnement de let il faudrait d'abord comprendre le fonctionnement du scope en JavaScript (voir plus bas dans la page). Pour l'instant on peut se limiter à définir let comme une manière de définir une variable seulement dans le bloc de code où elle a été déclarée.

La notation est la même que pour var :

let myScopeVar = "I am limited to this scope";
let n = 14;

const

Parfois on utilise des variables juste pour leur attribuer une valeur qui ne va jamais changer dans la logique de l'application, ce qui représente un contresens avec le mot même de "variable". Dans ce cas, il faudrait plutôt utiliser une constante, avec le mot clé const :

const gradeToPass = 4;
const secondsInAnHour = 60 * 60;

Si on essaie de changer la valeur d'une constante, le compiler de JavaScript va donner une erreur :

const gradeToPass = 4;
//On peut toujours essayer...
gradeToPass = 3; //--> ERROR!

Types de données

On peut associer différentes valeurs à une variable, on parle dans ce cas du type de données. En JavaScript, les types de données sont divisés en deux groupes :

  1. Les primitives : String, Number, Boolean, null et undefined
  2. Les objets : object, array et function

Voici quelques exemples de données primitives (les objets seront illustrés par la suite):

  • String : chaîne de caractères
    • var a = "Bonjour"
    • var b = 'Hello'
    • var c = "Il m'a dit \"Bonjour\" quand je l'ai vu";
      Si vous voulez utiliser des " à l'intérieur des " qui encadrent la valeur, il faut utiliser \ pour le mécanisme de escape
    • var d = 'Ajourd\'hui';
      Même principe que pour le "
    • var e = "Mais vous pouvez utiliser l'autre forme à l'intérieur sans problèmes";
      Dans ce cas on peut utiliser ' à l'intérieur de "...". L'inverse s'applique selon le même principe.
    • var f = "Pour faire apparaître un \\ il faut en mettre deux";
      Vue que le \ est le symbole de escape, si vous voulez l'afficher, il faudra en utiliser deux : le premier pour escape et le deuxième comme contenu.
  • Number : chiffres et décimales
    • var a = 12
    • var b = 3.14
    • var c = -12
      Les chiffres ne doivent pas être encadrés par des "...", si non ils devient des Stirng (voir plus bas)
  • Boolean : vrai/faux
    • var a = true
    • var b = false
      true et false toujours en minuscules et sans utiliser les "..." autour.
  • null et undefined : variables "vides"

Il est possible de tester le type d'une variable à travers la notation typeof suivi par la variable (ou valeur) :

typeof 3; //--> "number"
typeof "3"; //--> "string"
typeof true; //--> "boolean"

Contrairement à d'autres langages de programmation, les variables en JavaScript ne sont pas liées à un type de valeur spécifique. Il est tout à fait possible de définir une variable et lui associer d'abord une valeur de type "string" et par la suite de l'affecter à une valeur de type "number" ou à tout autre type de valeur.

//Le code suivant est tout à fait valide
var a = "Hello"; //--> a is a string
a = 100; //--> a is a number
a = false; //--> a is a boolean

Operateurs

Les opérateurs permettent de manipuler des valeurs, notamment de combiner des variables.

//Concaténation de texte
var a = "Hello";
var b = "world!";
console.log(a + " " + b); //Hello world!

//Opérateurs mathématiques
var a = 2 + 3; //5
var b = 10 - 5; //5
var c = 2 * 3; //6
var d = 9 / 3; //3

Il existe également une notation contractée qui permet de modifier la valeur de la même variable :

var a = 5;
a += 5; //--> a est égale à 10 maintenant, équivalent de a = a + 5;
a *= 10; //--> 100, équivalent de a = a * 10;
a -= 20; //--> 80, équivalent de a = a - 20;
a /= 8; //-->10, équivalent de a = a / 8;

Les opérateurs logiques NOT (!), AND (&&) et OR (||), ainsi que les opérateurs de comparaison (==, !==, ...) sont expliqués dans la partie plus approfondie sur les structures de contrôle.

Objets littéraux

Un objet littéral (la notion d'objet sera détaillée plus bas) est un élément qui se compose d'une ou plusieurs associations "clé-valeur" (key-value). On déclare un objet littéral de cette manière :

var monObjet = {
    key1: "value1",
    key2: "value2",
    key3: "value3"
}

Exemples:

var agesAmis = {Jean:20, Julie:25, Jan:23, Jolan:27};
var sexeAmis = {Jean:"homme", Julie:"femme", Jan:"homme", Jolan:"homme"};

On peut par la suite récupérer le contenu d'un objet à travers la notation monObjet.clé1, monObjet.clé2, etc. Exemple:

> agesAmis.Jean
20

Ce type de notation peut être utilisé également pour associer une valeur :

 monObjet.key1= "value1";

Avec l'exemple précédent :

 var agesAmis = {Jean:20, Julie:25, Jan:23, Jolan:27};
 agesAmis.Jean = 35;

Lorsqu'on récupère le contenu de la clé agesAmis.Jean, on obtiendra la nouvelle valeur associée :

> agesAmis.Jean
35

Dans le langage lui-même sont déjà présents des objets (i.e. built-in objects) qui disposent de leurs propres associations clés-valeurs. Par exemple lorsqu'on utilise Math.PI on accède à la clé "PI" de l'objet "Math". Cette clé correspond à la valeur 3.141592653589793. Math.PI est directement disponible dans le langage sans la nécessité de le définir. Veuillez cependant noter que, à différence des objets créés "manuellement", certains objets built-in n'acceptent pas que leurs propriétés soient modifiables. Voir la section dédiée aux objets en JavaScript pour plus de détails.

Array

Un array (tableau) est un groupe d'éléments qui disposent d'un index pour les mettre en ordre. L'index est associé automatiquement à partir de zéro.

var mesCours = ["STIC I", "STIC II", "STIC III", "STIC IV"];

On peut ensuite récupérer un élément en utilisant la syntaxe "[..]". mesCours[0] veut dire que l'on récupère le premier élément du array. Dans la plupart des langages de programmation, on commence à numéroter à partir de 0.

var STIC_I = mesCours[0];
var La_suite = mesCours[1];

Dans une console, on peut taper:

> STIC_I
"STIC I"
> La_suite
"STIC II"

Les arrays peuvent contenir tout type de données, mêmes des objets. Les arrays d'objets sont en effet des éléments très utiles pour faire des listes ou pour simuler des bases des données (lignes/colonnes). E.g.:

var students = [
  {
    name: "Student 1",
    email: "student1@tecfa.edu",
    status: "active"
  },
  {
    name: "Student 2",
    email: "student2@tecfa.edu",
    status: "active"
  }
];

console.log(students[0].email); //--> student1@tecfa.edu

Fonctions

Une fonction est une sorte de processus qui détermine un résultat final et le rend disponible, un schéma d'actions à accomplir. Une fonction est une première organisation du code et souvent on réutilise une fonction plusieurs fois dans le code. JavaScript permet de déclarer ses propres fonctions de cette manière :

function nomDeMaFonction() {
    //Processus de la fonction
}

Les fonctions peuvent accepter des arguments, c'est-à-dire des valeurs qui sont passés à la fonction. La fonction peut ensuite utiliser ces valeurs à l'intérieur de sa logique. Si on veut ajouter des arguments à la fonction, il faut les insérer dans les parenthèses et les séparer par des virgules (arg1, arg2, arg3). Par exemple la fonction suivante affiche à la console la valeur de "nom" passé en argument :

function afficheLeNom(nom) {
   console.log("Hello " + nom);
}

Pour exécuter cette fonction, il faudra donc l'utiliser de la manière suivante :

afficheLeNom("Batman"); //--> Hello Batman

Il arrive souvent qu'une fonction soit utilisée pour récupérer le résultat d'une computation et pouvoir l'utiliser dans la logique de l'application. On utilise à ce moment return. Voici un exemple qui utilise l'objet Date pour récupérer le temps actuel en heures et minutes :

function whatTimeIsIt() {
  var now = new Date();
  var formatDate = now.getHours() + ":" + now.getMinutes();

  //Return the result of the computation
  return formatDate;
}

var helloWithTime = "Hello there, it's " + whatTimeIsIt();
console.log(helloWithTime); //--> similaire à "Hello there, it's 10:12"

Structures de contrôle

Les structures de contrôle permettent d'exécuter du code si une ou plusieurs conditions s'avèrent vraies. Les conditions sont testées avec les éléments if, else if et else.

Utilisation simplement de if :

if (exp) {
  //Execute code ONLY if exp is true
}

Utilisation de if... else :

if (exp) {
  //Execute code ONLY if exp is true
} else {
  //Otherwise execute this part of the code
}

Complexifier avec l'ajout d'une else if (on peut en ajouter autant qu'on le souhaite, même si des chaînes trop longues sont difficiles à lire et à maintenir) :

if (exp1) {
  //Execute code if exp1 is true
} else if (exp2) {
  //Execute code if exp2 is true
} else {
  //Execute code if neither exp1 nor exp2 are true
}

Les structures de contrôle évaluent des expressions et déterminent si ces expressions sont vraies ou fausses. Pour ce faire, il y a une transformation (ou coercition) de tout type de valeur en valeur booléen. Voici les règles de coercition :

  • Une expression est fausse si sa valeur de retour est :
    • false
    • 0
    • null
    • undefined
    • NaN (Not a Number)
    • "" (empty string)
  • Une expression est vraie dans tous les autres cas, comme par exemple:
    • true
    • Tout chiffre (positive ou négative) différente de 0
    • Toute suite de caractères
    • Un objet
    • Un array
    • ...

Le code suivant affiche dans la console l'URL de la version du EduTech Wiki correspondante à la langue, ou affiche un message si la langue n'est ni français, ni anglais. Ci-dessous on parle français, mais vous pouvez changer...

 var lang = "Français" //  par exemple .....
 if(lang == "Français") {
     console.log("http://edutechwiki.unige.ch/fr/Accueil");
 } else if (lang == "Anglais") {
     console.log("http://edutechwiki.unige.ch/en/Main_Page");
 } else {
     console.log("EduTech Wiki n'est pas encore disponible dans votre langue!");
 }

Comme vous pouvez le voir, la variable lang est testée à l'aide de l'opérateur == qui détermine s'il y a correspondance entre la variable et la valeur. Les opérateurs de comparaison sont les suivants :

  • == détermine si les deux éléments sont similaires
  • != détermine si les deux éléments sont différents
  • >, >=, <, <= déterminent le rapport des éléments en fonction d'une échelle

Exemples :

var cours = "STIC I";
var credits = 6;

if(cours == "STIC I") {
  console.log("This is STIC I");
}

if (cours != "ERGO I") {
  console.log("This is not ERGO");
}

if (credits < 6) {
  console.log("You don't have all the required credits yet");
}

Boucles

Les boucles sont des éléments qui permettent de répéter un processus pour un nombre de fois établi (cycle for), ou jusqu'à ce qu'une certaine condition s'avère (cycle while).

La fonction for nécessite 3 arguments :

  • Une définition d'une variable d'entrée (point de départ de la boucle)
  • Une définition d'une variable de sortie (point final de la boucle)
  • Une définition de l'incrémentation de la variable à chaque passage

Voici un exemple de cycle qui aura lieu 20 fois :

for(var i = 0; i < 20; i++) {
   //code à exécuter à chaque fois
}

La notation i++ est un raccourci pour i = i + 1. Si vous voulez incrémenter votre itération avec plus d'une unité à la fois, il faudra utiliser donc la notation complète :

for(var i = 0; i < 50; i = i + 10) {
  console.log(i);
}

Depuis son introduction, dans les cycles de type for on utilise de préférence let au lieu de var :

for(let i = 0; i < 10; i++) {
   console.log(i);
}

Le cycle while évalue une condition et exécute le cycle jusqu'à ce que cette condition soit vraie. Ceci implique implicitement qu'un changement doit s'avérer à l'intérieur du cycle afin que cette condition soit fausse à un certain point, sinon le cycle ne s'arrêterait jamais. Voici le même résultat du cycle for vu plus haut dans le texte, mais avec la notation while :

var i = 0;
while (i < 20) {
    //code à exécuter à chaque fois
    i++;
}

La notation i++ à la fin du code ajoute une unité à la variable i, de cette manière la condition évaluée dans le cycle while sera fausse après 20 passages, et par conséquent le cycle while s'arrêtera. Il existe également la possibilité d'utiliser le cycle do... while qui contrairement au simple cycle while s'exécute au moins la première fois, même si la condition évaluée est fausse. Par exemple ce code affichera une fois la boîte d'alerte :

do {
    console.log("Une fois seulement");
} while (1 == 2);

La boucle for ... in permet de boucler sur les propriétés énumérables d'un objet.

var myObj = {x:20, y:30, nounours:40}; 
for (var chaine in myObj) { 
    console.log (chaine + "=" + myObj[chaine]); 
}

Donne:

x=20 
y=30
nounours=40

Attention: for ..in ne doit pas être utilisé pour des arrays pour lesquels l'ordre des indices est important, car l'ordre des itérations peut varier ou encore dit autrement, on ne sait pas quelle propriété sera choisie à quel moment...

La boucle for each ...in (JS 1.6) permettait d'itérer sur les valeurs des propriétés. Elle est replacée par l'instruction for ... of dans la dernière version 6 de ECMAScript). Cette dernière est plus versatile et parcourt tous les objets sur lesquels on peut itérer dans toutes les structures.

Comprendre JavaScript

Dans cette section nous proposons un survol des éléments clés qui permettent de comprendre le fonctionnement de JavaScript en tant que langage de programmation. Des éléments théoriques illustrés dans l'introduction à la programmation seront utilisés en fonction des particularités du langage.

Certains aspects abordés dans cette section son très abstraits et une compréhension immédiate n'est pas possible.

Pour une introduction plus souple et ciblée voir

Le code source

Grâce aux éléments de la syntaxe de JavaScript illustrés plus haut dans la page, il est possible de composer le code source d'un programme ou d'une application en JavaScript. JavaScript est un langage hybride qui est à la fois compilé et interprété : l'interprète JavaScript compile le code source juste avant son exécution (i.e. Just-In-Time Compilation). Cela signifie que tout le code JavaScript est d'abord lu, du haut vers le bas, et de gauche vers la droite, et compilé pour être ensuite exécuté. Ce mécanisme est assez complexe et pour bien le maîtriser, c'est-à-dire pour ne pas rencontrer des mauvaises surprises lors de l'écriture du code source, il est nécessaire de comprendre quelques principes.

Éléments symboliques et littéraux

Le code source en JavaScript se compose de deux types d'éléments :

  • Les éléments symboliques, représentés par les variables, les fonctions, etc.
  • Les éléments littéraux, représentés par des valeurs spécifiques associés surtout aux variables

Le code source est un mélange de deux types d'éléments. Voici un exemple :

var a = 10;
var b = a + 5;
var c = a + 5;

Dans ce simple bout de code, a est un élément symbolique qui est associé à une valeur littérale de type Number (10). Ensuite, b est un autre élément symbolique qui est associé à l'élément symbolique a (10 à ce moment) auquel on ajoute une autre valeur littérale de type Number (5). Enfin, c est un autre élément symbolique qui est affecté de la même manière que b

L'affectation des variables b et c présuppose que l'élément symbolique a existe déjà, ce qui est vrai dans ce cas, car on l'a déclaré et affecté à la valeur littéral 5 dans la première ligne. Si on modifie l'ordre des instructions, par contre, il se passe quelque chose de différent par rapport à ce que l'on pourrait s'attendre :

var b = a + 5;
var a = 10;
var c = a + 5;

Si on exécute ce bout de code, on peut s’apercevoir qu'on n'obtient pas un message d'erreur qui nous informe que a n'existe pas, mais si on demande quelle est la valeur de b, on obtient NaN (i.e. Not a Number), tandis que si on demande la valeur de c on obtient 15. Cela s'explique par un mécanisme de JavaScript appelé hoisting et qui détermine que la déclaration, mais pas l'affectation (i.e. l'association à une valeur, littéral ou symbolique), d'une variable est remontée aux début du code. Le deuxième bout de code est en réalité compilé de cette manière :

var b; //--> b est undefined
var a; //--> a est undefined
var c; //--> c est undefined
b = a + 5; //--> undefined + 5 --> NaN
a = 10;
c = a + 5; //--> 15

En d'autres termes, tous les éléments symboliques du code source (ou d'un scope, voir plus bas) sont déclarés au début du code compilé, n'importe à quelle ligne ils ont été définis dans le code source, mais leur affectation est effectuée en respectant l'ordre du code source.

Pour cette raison, et pour des raisons liées au scope illustré plus bas, il est de bonne pratique de déclarer et, si possible, affecter toujours les variables en haut du code :

  • en haut du script pour des variables ou constantes qui sont utilisé par tout dans la logique de l'application ;
  • en haut du bloc de code d'une fonction si elles sont utilisées seulement à l'intérieur de celle-ci.

Modification de l'état d'une application

Un autre aspect important dans la programmation est la distinction entre instructions qui modifient ou ne modifient pas l'état d'une application.

L'état d'une application (en anglais on utilise le terme state) concerne la valeur à un moment données de tout les éléments symboliques disponibles dans l'application.

Un exemple d'une instruction qui ne modifie pas l'état de l'application est la suivante :

5 + 5;

JavaScript sait interpréter cette instruction et renvoyer le résultat 10. Cependant, cette instruction n'a pas d'effet sur l'état de l'application car :

  1. Il n'existe pas d'éléments symboliques dans l'instruction ;
  2. Par conséquent, le résultat de cette instruction n'est pas stocké dans la "mémoire" du programme et n'apporte donc pas aucune différence par rapport à l'état actuel.

Par contre, si on insère des éléments symbolique dans le code, on peut créer des instructions qui modifient l'état de l'application et qui, par conséquent, peuvent entraîner des conséquences dans tous les endroits de l'application qui font référence à ces éléments symbolique :

var result = 5 + 5;

À ce moment nous avons :

  1. Déclaré une variable qui s'appelle result, ce qui a comme conséquence de stocker un élément symbolique dans la mémoire du programme ;
  2. Demandé à JavaScript d’exécuter l'addition 5 + 5 et de stocker le résultat dans l'élément symbolique result que nous avons défini ;

Imaginons que la variable result se réfère au résultat d'un quiz où il faut obtenir au moins 9 points pour passer à l'étape successive. Grâce au changement de l'état de cette variable, on peut imaginer d'autres changements conséquentes comme le changement du niveau de difficulté, l'obtention d'un badge de renforcement, etc.

On peut illustrer le concept de modification de l'état avec un exemple plus complexe qui utilise des arrays (i.e. des listes, voir également plus bas). JavaScript met à disposition la méthode sort() qu'on peut utiliser pour trier un array :

 var courses = ["STIC I", "ERGO I", "VIP I"];
 var firstCoursBeforeSort = courses[0]; //--> "STIC I"
 courses.sort();
 console.log(courses); //--> ["ERGO I", "STIC I", "VIP I"]
 var firstCourseAfterSort = courses[0]; //--> "ERGO I"

La méthode sort() a comme conséquence de modifier l'ordre des éléments, car après son exécution les éléments de l'array courses sont triés par ordre alphabétique.

Au contraire, la méthode join(), qui permet de faire une concaténation des éléments d'un array, ne change pas l'état de l'array :

 courses.join(); //--> "ERGO I,STIC I,VIP I"
 console.log(courses); //--> ["ERGO I", "STIC I", "VIP I"]

Si on voulait garder trace de la concaténation des éléments, il faudra donc utiliser un autre élément symbolique et l'affecter au résultat de la méthode join :

var coursesConcatenated = courses.join(); //--> "ERGO I,STIC I,VIP I"

Le scope

Pour comprendre le fonctionnement de JavaScript il faut comprendre le scope. Lorsque l'interprète JavaScript rencontre un élément symbolique (e.g. une variable) dans le code source, il faut qu'il sache à quel endroit aller pour récupérer sa valeur actuelle. Exemple :

var language = "PHP"
//No I changed my mind
language = "HTML5";
console.log(language); //The value must be looked up at line 3, not line 1
//I changed my mind once again
language = "JavaScript";
console.log(language); //The value must be looked up at line 6, not line 3 nor line 1

Dans cet exemple le mécanisme est assez simple parce que toutes ces variables appartiennent au même bloc de code. Mais dès qu'on utilise des éléments qui créent leurs propres blocs de code, les choses sont plus compliquées.

Le scope et les fonctions

Les variables que l'on définit à l'extérieur d'une fonction seront disponibles aussi à l'intérieur d'une fonction, mais les variables déclarées à l'intérieur d'une fonction seront disponibles seulement à l'intérieur de la fonction elle-même. Voici un exemple :

var dispoPartout = "Je suis disponible aussi dans les fonctions";

function logMesVariables() {
     var dispoIci = "Je suis disponible seulement dans cette fonction";
     console.log(dispoPartout);
     console.log(dispoIci);
}

logMesVariables(); //--> OK!, affiche les deux messages

console.log(dispoPartout); // OK!, le message de la variable dispoPartout sera affiché dans la console
console.log(dispoIci);// ERROR!, la variable dispoIci n'existe pas dans ce scope, elle est limitée à la fonction

L'image suivante montre le même principe de manière plus abstraite :

Les différentes scopes selon le "niveau" du code.

Une chose à laquelle il faut faire attention concerne le fait qu'une fonction JavaScript se "souvient" du scope dans lequel elle a été déclarée, quelque soit le scope dans lequel elle sera utilisée. Un exemple permettra de clarifier ce passage :

//Global scope
var country = "Switzerland";
var capital = "Bern";

function printCountry() {
  //Function scope
  console.log(country);
}

function printCountryAndCapital() {
  //Function scope
  var country = "Italy";
  var capital = "Rome";

  function printCapital() {
    console.log(capital);
  }

  printCountry();
  printCapital();
}

printCountryAndCapital();

/**
 * Output :
 * Switzerland
 * Rome
 */

On pourrait s'attendre que ce code donne "Italy" et "Rome", car les deux variables qui se trouvent à l'intérieur de la fonction printCountryAndCapital() ont ces valeurs. La différence concerne où les deux fonctions printCountry() et printCapital() ont été déclarées :

  • printCountry() a été déclarée dans le scope global et donc lorsqu'elle cherche une variable, elle la cherche dans le global scope où var country = "Switzerland"
  • printCapital() a été déclarée à l'intérieur du scope de la fonction printCountryAndCapital(), où var capital = "Rome"

Voici une représentation graphique qui explique ce principe :

JavaScript se "souvient" du scope dans lequel les variables et les fonctions ont été déclarées, ce qui peut provoquer des comportements inattendus si on ne comprend pas le principe.

Le scope et les variables : var vs. let

On peut comprendre le fonctionnement du scope également à travers la différence entre var et let illustrée dans cet exemple :

var everywhere = "I am a var";
let here = "I am a let";

console.log(everywhere, here); //--> I am a var & I am a let

if (true) {
    var everywhere = "I have changed";
    let here = "I have changed too";
}

console.log(everywhere, here); //--> I have changed & I am a let

La différence concerne le fait que var et let ont un effet différent à l'intérieur d'un autre bloc de code, dans ce cas un bloc de type if() :

  • var évalue le scope "supérieur" ou se trouve une autre variable avec le même nom et donc remplace sa valeur
  • let agit seulement sur le bloc de code dans lequel elle se trouve, et par conséquent crée une deuxième conteneur symbolique qui s'appelle "here", sans aucun lien avec le "here" du scope supérieur

Conversion de type de données

JavaScript est un langage non-typé, c'est-à-dire que chaque variable peut être associée à tout type de donnée. Pour cette raison, il est parfois nécessaire de modifier le type de donnée associé à une variable ou contrôler qu'une variable est associée à un type de donnée spécifique, par exemple être sûr que le score d'un jeu soit bien de type Number. La modification du type de données est surtout utile lorsque certains inputs sont déterminés directement par l'utilisateur, notamment dans le cadre de JavaScript côté client La modification du type de donnée est appelée conversion est peut se faire de deux manières :

  1. "Manuellement", à travers des fonctions (ou raccourcis) mis à disposition des développeurs par le langage ;
  2. Automatiquement par l'interprète JavaScript

La manière la plus sûre de faire une conversion est de la déclarer explicitement au niveau du code, cela permet d'éviter des conversions automatiques (voir plus bas) par JavaScript qui peuvent être assez difficiles à comprendre pour des néophytes. La conversion "manuelle" peut se faire de différentes manières, voici de suite quelques exemples :

De String à Number

Une des conversions les plus utiles est celle qui permet de passer d'une donnée de type String à Number. Cela permet d'éviter, par exemple, des comportements de ce type :

"3" + "9" //--> "39" (String)

On peut forcer le type de donnée en Number avec la fonction Number() :

Number("3") + Number("9") //--> 12 (Number)

Veuillez faire attention à ce que chaque chiffre doit être d'abord converti en Number, sinon on n'obtient pas le résultat attendu :

Number("3" + "9") //--> 39 (Number)

Un raccourci pour la conversion String -> Number consiste tout simplement à ajouter un + avant la valeur en String :

var a = "10";
var b = "5";
var c = +a + +b; //--> 15

D'autres manières pour passer de String à Number sont :

  • parseInt() qui permet de récupérer un chiffre entier depuis du texte : parseInt("1CHF") //--> 1.
  • parseFloat() qui permet de récupérer un chiffre décimal  : parseFloat("1.457cm"); //--> 1.457

Veuillez noter que cette fonction marche seulement si le string commence par un chiffre;

De Number à String

Parfois il est utile de passer d'un Number à un String. Pour une conversion simple, on peut utiliser String() :

String(100) //--> "100" (String)

Pour des conversions plus complexes (et utiles) il existe des méthodes qui peuvent être ajoutées à travers la notation par points (voir la section consacrée aux Objets plus bas dans cette page) :

var longDecimal = 123.456789
longDecimal.toFixed(1); //--> "123.5"
longDecimal.toFixed(2); //--> "123.46"
longDecimal.toFixed(5); //--> "123.45679"

Veuillez noter que ces méthodes n'affectent pas la valeur originale de la variable, c'est-à-dire que longDecimal sera toujours 123.456789.

Conversion en valeur Boolean

La conversion en valeur Boolean (i.e. true or false) est normalement faite de manière automatique, surtout dans le cadre des structures de contrôle (voir plus haut). On peut en tout cas forcer la conversion en utilisant Boolean() :

Boolean("STIC I"); //--> true
Boolean(0); //--> false

Un raccourcis, intéressant plutôt d'un point de vue logique que pratique, permet de transformer toute valeur en Boolean en utilisant la double négation :

var s = "STIC I";
var booleanS = !!s; //--> true

Conversion automatique

Si aucune instruction n'est donnée pour la conversion de type de données, JavaScript utilise des règles internes qui sont plutôt difficile à comprendre et que nous n'allons pas illustrer dans cette page. La conversion automatique a lieu en particulier dans deux conditions :

  1. Lorsqu'on utilise un opérateur pour associer deux données (ou plus) de types différents
  2. Lorsqu'on utilise des structures de contrôles qui transforment automatiquement des instructions ou des valeurs en Boolean (voir plus haut)

Voici quelques exemples de conversion automatique du premier type :

"10" + 10; //--> 1010 car le 10 est converti en String "10"
"10" - 10; //--> 0 car le "10" est converti en Number 10
"2" + true; //--> "2true" car le true est converti en String "true"
2 - true; //--> 1 car true est converti en Number 1
"10" * "10"; //--> 100 car les deux String "10" sont d'abord converties en Number 10
10 + [2,3]; //--> "102,3" car le Number 10 est converti en String "10" et l'array [2,3] en String "2,3"

Les structures de contrôle

Dans la partie sur la syntaxe, nous avons vu les aspects principaux des structures de contrôle avec un exemple if... else if... else. Dans cette section, nous allons approfondir ces aspects.

Vrai ou faux pour JavaScript

D'abord, nous allons approfondir ce qui est considéré vrai ou faux en JavaScript, notamment en relation avec les types de données et les transformations automatiques qu'on a vu dans la section "Comprendre JavaScript".

Pour montrer quelques exemples nous allons créer une fonction assert() qui évalue une expression et renvoie à la console un message "I am true" ou "I am false".

//Définir la fonction assert
function assert(exp) {
  //Contrôler si l'expression est vraie (équivaut à exp == true)
  if(exp) {
    console.log("I am true");
  } else {
    console.log("I am false");
  }
}

//Exemples
assert(true); //--> I am true
assert(false); //--> I am false
assert(0.0001); //--> I am true
assert(1 - 1); //--> I am false
assert({ name: "Student 1", email : "student1@tecfa.edu" }); //--> I am true
assert(null); //--> I am false
assert([]); //--> I am true
assert(""); //--> I am false
assert(" "); //--> I am true
assert(8 * "a"); //--> (NaN) I am false

Vous pouvez identifier dans cette liste l'utilisation de la notation ! (NOT) pour définir la négation. Le ! peut être utilisé également pour transformer une valeur dans son contraire suivant les règles de conversion booléenne décrites plus haut.

!true; //--> false
!false; //-->true
!6; //--> false
!0; //--> true

Voici quelques exemples (faites attention au fait qu'un chiffre entre guillemets devient une suite de caractères) :

  • 6 == 6 //--> true
  • 6 == "6" //--> true
  • 6 === "6" //--> false
  • 6 != "6" //--> false
  • 6 !== "6" //--> true
  • 6 === !6; //--> false
  • 6 !== !6 //--> true
  • "a" < "b" //--> true
  • "A" < "a" //--> true
  • "B" < "a" //--> true
  • 1 > "A" //--> false

Tester plusieurs conditions à la fois

Parfois il est nécessaire de tester plusieurs conditions à la fois, c'est-à-dire que plus d'une condition doivent s'avérer vraies au sein du même test. Pour ce faire, on utilise les opérateurs logiques :

  • && équivaut à ET (AND) : implique que les deux conditions liées par cet opérateur soient vraies
  • || équivaut à OU /OR) : implique qu'au moins une des deux conditions liées par cet opérateur soit vraie

Il ne faut pas confondre les opérateurs logiques && et || (double) avec les opérateurs "bitwise" & et | (simple), dont l'utilisation n'est pas illustrée dans cette page.

Voici quelques exemples :

 if(mois == "décembre" && jour == 25) {
     console.log("C'est Noël");
 }

 if(jour == "samedi" || jour == "dimanche") {
     console.log("C'est le weekend!");
 }

Utiliser switch

Lorsque les conditions à tester sont plusieurs, au lieu d'utiliser plusieurs if, else if et else, on peut utiliser le cycle switch :

 switch( lang ) {
     case "Français":
     console.log("http://edutechwiki.unige.ch/fr/Accueil");
     break;

     case "Anglais":
     console.log("http://edutechwiki.unige.ch/en/Main_Page");
     break;

     default:
     console.log("EduTech Wiki n'est pas encore disponible dans votre langue!");
 }

Le command break est nécessaire afin d'arrêter l'exécution du code pour la condition.

Les fonctions en JavaScript

Comme on l'a vu brièvement dans la syntaxe de base, les fonctions sont des ensembles d'instructions qui forment un processus. Toutes les instructions qui se trouvent à l'intérieur de la fonction seront exécutées lorsque la fonction sera utilisée. La "vie" d'une fonction se caractérise par deux phases :

  • Une phase de définition dans laquelle le fonctionnement interne de la fonction est établi (i.e. ce que la fonction est censée faire)
  • Une phase d'invocation (i.e. d'utilisation) de la fonction dans un contexte où son fonctionnement interne est utile à la logique de programmation

Il existe néanmoins la possibilité en JavaScript de combiner les deux phases, dans ce cas on parle de fonction anonyme ou immédiate (voir plus bas dans la section).

Définition d'une fonction

Pour définir une fonction il faut la nommer. On peut définir une fonction une seule fois, donc chaque fonction doit avoir un nom unique. La syntaxe pour définir une fonction est la suivante :

function nomDeLaFonction([arguments optionnels]) {
    //Instructions
}

Il existe une syntaxe alternative pour déclarer une fonction à travers une variable:

var maFonction = function([arguments optionnels]) {
   //Instructions
}

Les deux types de déclarations sont pratiquement équivalent, si ce n'est pour quelques détails très techniques.

Une fonction accepte entre zéro et plusieurs arguments. Les arguments sont des références à des valeurs externes passées à la fonction pour être utilisées à l'intérieur. Si la fonction nécessite plusieurs arguments, il faudra les séparer par une virgule.

Invocation d'une fonction

Pour invoquer une fonction, c'est-à-dire exécuter les instructions contenues à l'intérieur de la fonction à un moment donné dans le code, il faut simplement écrire le nom de la fonction et éventuellement passer les arguments nécessaires à son fonctionnement interne.

nomDeMaFonction([arguments optionnels]);

Voici quelques exemples de déclaration et invocation:

 //Déclaration
 function printCoursName() {
   console.log('STIC I');
 }
 //Invocation
 printCoursName(); //--> STIC I dans la console

 //Déclaration
 var printCoursGrade = function() {
   console.log(6);
 }
 //Invocation 
 printCoursGrade(); //--> 6 dans la console


Arguments dans une fonction

Les fonctions de JavaScript acceptent des arguments (i.e. paramètres) qui sont optionnels. Ces arguments sont utilisés à l'intérieur du corpus de la fonction. Il y a deux manières pour récupérer un argument à l'intérieur de la fonction :

  1. L'argument est spécifié dans la définition de la fonction et à l'intérieur il est utilisé avec le nom de la référence
  2. L'argument n'est pas spécifié dans la définition et il est récupéré grâce à l'array arguments qui associe un index à partir de 0 à chaque argument passé par référence

Voici un exemple pour chaque modalité :

 //1.
 function additionWithArguments(a, b) {
     console.log(a + b);
 }
 //2.
 function additionWithoutArguments() {
     console.log(arguments[0] + arguments[1]);
 }

 //L'invocation est similaire pour les deux cas
 additionWithArguments(5, 5); //--> 10
 
 additionWithoutArguments(10, 10); //--> 20

La deuxième méthode est particulièrement utile si on ne sait pas à l'avance combien d'arguments seront passés à une fonction. Par exemple on peut configurer notre fonction addition() afin qu'elle calcule la somme des arguments indépendamment de leur nombre :

 function addition() {
     var numArgs = arguments.length;
     var total = 0;
     for(var i=0; i < numArgs; i++) {
          total += arguments[i];
     }
     console.log(total);
 }
 addition(11,23,45,21,97); //--> 197

Retour d'une fonction

Les instructions d'une fonction sont censées aboutir à un certain résultat qui peut être une action, par exemple afficher un message à la console, mais également fournir le résultat d'une manipulation des données dans l'endroit du code où cette fonction a été invoquée. Pour renvoyer un résultat on utilise l'instruction return. Cette instruction détermine que la fonction a exécuté son "rôle" et que le processus à son intérieur est terminé.

 function addition(a, b) {
     var total = a + b;
     return total;
 }

Cette fonction renvoie le résultat d'une addition entre les deux arguments de la fonction. On peut utiliser plusieurs notations return dans la même fonction, par exemple dans le cadre d'un cycle conditionnel. On exploite dans ce cas le fait que cette instruction termine l'exécution du code à l'intérieur d'une fonction.

 function controlerMoyenne(note) {
     if(note < 4) {
          return;
     } 
     console.log("Yeah!!");
 }
 controlerMoyenne(4.5); //--> Yeah!! s'affiche
 controlerMoyenne(3.75); //--> Pas de Yeah!!

Le "return" d'une fonction est généralement utilisé pour que la valeur renvoyée soit intégrée dans la logique de l'application, par exemple en tant qu'affectation d'une variable :

//Définition d'une fonction d'addition
 function addition(a, b) {
     var total = a + b;
     return total;
 }

var totalPointsUser = addition(addition(23, 25), addition(21, 30));
var totalPointsComputer = addition(addition(27, 20), addition(25, 25));

//Guess who won ;) 
if(totalPointsUser > totalPointsComputer) {
  console.log("You won!");
}

Les fonctions récursives

Il arrive parfois que pour solutionner un problème, le programmeur doive créer une fonction que l'on appelle récursive. Il est possible de programmer une fonction récursive dans presque tous les langages de programmation, donc en Javascript aussi.

Qu'est-ce qu'est une fonction récursive ?

Il s'agit d'une fonction qui s'appelle elle-même. C'est à dire, dans le corps de la fonction, on fait appel à cette même fonction. Résoudre un problème par la récursivité est particulièrement adapté lorsque le problème en question peut se découper en "sous problèmes".

Ci-dessous un exemple permettant de calculer une suite de Fibonacci à l'aide d'une fonction récursive :

function fibo(n){
  if (n < 2) return n; // cas simple
  return fibo(n-2) + fibo(n-1); // cas complexe - gestion du sous-problème
 }

En principe, une fonction récursive à toujours la même structure. On gère en premier lieu le cas simple qui ne nécessite pas l'appel de la fonction. Ensuite, on gère le ou les sous-problème(s) plus complexe, en appelant la fonction elle-même.

Les fonctions de callback

Une fonction de callback est une fonction qui est passée en tant qu'argument d'une autre fonction et qui reçoit de cette fonction un ou plusieurs arguments. De manière sémantique, on peut qualifier une fonction de callback de la manière suivante : lorsque la fonction A a été exécutée et donne le résultat X, exécute la fonction B avec l’argument X. Pour obtenir ce processus, la fonction B est passé en tant qu’argument de la fonction A. Voici le code :

//Déclaration de la fonction principale (A)
function A(callback) {
  //Produire un résultat X
  var X = 100;
  //Invoquer la fonction de callback avec l'argument X en paramètre
  callback(X);
}

//Déclaration de la fonction de callback (B)
function B(X) {
  console.log(X);
}

//Utilisation des deux fonctions A et B (en callback)
A(B); //--> 100 à la console

On peut imaginer d'ajouter une troisième fonction C(X) à cet exemple pour montrer une autre fonction de callback :

//Déclaration de la fonction principale (A)
function A(callback) {
  //Produire un résultat X
  var X = 100;
  //Invoquer la fonction de callback avec l'argument X en paramètre
  callback(X);
}

//Déclaration de la fonction de callback (B)
function B(X) {
  console.log(X);
}

//Déclaration de la fonction de callback (C)
function C(X) {
  console.log(X + 100);
}

//Utilisation des deux fonctions A et B (en callback)
A(B); //--> 100 à la console
A(C); //--> 200 à la console

Dans cet exemple, le recours à une fonction de callback n'est pas très utile, car on pourrait obtenir le même résultat de manière plus simple. Toutefois, cet exemple montre le principe fondamental des fonctions de callback : le fait qu’elles sont exécutées à un moment donné dans l’exécution d’une autre fonction. Pour cette raison, les fonctions de callback sont souvent utilisées lorsqu’on ne peut pas, à l’avance, déterminer à quel moment se termine l’exécution d’une autre fonction. Ce principe est à la base de la programmation asynchrone, car l’exécution du code dépend du déclenchement d’une autre fonction qui est faite de manière décalée. On utilise souvent les fonctions de callback avec les requêtes asynchrones de type « AJAX » qui permettent notamment d’obtenir des informations d’une autre page, à travers une requête http, sans que la page principale soit mise à jour. Dans ce cas, la fonction de callback est utile pour déterminer qu’est-ce qu’il faut faire avec le contenu récupéré de manière asynchrone, lorsqu’il sera disponible. Voici le mécanisme d'une fonction de callback (sans le code AJAX):

//Déclaration de la fonction principale
function getInfoFromInternet(successCallback, errorCallback) {
  data = //Get some data from another page, e.g. a JSON object
  if(data) {
    successCallback(data);
  } else {
    errorCallback(error)
  }
}

//Définition de deux fonctions qui sont utilisées en callback
function populateDOM(data) {
  //Do something with the data, e.g. populating the DOM
}

function showError(error) {
  //Do something with the error, e.g. pop up an alert
}

//Invocation de la fonction principale avec callbacks
getInfoFromInternet(populateDOM, showError);

Fonctions à exécution immédiate (IIFE)

Un dernier type de fonction que vous pouvez rencontrer dans du code JavaScript concerne les fonctions à exécution immédiate, ou Immediately-invoked function expression (IIEF). Comme le nom l'indique, il s'agit de fonctions qui sont exécutées directement lorsqu'elles sont déclarées. On utilise souvent cette notation pour éviter des conflits de scope (voir plus haut), car toutes les variables et fonctions déclarées à l'intérieur d'une IIFE sont limitées au scope de la fonction.

Il y a différentes manières pour écrire une IIFE (voir par exemple la page sur les IIFE sur Wikipedia). Voici l'une des plus utilisées:

(function () {
    //Contenu de la IIFE 
    console.log("Immediate")}
)();

Les fonctions liées au temps

JavaScript permet également d'exécuter du code en fonction du temps, plus spécifiquement grâce aux fonctions :

  • setTimeout() permet d'exécuter du code une seule fois après une période de temps définie ;
  • setInterval() permet d'exécuter du code à des intervalles reguliers de temps.

setTimeout()

La syntaxe pour utiliser la fonction setTimeout() est la suivante :

setTimeout(function,milliseconds, [param1,param2,...]);

Les paramètres sont optionnels, tandis que la fonction à exécuter et le temps en millisecondes sont obligatoires. Voici un exemple qui affiche un message dans la console après 5 secondes (i.e. 5 * 1000 milliseconds) :

var afficherApres5seconds = setTimeout(function () { 
  console.log("Message"); 
}, 5000);

Il est également possible de définir d'abord une fonction et ensuite passer son nom comme référence dans la fonction setTimeout() :

function printMessage() {
  console.log("Message");
}
var afficherApres5seconds = setTimeout(printMessage, 5000);

Associer la fonction setTimeout() à une variable est utile si on veut annuler l'exécution de la fonction avant que la période de temps définie avec la notation :

clearTimeout(variable);

En ajoutant cette ligne de code à l'exemple précédent, la fonction alertMessage() ne sera pas déclenchée :

function printMessage() {
  console.log("Message");
}
var afficherApres5seconds = setTimeout(printMessage, 5000);
clearTimeout(afficherApres5seconds);

setInterval()

La fonction setInterval est similaire à setTimeout() si ce n'est pour le fait que le code sera exécuté chaque X millisecondes. La syntaxe reste par contre la même :

setInterval(function,milliseconds, [param1,param2,...]);

Voici un exemple qui affiche dans la console un message chaque 3 secondes (sans arrêt si la page ne sera pas fermée ou après changement de URL) :

var chaque3seconds = setInterval(function () { 
  console.log("...encore 3 seconds"); 
}, 3000);

Pour limiter les cycles on peut utiliser un conteur et utiliser la fonction clearInterval directement à l'intérieur de la fonction invoquée par setInterval() :

var count = 0;
var cinqFois = setInterval(function () {
 count++; 
 console.log(count);
 if(count == 5) {
   clearInterval(cinqFois);
 }
}, 2000);

Arrays en JavaScript

Les arrays (ou tableaux en français) sont des éléments très utilisés en programmation, c'est pourquoi JavaScript met à disposition des propriétés et méthodes spécifiques pour les manipuler. Rappelons d’abord qu’un array est une liste indexée d’éléments. Ces éléments peuvent être de tout type : des suites de caractères, des chiffres, mêmes des objets, des fonctions ou d’autres arrays (dans ce cas on aura donc des arrays emboités). JavaScript permet de mixer différents types de données à l’intérieur du même array, voici un exemple :

var mixed = ['Hello', 3, true, { name: "Student 1", email: "student1@tecfa.edu"}, [1, 2, 3, 4]];

Pour faciliter la lecture d'un array on peut utiliser des espaces et des retours à la ligne :

var mixed = [
  "Hello",
  3,
  true,
  {
    name: "Student 1",
    email: "student1@tecfa.edu"
  },
  [
    1,
    2,
    3,
    4
  ]
];

En termes d'indexes cet array correspond à:

  • mixed[0] --> "Hello"
  • mixed[1] --> 3
  • mixed[2] --> true
  • mixed[3] --> Object {name: "Student 1", email: "student1@tecfa.edu"}
  • mixed[4] --> [1, 2, 3, 4]

Veuillez noter que dans les cas des deux derniers éléments de cette array, on peut enchaîner la notation pour identifier des éléments à l'intérieur respectivement d'un objet ou d'un array emboîté:

  • Objet: mixed[3].name --> "Student 1"
  • Array emboité : mixed[4][0] --> 1

On peut modifier le contenu d'un array en associant à un index donné une nouvelle valeur :

var a = [10,20,30,40];

a[1] = 25;
a[3] = 50;

console.log(a); //--> [10, 25, 30, 50]

On peut utiliser cette notation également pour ajouter des éléments à un array. Si l'index que nous spécifions est plus grand du dernier index existant, l'array sera rempli d'éléments "undefined" jusqu'à l'index spécifié :

//Définir un array avec 2 éléments
var a = [10, 20];

//Ajouter un troisième élément, donc à l'index 2
a[2] = 30;

console.log(a); //--> [10, 20, 30]

//Ajouter un élément à un index supérieur à 3 (qui serait le "next in line")
a[4] = 100;

console.log(a); //--> [10, 20, 30, undefined × 1, 100]

Veuillez cependant noter qu'il existe des méthodes plus flexibles pour manipuler les arrays (illustrés par la suite).

Itération dans les Arrays

En tant que liste indexée, il est souvent utile de pouvoir récupérer tous les éléments de la liste l’un après l’autre : on parle dans ce cas d’itération. Il existe plusieurs méthodes pour itérer un array en JavaScript. L’un des plus fréquents correspond à l’utilisation d’un cycle for avec une variable qui détermine :

  1. La condition d’entrée qui correspond à 0 car les indices commencent à partir de ce chiffre ;
  2. Une condition de sortie, qui correspond au nombre d’éléments contenu dans l’array. On peut récupérer cette information grâce à la propriété .length
  3. Une condition d’incrémentation de la variable qui est tout simplement un incrément de +1 car les indices des arrays sont automatiquement séquentiels.

Voici un exemple :

var a = ["STIC I", "STIC II", "STIC III", "STIC IV"];

for(let=0; i< a.length; i++) {
  console.log(a[i]);
}

Veuillez faire attention au fait que la condition de sortie du cycle est < et non pas <=. Cela est dû au fait que les indices des arrays commencent à 0. Donc le cycle for doit s'arrêter à length - 1. Autrement dit, dans le cas de l'array d'exemple qui contient 4 éléments :

  • a.length = 4
  • Les indices seront donc a[0], a[1], a[2], a[3]
  • Le cycle for doit partir à 0 et s'arrêter à 3, c'est à dire à i < a.length

JavaScript met également à disposition une méthode associé directement aux array pour l'itération, la méthode forEach(). Cette méthode accepte comme argument une fonction de callback (voir plus haut dans la page) à laquelle sont passés trois arguments :

  1. La valeur de l'élément courant dans le cycle d'itération
  2. L'index de l'élément courant dans le cycle d'itération
  3. L'array lui-même qui est itéré

Voici un exemple :

//Définir un array
var a = ["STIC I", "STIC II", "STIC III", "STIC IV"];

//Définir une fonction qui sera utilité en tant que callback, veuillez noter qu'on n'est pas forcé à utiliser les 3 arguments
function doSomething(element, index) {
  console.log("The element with index " + index + " has the following value: " + element);
}

//Invoquer l'itération
a.forEach(doSomething);

Le résultat à la console sera le suivant:

The element with index 0 has the following value: STIC I
The element with index 1 has the following value: STIC II
The element with index 2 has the following value: STIC III
The element with index 3 has the following value: STIC IV

Parfois l'itération dans un array peut servir pour transformer les éléments de l'array selon un algorithm donné. On utilise dans ces cas la méthode map() qui accepte une fonction de callback avec les mêmes arguments de la méthode forEach(). La différence consiste dans le fait que la fonction map() transforme chaque élément passé à travers la fonction de callback. Voici un exemple qui transforme un array de note sur base 6 en notes sur base 20 :

//Définir les notes sur base 6
var grades_6 = [4.5, 5.25, 3.75, 6, 4.75, 5.5];

//Définir la fonction qui transforme les notes en base 20
function transform20(element) {
  return Math.round(element * 20 / 6);
}

//Obtenir un array avec toutes les notes en base 20
var grades_20 = grades_6.map(transform20);

console.log(grades_20); //--> [15, 18, 13, 20, 16, 18]

Ajouter/enlever des éléments d'un Array

Une autre fonctionnalité très utile avec la liste consiste dans la possibilité d'ajouter ou enlever des éléments. Pour ce faire, JavaScript met à disposition différents méthodes :

  • push() : ajoute un élément à la fin d'une liste
  • pop() : enlève le dernier élément d'une liste
  • unshift() : ajoute un élément au début d'une liste
  • shift() : enlève le premier élément au début d'une liste

Voici quelques exemples de manipulations :

var a = ["STIC I", "ERGO I", "VIP I", "COMEL I"];

//Ajouter le cours BASES à la fin de l'array
a.push("BASES"); //--> retourne 5, le nouveau nombre d'éléments contenus

console.log(a); //--> ["STIC I", "ERGO I", "VIP I", "COMEL I", "BASES"];

//Ajouter le cours "METHODO" au début de la liste
a.unshift("METHODO"); //-> retourne 6, le nouveau nombre d'éléments contenus

console.log(a); //--> ["METHODO", "STIC I", "ERGO I", "VIP I", "COMEL I", "BASES"];

//Enlever le dernier cours de la liste
a.pop(); //--> retourne "BASES", la valeur de l'élément enlevé

//Enlever le premier cours de la liste
a.shift(); //--> retourne "METHODO", la valeur de l'élément enlevé

console.log(a) //--> on est révenus à l'array initiale ["STIC I", "ERGO I", "VIP I", "COMEL I"]

Veuillez noter que ces types de manipulations mettent automatiquement à jour la liste des indices dans l'array, e.g. :

var a = ["STIC II", "STIC III"];

console.log(a[0]); //--> "STIC II";

//Ajouter un élément au début de la liste
a.unshift("STIC I");

console.log(a[0]); //--> "STIC I";
console.log(a[1]); //--> "STIC II";

En considération du fait qu'un array en JavaScript peut contenir tout type de données, la méthode push() peut être utilisée pour ajouter des objets à un array. Voici un exemple :

//Définir un array vide
var students = [];

//Définir une fonction qui ajoute un nouveau étudiant à l'array
function addStudent(name, email, status) {
  //Créer un nouveau objet avec les valeurs passées en tant qu'arguments
  var newStudent = {
    name : name,
    email : email,
    status : status
  };
  //Ajouter l'objet à l'array
  students.push(newStudent);
}

//Ajouter un étudiant
addStudent('Student 1', 'student1@tecfa.edu', 'active');

console.log(students) //--> Un élément dans l'array;

//Ajouter un autre étudiant
addStudent('Student 2', 'student2@tecfa.edu', 'active');

console.log(students) //--> Deux éléments dans l'array;

Il existe également la méthode splice() qui permet de faire des manipulations à tout endroit dans la liste (pas seulement au début ou à la fin). Voir la documentation MDN pour plus de détails : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

Autres manipulations utiles

Les méthodes mises à disposition de JavaScript pour manipuler des arrays sont nombreuses, vous pouvez vous référez à la documentation MDN pour une liste exhaustive et très technique (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) ou à la liste W3School (http://www.w3schools.com/jsref/jsref_obj_array.asp). De suite nous illustrons quelques méthodes qui pourraient être utiles de manière générale.

  • join()

Cette méthode permet de joindre des éléments d'un array dans une suite de caractères avec un élément de séparation qui peut être spécifié. Si aucun élément de séparation n'est spécifié, les éléments seront séparés par une virgule e.g. :

var a = ["STIC I", "STIC II", "STIC III", "STIC IV"];

console.log(a.join()); //--> STIC I,STIC II,STIC III,STIC IV
console.log(a.join(", ")); //--> STIC I, STIC II, STIC III, STIC IV
console.log(a.join("___")); //--> STIC I___STIC II___STIC III___STIC IV
  • filter()

Cette méthode permet de déterminer dans une liste quels sont les éléments qui respectent un certain critère, donné par une fonction de callback. Dans l'exemple suivant nous allons créer un nouveau array qui inclut exclusivement les notes suffisantes (>= 4) d'un élève.

//Liste de toutes les notes
var grades = [4, 3.75, 2.5, 5.5, 6];

//Définir la fonction de filtre
function isEnough(element) {
  return element >= 4;
}

//Liste des notes suffisantes
var gradesGt4 = grades.filter(isEnough);

console.log(gradesGt4); //--> [4, 5.5, 6]
  • every()

Cette méthode permet d'évaluer si tous les éléments dans une liste respectent ou pas un critère donné par une fonction de callback. Cette fonction retourne true si tous les éléments respectent le critère ou false si au moins un élément ne respecte pas. Dans cet exemple on peut évaluer si un élève n'a reçu que des notes suffisantes (>= 4).

//Définir la liste des notes
var grades = [4, 4.25, 5.5 , 6, 5.25, 4.75, 4.5];

//Définir la fonction pour le critère
function isEnough(element) {
  return element >= 4;
}

//Définir si l'élève n'a que des notes suffisantes
if(grades.every(isEnough)) {
  console.log("Congratulations!");
} else {
  console.log("You have at least one exam to retake");
}

Le résultat de cet exemple sera "Congratulations!" car toutes les notes de l'array grades sont >= 4. La méthode some() est similaire, si ce n'est pour le fait qu'elle sera true si au moins un élément respecte le critère de la fonction de callback.

  • sort()

Cette méthode permet de trier les éléments d'un array. Elle accepte en option une fonction de callback qui permet de déterminer le critère pour trier les éléments. Si aucune fonction n'est passé, le trie sera fait selon le critère de grandeur selon lequel 1 < 2, a < b, A < a, etc. Exemple:

var a = [1, "Banana", 3, "apple", 0.5];

console.log(a.sort()); //-> [0.5, 1, 3, "Banana", "apple"]

Si, par contre, on veut créer des critères de classement plus complexes, nous allons exploiter le fait que cette fonction accepte deux paramètres a et b qui représentent deux éléments de l'array à comparer. La méthode sort() va automatiquement faire toutes les comparaisons possibles entre les éléments de l'array et détermine l'ordre selon la valeur retournée par la fonction de comparaison :

  • Si la valeur retournée est mineur de 0, alors a < b
  • Si la valeur retournée est égale à 0, alors a == b
  • Si la valeur retournée est majeur de 0, alors a > b

Voici un exemple: imaginons un concours dans lequel on demande aux participants de deviner le nombre de cantons en Suisse (y compris le 1/2 cantons). On veut donc trier les réponses en fonction qu'elles s'approchent le plus du chiffre 26. Pour ce faire on compare la différence absolue entre 26 et a avec la différence absolue entre 26 et b :

//Définir les réponses
var r = [21, 44, 26, 29, 6, 15, 26, 3];

//Définir la fonction de classification
function compare(a, b) {
  return Math.abs(26 - a) - Math.abs(26 - b);
}

console.log(r.sort(compare)); //--> [26, 26, 29, 21, 15, 44, 6, 3]

On aurait pu écrire la même fonction de comparaison de la manière suivante :

function compare(a, b) {
  var diff_a = Math.abs(26 - a);
  var diff_b = Math.abs(26 - b);

  if(diff_a < diff_b) {
    return -1;
  } else if (diff_a == diff_b) {
    return 0;
  } else {
    return 1;
  }
}

On peut utiliser la fonction de comparaison même avec des arrays d'objets. Imaginons l'exemple précédente avec le nom du participant associé à sa réponse :

//Définir les réponses des participants
var r = [
  {
    name : 'Participant 1',
    guess : 21
  },
  {
    name : 'Participant 2',
    guess : 26
  },
  { 
    name : 'Participant 3',
    guess : 12
  }
];

//Modifier la fonction de comparaison pour prendre en compte juste la propriété guess de l'élément
function compare(a, b) {
  return Math.abs(26 - a.guess) - Math.abs(26 - b.guess);
}

//Utiliser une fonction pour imprimer les résultats
function printResult(element, index) {
  var rank = index + 1;
  console.log(rank + ". " + element.name + " with answer " + element.guess);
}

//Imprimer l'ordre des participants en utilisant la fonction forEach()
r.sort(compare).forEach(printResult);

Le résultat à la console sera le suivant :

1. Participant 2 with answer 26
2. Participant 1 with answer 21
3. Participant 3 with answer 12
  • map()

La méthode map() permet de transformer tous les éléments d'un array à travers la même fonction, sans modifier l'array original.

var originalArray = [1,2,3,4,5,6];

var transformedArray = originalArray.map(function(element) {
  return element * 10;
});
//Transformed array -> [10, 20, 30, 40, 50, 60]
  • indexOf()

La méthode indexOf(search) cherche s'il existe un élément qui correspond à l'argument. S'il le trouve, la méthode renvoie le numéro de l'index (à partir de 0), autrement -1.

var courses = ["STIC I", "STIC II", "STIC III", "STIC IV"];

var areYouThere = courses.indexOf("STIC II"); //--> 1
var areYouNotThere = courses.indexOf("ERGO I"); //--> -1

Objets en JavaScript

Définition d'un objet

Comprendre les objets en JavaScript équivaut à comprendre le langage lui-même, car pratiquement tout est un objet en JavaScript : les types de données (String, Number, Array, …) sont des objets, l’élément « document » utilisé pour accéder aux différents éléments d’une page web est un objet, et ainsi de suite. Par conséquent, la définition d’un objet doit forcément être assez générale pour prendre en compte toutes les différentes applications des objets :

  • Un objet est un élément qui contient d’autres éléments, même d'autres objets.

Les éléments contenus dans un objet peuvent être de deux types :

  1. Propriétés : c’est l’équivalent des variables dans un objet, car une propriété n’est qu’une valeur associée à un objet.
  2. Méthodes : c’est l’équivalent des fonctions dans un objet, car une méthode permet d’exécuter une certaine action sur un objet, souvent en relation avec ces propriétés.

Voyons tout de suite un exemple. Vu que pratiquement tout est un objet en JavaScript, prenons une simple suite de caractères (i.e. string).

var phrase = "Ceci n’est pas un Wiki" ;

La variable phrase est maintenant un objet de type String, un objet qui fait partie du langage JavaScript de base, et donc les propriétés et les méthodes sont accessibles à tout endroit dans le code. Voici deux exemples :

console.log(phrase.length) ; //22
console.log(phrase.toUpperCase()) ; //CECI N'EST PAS UN WIKI

On vient d’utiliser une propriété (i.e. length) et une méthode (i.e. toUpperCase()) associés à un objet de type String. De plus, on vient également d'utiliser la méthode log() de l'objet console pour afficher le contenu dans le navigateur web - tout est un objet! Pour mieux comprendre encore cette idée, on aurait même pu tout simplement utiliser la propriété et la méthode directement avec la suite de caractères, sans utiliser une variable :

"Ceci n'est pas un Wiki".length ;
"Ceci n'est pas un Wiki".toUpperCase() ;

L’accès aux propriétés et méthodes d’un objet se fait normalement à travers une notation « par points ». Vu qu’une propriété est une variable, pour y accéder il faut tout simplement ajouter son nom après l’objet et le point :

  • Objet.propriété

Au contraire, une méthode étant une fonction, il faut ajouter également les deux parenthèses.

  • Objet.méthode()

Cette notation peut être "enchaînée", par exemple la notation suivante permet transorm la phrase "Ceci n'est pas un Wiki" en majuscules et extrait les 4 premiers caractères :

"Ceci n'est pas un Wiki".toUpperCase().substr(0,4) //--> CECI

JavaScript met à disposition des développeurs trois types d’objets différents :

  1. Les objets globaux du langage de base (i.e. « native objects ») : il s’agit d’objet constitutifs du langage lui-même et qui sont par conséquent accessibles dans n’importe quel endroit dans le code et indépendamment de l’utilisation de JavaScript côté client ou serveur dans une page web, dans une application mobile, logiciel desktop, etc.
  2. Les objets mis à disposition par l’environnement : il s’agit d’objets qui dépendent directement de l’endroit dans lequel le code est interprété (voir Tutoriel JavaScript côté client ou Node.js)
  3. Les objets personnalisés : il s’agit d’objets que le développeur définit lui-même selon les nécessités particulières à l’application

Une autre manière de différencier les objets concerne la possibilité de les modifier, car certains objets (surtout les objets natifs et certains objets environnementales) sont "read-only", c'est-à-dire qu'il n'est pas possible de modifier les méthodes et les propriétés d'un objet. Par exemple la propriété PI de l'objet Math contient une approximation du nombre PI. Cette propriété ne peut pas être modifiée, même si on essaie de l'associer à une autre valeur:

//Valeur de base
Math.PI; //--> 3.141592653589793

//Essayer d'associer une autre valeur
Math.PI = 2; //--> 2 (cela parrait marcher, mais...)

//Afficher à nouveau la propriété
Math.PI; //--> 3.141592653589793 (read-only value)

Objets globaux (Native Objects)

Les objets disponibles dans le langage de base constituent les bases de l’API du langage lui-même, c’est-à-dire les propriétés et les méthodes que le langage considère utile pour définir les algorithmes nécessaires à manipuler les données dans une application. Voici de suite une liste non exhaustive de certains de ces objets (pour la liste complète : consulter par exemple la documentation Mozilla).

String

L'objet String permet d'exécuter des manipulations sur des chaînes de caractères. Voici quelques exemples :

var msg = "Bonjour";
msg.toUpperCase(); //BONJOUR
msg.substr(3, 7); //jour
msg.replace("jour", "soir"); //Bonsoir

Number

L'objet Number permet d'exécuter des manipulations sur des nombres. Voici un exemple pour la méthode toFixed() qui transforme un chiffre en caractère avec une précision décimale fixée.

var num = 6.749737898732;
num.toFixed(2); //6.75

Curiosité: vous pouvez utiliser cette méthode pour tester empiriquement l'un des problèmes les plus répandue dans la gestion des nombres décimal par des systèmes computationnels binaires :

var division = 1 / 10; //--> on s'attend à 0.1;
division.toFixed(20); //--> mais au fond... "0.10000000000000000555"

Les chiffres décimales sont en réalité des approximations, dans la pluspart des cas assez précises, mais qui parfois peuvent donner des problèmes.

Math

L'objet Math permet d'exécuter des manipulations mathématiques sur des chiffres. Voici deux exemples pour trouver un nombre aléatoire entre 1 et 100 :

var randomNumber = Math.floor((Math.random() * 100) + 1);
var randomNumber = Math.round((Math.random() * 100) + 1);
  • Math.random() renvoie un nombre au hasard entre [0;1[.
  • Math.floor(x) renvoie le plus grand entier inférieur ou égal à x.
  • Math.round(x) renvoie le plus grand entier supérieur ou égal à x.

Ceux-ci peuvent pour être utiles si vous souhaitez prendre au hasard un objet dans un Array :

var myFruits = ["pomme", "poire", "fraise", "framboise"];
var myFruitsDrawn = new Array(myFruits.length - 1); // création d'un array de taille 4 - 1 (un array commence à l'objet 0)

function chooseRandom(i) {
 i = Math.round(Math.random()*(myFruits.length - 1));
 if (myFruitsDrawn.indexOf(myFruits[i]) === -1) // indexOf(x) renvoie l'index de myFruitsDrawn où se trouve l'objet x, sinon renvoie -1 (ici on l'utilise pour checker si l'objet à la position i de l'array myFruits ne se trouve pas déjà dans myFruitsDrawn)
 {
   return (i);
 }
 return (-1)
 }

function displayRandomFruits(){
 var i = -1
  
 while (i === -1)
 {
   i = chooseRandom(i);
 }
 myFruitsDrawn.push(myFruits[i]); // push(x) 'pousse' x dans l'array myFruitsDrawn
 myFruits.splice(i,1); // splice(x) coupe myFruits en position i de 1 objet, c'est-à-dire on enlève l'élément qui a été précédemment push
 return (myFruitsDrawn[myFruitsDrawn.length - 1]); // la fonction retourne un fruit choisi au hasard et qui n'a pas déjà été choisi !
}

Date

L'objet Date permet d'exécuter des manipulations sur les dates. La gestion des dates n'est pas simple en JavaScript. Par exemple la méthode getMonth() qui identifie le mois de l'année en chiffres ne propose pas les mois de 1 à 12, mais plutôt de 0 à 11. Donc le mois 10 n'est pas octobre comme on pourrait s'imaginer, mais plutôt novembre. Voici un exemple pour obtenir le jour du mois (de 1 à 31) :

var d = new Date();
var aujourdhui = d.getDate();

Objets personnalisés

JavaScript permet de créer ses propres objets avec les propriétés et méthodes souhaitées. Les propriétés sont représentées par des données, tandis que les méthodes par des fonctions.

Définition d'un objet

La définition d'un objet peut se faire de différentes manières. Les notations suivantes définissent le même objet appelé Cours :

 //1.
 var Cours = {
    nom: "STIC I", 
    periode: "Automne", 
    nombreExercices: "8"
 };

 //2.
 var Cours = {}; //Aussi var Cours = new Object();
 Cours.nom = "STIC I";
 Cours.periode: "Automne";
 Cours.nombreExercices: "8";

Les noms des propriétés ne doivent pas suivre la notation des variables, mais s'ils ne la suivent pas, il faut les insérer entre guillemets comme les valeurs :

var Cours = { 
    nomRespecte: "STIC I", 
   "nom-ne-respecte-pas": "STIC I"
}

On peut associer à un objet aussi des méthodes, encore une fois de différentes manières dont le résultat est équivalent :

 //1. avec une fonction anonyme
 var Cours = {};
 Cours.nom = "STIC I";
 Cours.afficherNom = function () { 
    return "STIC I" 
 };

 //2. Définir la fonction à l'avance
 function afficherNomDuCours () {
     return "STIC I";
 }
 var Cours = {};
 Cours.nom = "STIC I";
 Cours.afficherNom = afficherNomDuCours;

Utilisation des objets

Une fois définit l'objet, on peut l'utiliser facilement à travers la notation "par points" pour propriétés dont le nom respecte la notation des variables ou les méthodes. Pour les noms des propriétés qui ne respectent pas la nomination des variables, il faudra utiliser la notation "à Array". Voici des exemples :

 var Cours = { 
     nomRespecte: "STIC I", 
     "nom-ne-respecte-pas": "STIC I"
 };
 
 Cours.maMethode = function () { 
     console.log("Je suis une méthode de l'objet Cours"); 
 };
 
 var nomDuCours1 = Cours.nomRespecte;
 var nomDuCours2 = Cours["nom-ne-respecte-pas"];
 Cours.maMethode(); //Il faut utiliser les parenthèses

L'élément this dans les Objets

Parfois il est nécessaire d'accéder à d'autres propriétés ou méthodes d'un objet à l'intérieur de l'objet lui-même. Dans ce cas, l'objet est représenté par la notation this. Voici un exemple illustratif :

 var Cours = {};
 Cours.nom = "STIC I";
 Cours.afficheLeNom = function () { 
    console.log(this.nom) 
 };
 Cours.afficheLeNom(); //--> STIC I

Définir des objets prototypes

Les notations qu’on a vues plus haut pour définir un objet sont utiles pour définir un seul objet de ce type, ce qu’on appelle une « instance » de l’objet. Il est également possible de créer plusieurs instances d’un objet, pour ce faire il faut le définir à travers une fonction « constructrice », qui crée des objets prototypes. Voici un exemple pour créer deux instances d’un objet « Tutoriel » :

function Tutoriel(argument, niveau) {
  this.argument = argument;
  this.niveau = niveau;
  this.printTutorielInfo = function () {
    return 'Tutoriel de niveau ' + this.niveau + ' sur ' + this.argument;
  }
}
var tutorielJavaScriptBase = new Tutoriel('JavaScript', 'intermédiare');
var tutorielNodeJs = new Tutoriel('Node.js', 'avancé');

console.log(tutorielJavaScriptBase.printTutorielInfo()); // --> Tutoriel de niveau intermédiare sur JavaScript
console.log(tutorielNodeJs.printTutorielInfo()); // --> Tutoriel de niveau avancé sur Node.js

L’objet Tutoriel fonction correctement, mais son fonctionnement interne peut être amélioré, car à présent chaque fois qu’on crée une instance de cet objet, le navigateur doit créer trois éléments :

  1. La propriété argument
  2. La propriété niveau
  3. La méthode pour récupérer les infos sur le Tutoriel

De ces trois éléments, la méthode est commune à toute instance de l’objet, car elle se limite à fournir les deux propriétés qui différencient les différents tutoriels. Pour éviter que cette méthode soit créée pour chaque instance, on peut exploiter la propriété « prototype » commune à tout objet. Cette propriété permet d’ajouter une propriété ou une méthode communes à toute instance du même objet. Dans le cas du tutoriel, on peut effacer la fonction printTutorielInfo() à l’intérieur de la fonction constructrice, et la déclarer en tant que méthode prototype :

function Tutoriel(argument, niveau) {
  this.argument = argument;
  this.niveau = niveau;
}

Tutoriel.prototype.printTutorielInfo = function () {
  return 'Tutoriel de niveau ' + this.niveau + ' sur ' + this.argument;
}
var tutorielJavaScriptBase = new Tutoriel('JavaScript', 'intermédiare');
var tutorielNodeJs = new Tutoriel('Node.js', 'avancé');

console.log(tutorielJavaScriptBase.printTutorielInfo()); // --> Tutoriel de niveau intermédiare sur JavaScript
console.log(tutorielNodeJs.printTutorielInfo()); // --> Tutoriel de niveau avancé sur Node.js

Ce type de programmation à objets peut être très utile par exemple pour les jeux. Voici un exemple incomplet de comment un objet "Monster" pourrait se présenter. D'abord, on définit la fonction constructrice qui accepte trois paramètres: (1) le type de monstre, (2) sa position X, et (3) sa position Y:

//Définir la fonction constructrice des Monstres, avec les éléments particuliers à chaque instance.
function Monster(name, x, y) {
  this.name = name;
  this.x = x;
  this.y = y;
}

Ensuite, on définit les propriétés et les méthodes communes à toute instance qui permettent de faire bouger le monstre et de le tuer. On crée également une fonction qui fournit des informations sur l'état du monstre à un certain moments dans le jeu:

//Définir les propriétés et les méthodes communes à toute instance d'un monstre.
Monster.prototype.health = 100;
Monster.prototype.isAlive = true;
Monster.prototype.isHit = function (damage) {
  this.health -= damage;
  if(this.health <= 0) {
    this.isAlive = false;
  }
}
Monster.prototype.moveUp = function () {
  this.y += 10;
}
Monster.prototype.moveDown = function () {
  this.y -= 10;
}
Monster.prototype.moveRight = function () {
  this.x += 10;
}
Monster.prototype.moveLeft = function () {
  this.x -= 10;
}
Monster.prototype.printInfo = function () {
  if(!this.isAlive) {
    return "Le " + this.name + " a été tué!";
  }
  return "Le " + this.name + " se trouve aux coordonnées [" + this.x + ":" + this.y + "] et il lui manque " + this.health + " avant de disparaître.";
}

Maintenant on peut simuler le jeu en créant deux monstres:

//Simulation du jeu avec deux monstres, un Dragon et un Goblin. 
var firstMonster = new Monster('Dragon', 0, 0);
firstMonster.moveLeft();
firstMonster.moveUp();
firstMonster.isHit(50);
console.log(firstMonster.printInfo()); // --> Le Dragon se trouve aux coordonnées [-10:10] et il lui manque 50 avant de disparaître.

var secondMonster = new Monster('Goblin', 25, -15);
secondMonster.moveDown();
secondMonster.isHit(5);
console.log(secondMonster.printInfo()); // --> Le Goblin se trouve aux coordonnées [25:-25] et il lui manque 95 avant de disparaître.

firstMonster.moveUp();
firstMonster.moveLeft();
firstMonster.isHit(60);
console.log(firstMonster.printInfo()); // --> Le Dragon a été tué!

Références