Le Javascript est un langage qui a plusieurs caractéristiques :
Les instructions d'un programme en Javascript sont interprétées par le moteur Javascript au moment de l'exécution du programme. Cela permet le typage faible et la nature dynamique du langage.
Le type des variables n'est pas déclaré dans le programme. Il est déduit automatiquement lors de l'exécution. Le type d'une variable peut donc changer pendant d'exécution du programme.
A part les types simples : booléen, nombre et chaîne de caractère, tous les autres éléments du langage sont des objets. Un objet est conteneur d'une collection de propriétés. Chaque propriété, comme une variable, possède une étiquette (son nom) et une valeur qui peut-être un type simple (booléen, nombre, chaîne de caractère) ou un autre objet ce qui permet des structures complexes.
On peut à tout moment de sa vie ajouter dynamiquement des propriétés à un objet. C'est à dire ajouter des propriétés non déclarées au préalable dans le programme initial.
Tous les appels à des entrées/sorties (requêtes ajax, timer, lecture de fichier, détection d'un changement d'état, ...) sont non bloquants. Le programme n'attend pas le retour des entrées/sorties pour continuer. Une fonction de rappel est programmée pour être appelée au moment de la fin de l'opération d'entrée/sortie.
Javascript n'exécute qu'un programme à la fois. Les fonctions de rappel sont appelées quand toutes les instructions courantes sont terminées.
JavaScript emprunte la plupart des éléments de sa syntaxe à Java, C et C++.
Le Javascript est sensible à la casse (majuscules / minuscules).
Les instructions doivent être séparées par un ; ou par un saut de ligne. La bonne pratique est de toujours mettre un point virgule. Les espaces, tabulations et sauts de ligne sont des caractères blancs (ils sont ignorés).
Toutes les variables doivent être déclarées la première fois avec un des mots clés var, let ou const.
Le mot clé var défini une variable de portée globale ou de portée locale dans une fonction.
Le mot clé let défini une variable de portée locale dans une structure (dans un if, while, une fonction)
Le mot-clé const défini une variable en lecture seule (une constante). Sa portée est similaire à var.
Installer l'extension Live Server dans Visual Studio Code
Créer un dossier (projet) dans Visual Studio Code
Créer un fichier index.html dans le projet
Créer un fichier base.js
Faire un clic droit sur le fichier index.html et cliquer sur Open with live server. Dans le navigateur, ouvrez la console avec F12.
Créer un fichier index.html dans le projet
<html>
<head>
<title>Les bases de Javascript</title>
</head>
<body>
<h1>Javascript : les bases, ouvrez la console avec F12</h1>
<script src="base.js"></script>
</body>
</html>
Créer un fichier base.js
var hw="Bonjour monde !";
console.log(hw);
function testPortee() {
console.log("valeur de hw",hw);
}
var hw="Bonjour monde !";
console.log(hw);
testPortee();
La variable est définie dans la fonction !
function testPortee() {
var hw="Bonjour monde !";
console.log(hw);
}
testPortee();
console.log("Valeur de hw", hw);
La variable n'est définie que dans la fonction au moment de l'appel.
function testPortee(lang) {
if (lang=='fr') {
let hw="Bonjour monde !";
console.log(hw);
} else {let hw="Hello world !";
console.log(hw);
}
console.log(hw);
}
testPortee('fr');
La variable hw n'est visible que dans la structure où elle est définie (ici if ou else).
function testPortee() {
console.log(hw);
hw="Hello world !";
}
const hw="Bonjour monde !";
testPortee();
La variable hw ne peut pas être assignée deux fois !
A part les types de base booléen, nombre et texte, toutes les structures du langage sont des objets.
Un objet est un conteneur de propriétés nommées. A chaque propriété on associe une valeur ou un autre objet. Des propriétés peuvent être ajoutées à tout moment sur n'importe quel objet.
Un objet est toujours affecté à au moins une variable ou à au moins une propriété d'un autre objet.
Les tableaux et les fonctions sont des objets.
On peut créer un objet vide de deux manières :
Les accolades représentent un objet.
Les propriétés sont manipulées de trois façon différentes :
avec le caractère .
avec la notation []
avec la notation Json
o.message="Bonjour Monde !"
Dans ce cas, le nom de la propriété est directement écrite comme une variable. Elle est ajoutée après la création de l'objet.
o["message"]="Bonjour monde !"
Dans ce cas, le nom de la propriété est une chaîne de caractère et peut contenir des caractères interdits dans le nom d'une variable. Elle est ajoutée après la création de l'objet.
var o = {
message : "Bonjour monde !"
}
Dans ce cas, les propriétés sont déclarées au moment de la création de l'objet.
On peut affecter un objet à une propriété comme à une variable.
o.time = {
heure : 10,
minute : 30,
seconde : 0
}
var o = {
message : "Bonjour monde !",
time : {heure : 10,
minute : 30,
secondes : 0
}
}

Il suffit d'enchaîner les . ou les []
console.log(o.time.heure) ;
console.log(o["time"]["heure"]);
console.log(o.time["heure"]);
Créez un objet Personne qui vous décrit : nom, prénom, formation. Détaillez les propriétés de la formation (niveau, intitulé, école, ...). Affichez l'objet avec console.log.
Les fonctions en Javascript sont des objets à part entière.
Il y a plusieurs manière de créer un objet fonction.
function afficheNom(prenom,nom) {
console.log(prenom,nom);
}
Crée un objet Function et l'affecte à la variable afficheNom
var afficheNom=function(prenom,nom) {
console.log(prenom,nom);
}
Crée un objet Function et l'affecte à la variable afficheNom, la fonction est dite anonyme.
var afficheNom=(prenom,nom)=>{
console.log(prenom,nom);
}
Crée un objet pseudo Function et l'affecte à la variable afficheNom, la fonction est dite fléchée. Ce n'est pas tout à fait la même chose qu'une fonction anonyme (voir plus tard)
Pour appeler une fonction (c'est à dire l'exécuter), il suffit d'appeler son nom suivi des () avec les arguments éventuels.
afficheNom("Florent","TETART") ;
Une fonction peut-être déclarée dans une autre fonction, cela crée une variable locale qui contient l'objet Function associé. Elle ne sera donc pas visible dans l'espace global.
Avec la notation anonyme, on peut affecter une fonction à une propriété d'un objet.
var o = {
message : "Bonjour monde !",
time : {heure : 10,
minute : 30,
secondes : 0
},
afficheNom : function(prenom, nom) {
console.log(prenom,nom);
}
}

On appelle la fonction en utilisant la propriété de l'objet.
o.afficheNom("Florent","TETART") ;
Le mot clé this représente le contexte d'appel de la fonction. C'est à dire l'objet associé à l'exécution de la fonction.
Si la fonction est appelée avec le nom de l'objet auquel elle appartient, this vaut cet objet.
var o = {
message : "Bonjour monde !",
time : {heure : 10,
minute : 30,
secondes : 0
},
afficheHeure : function() {
console.log(this.time.heure+":"+this.time.minute+":"+this.time.secondes);
}
}
Si on appelle o.afficheHeure() ; this représente l'objet o. On parle alors de méthode de l'objet o.

Ajoutez une méthode afficheInfos() à votre objet Personne qui affiche votre nom, prénom et formation.
Pour créer un objet Array, c'est à dire un tableau, deux syntaxes sont possibles.
var t = new Array("bonjour", 10, 24) ;
var t = ["bonjour", 10, 24] ;
Un tableau est une collection de valeurs auxquelles on accède par l'indice numérique de l'ordre dans le tableau. Pour accéder à un élément, on utilise la notation crochet. Les indices commencent à 0.
console.log( t[2] ) ;
Affiche 24.
L'objet Array possède des méthodes pour manipuler le tableau.
La méthode push(valeur) permet d'ajouter un élément en dernier au tableau.
t.push("monde") ;
console.log( t[3] ) affiche monde
L'objet window représente la fenêtre du navigateur. C'est aussi l'objet qui contient l'espace global de Javascript.
Toute variable ou fonction déclarée dans l'espace global est un réalité une propriété de l'objet window.
var nom = "CESR" ; est la même chose que window.nom="CESR" ;
function plus(a,b) { return a+b ; } est la même chose que window.plus=function(a,b) { return a+b ; }
L'objet document représente la page HTML en cours d'affichage dans le navigateur. C'est en manipulant les propriétés de l'objet document que l'on agit sur la page.
document.body.style.background="#FF0000" ;
L'objet HTMLElement représente un élément (tag) de la page HTML en cours d'affichage.
h=document.getElementsByTagName("h1") ; //revoie un tableau de HTMLElement
h[0].innerHTML="Bonjour CESR" ;
L'objet console représente l'environnement de débuggage (acessible par F12).
console.log("CESR") ;
L'objet history représente l'historique de navigation.
history.go(-1) ;
revient en arrière d'une page dans l'historique.
Pour chaque objet que l'on doit créer, il faut déclarer les propriétés et les méthodes (fonctions affectées à des propriétés).
Il existe en Javascript un mécanisme qui permet de ne déclarer qu'une seule fois les méthodes pour des objets de même nature, c'est à dire d'une même classe.
Ce mécanisme combine l'instanciation et la notion de prototype.
Le principe est de déclarer une fonction qui représente la classe d'objet.
Dans la fonction on crée les propriétés qui seront affectées à l'instanciation.
Ensuite on affecte à la propriété prototype de l'objet fonction un objet qui contient les méthodes communes à toutes les instances.
L'instanciation se fait avec le mot clé new.
Le mot clé new crée un objet vide et l'associe à this puis exécute la fonction d'instanciation. La fonction d'instanciation crée les propriétés sur cet objet vide. Enfin, les méthodes dans l'objet prototype de la fonction sont rattachées au nouvel objet instance.
function Livre(titre,auteur,isbn) { //Fonction d'instanciation
this.titre=titre;
this.auteur=auteur;
this.isbn=isbn;
}
//PrototypeLivre.prototype={
afficheInfos : function() {
console.log(this.titre+' / '+this.auteur+' - '+this.isbn);
}
}
//Instanciationvar livre1 = new Livre("L'art du scripting","Kais Ayari","978-2-212-14038-5");
livre1.afficheInfos();
Affiche L'art du scripting / Kais Ayari - 978-2-212-14038-5.

Chaque instance a donc les mêmes propriétés avec des valeurs différentes et partage les même méthodes via le prototype dans la propriété _proto_.
Créez une classe Personne instanciable.
Il existe une syntaxe raccourcie pour tout déclarer en une fois. Mais le mécanisme reste le même.
class Livre {
constructor(titre,auteur,isbn) { //Fonction d'instanciation
//Fonction d'instanciationthis.titre=titre;
this.auteur=auteur;
this.isbn=isbn;
}
afficheInfos() { //Méthode du prototype
console.log(this.titre+' / '+this.auteur+' - '+this.isbn);
}
}
//Instanciationvar livre1 = new Livre("L'art du scripting","Kais Ayari","978-2-212-14038-5");
livre1.afficheInfos();
Lorsque le Javascript exécute une opération d'entrée / sortie (par exemple une requête Ajax), il délègue l'exécution de cette opération au système dans lequel le JavaScript s'exécute (le navigateur par exemple) et le moteur Javascript continue à exécuter les instructions suivantes.
Le moteur du Javascript n'attend pas la fin de l'opération de l'entrée / sortie avant de continuer. Autrement dit, le résultat de l'entrée / sortie est traité quand il est disponible plus tard : de manière asynchrone avec le programme principal.
A la place d'un traitement synchrone, une fonction de rappel doit être fournie. Quand l'opération d'entrée sortie se termine, la fonction de rappel est mise en attente d'exécution. Quand le Javascript a fini d’exécuter les instructions du programme principal, si une fonction de rappel est en attente elle est exécutée.

Le Javascript est asynchrone pour ne pas bloquer le navigateur quand on attend un résultat d'une entrée / sortie !
Le moteur Javascript n'exécute qu'un programme à la fois. Il n'y a pas de parallélisme.
Créer un fichier index_async.html dans le projet
<html>
<head>
<title>Asynchrone</title>
</head>
<body>
<h1>Test asynchrone</h1>
<script src="js_async.js"></script>
</body>
</html>
Créer un fichier js_async.js
setTimeout(function() {
console.log("2 secondes après !");
},2000);
console.log("suite du programme !");
Modifier le fichier js_async.js
setTimeout(function() {
console.log("2 secondes après !");
let i=0;
//On perd du temps !while (i<100000) {
i++;
}
},2000);
setTimeout(function() {
console.log("3 secondes après !");
},3000);
console.log("suite du programme !");
Augmentez le compteur !
Multipliez par 10 le nombre de tours dans la boucle while jusqu'à ce que le message 3 secondes n'apparaisse plus au bout de 3s !!
Dans toutes les fonctions de rappel, this représente l'objet qui a déclenché le rappel (ici le timer). Vous pouvez le vérifier en faisant un console.log(this).
Lorsque l'on va utiliser une méthode d'un objet comme fonction de rappel d'un appel asynchrone, this ne vaut pas l'objet qui porte la méthode mais l'objet qui a généré le rappel.
Pour conserver l'objet d'origine dans this il faut utiliser les fonctions fléchées.
class Compteur {
constructor(duree) {
this.duree=duree;
this.compteur=0;
this.timer=setInterval(this.incrementeCompteur,this.duree); //Ne marche pas !
}
incrementeCompteur() {
this.compteur+=1;
console.log(this.compteur);
}
stopCompteur() {
clearInterval(this.timer);
}
}
var c=new Compteur(1000);
this.incrementCompteur est la fonction passée à setInterval qui sera rappelée tous les duree en ms. Au moment du rappel, dans la fonction incrementeCompteur, this vaut l'objet timer qui a été créé par setInterval pour faire le rappel et non l'instance de Compteur.

class Compteur {
constructor(duree) {
this.duree=duree;
this.compteur=0;
this.timer=setInterval(()=>{ this.incrementeCompteur() },this.duree); //Marche !
}
incrementeCompteur() {
this.compteur+=1;
console.log(this.compteur);
}
stopCompteur() {
clearInterval(this.timer);
}
}
var t
var c=new Compteur(1000);
La fonction fléchée ()=>{ this.incrementeCompteur() } est la fonction qui sera rappelée par setInterval tous les duree en ms. Au moment du rappel, la fonction fléchée conserve dans this la valeur qu'il avait au moment de la création de la fonction fléchée, soit l'instance de Compteur.

Dans tous les rappels asynchrones d'une méthode d'un objet, pour conserver l'instance d'origine, il faut utiliser une fonction fléchée.