Actions

Cours

Technologies avancées du eLearning 2/TOUT ce qu'il y a à savoir

De GBLL, TAL, ALAO, etc.

< Cours:Technologies avancées du eLearning 2

Dans ce qui suit :

élément javascript à savoir

complément d'information

Variable et type

Dès qu'on a besoin de conserver une valeur on va créer une variable (qui est comme une boite à laquelle on a donné un nom)

En javascript: var nomVar ;

Toute variable a un type, qui décide de la manière dont le système va traiter l'information.

En javascript, on peut demander le type d'une variable : typeof nomVar ;. (réponses possibles cf. diapo 9)

Quand une variable n'a pas le type attendu par le système, javascript va automatiquement essayer de la transtyper[1]. Par conséquent, vous devez toujours savoir quel type de variable vous manipulez.

Opérateurs

Javascript définit un ensemble d'opérateurs qui prennent deux opérandes et renvoient une valeur. Si les opérandes sont des symboles (ex : nom de variable, appel de fonction) ou autre expression, la valeur des opérandes est calculée avant que l'effet de l'opérateur ne lui soit appliqué.

Affectation

coteGauche = coteDroit; //coteGauche ← coteDroit

  • le coteGauche est le nom de la variable qui va accueillir la valeur ;
  • le coteDroit est une constante/expression qui sera calculée avant que l'on ne stocke son résultat[2].

Opérateurs arithmétiques

Les opérateurs suivants prennent des nombres (Number) en entrée et renvoient un nombre :

  • + → addition var num = 1 + 4 ; // num vaut 5 ;
  • - → soustraction var num = 3 - 2 ; // num vaut 1 ;
  • * → multiplication var num = 2 * 4 ; // num vaut 8 ;
  • / → division var num = 3 / 2 ; // num vaut 1.5 ;
  • % → reste de la division entière var num = 5 % 2 ; // num vaut 1.

Opérateur de concaténation

L'opérateur suivant prend une chaine de caractère (String) en entrée et renvoie une chaine de caractère[3] :

  • + → concaténation var phrase = "Bonjour"+ " " + "tout le monde" ; // phrase vaut "Bonjour tout le monde".

Opérateurs booléens

Les opérateurs suivants prennent des booléens (Boolean) en entrée et renvoient un booléen :

  • || → ou logique var booleen = true || false ; // booleen vaut true ;
  • && → et logique var booleen = true && false ; // booleen vaut false ;
  • ! → non logique var booleen = !false ; // booleen vaut true.

Les opérateurs suivants prennent n'importe quel type en entrée et renvoient un booléen[4] :

  • == → test d'égalité var booleen = 1 == 2 ; // booleen vaut false ;
  • != → test de différence var booleen = "1" != "2" ; // booleen vaut true ;

Fonction

Une fonction permet d'assimiler une séquence d'instructions à un nom et de renvoyer une valeur. Certaines fonctions sont définies par le langage javascript, d'autres peuvent être créées par le programmeur.

Déclaration de fonction

En javascript :
function nomDeLaFonction(liste,des,parametres){
   //séquence d'instructions
   return valeurRenvoyée ;
}

Attention, aucune instruction située après un return n'est jamais exécutée.

Appel de fonction

Quand le système rencontre un appel de fonction, il va essayer de retrouver sa définition, faire correspondre les valeurs transmises aux paramètres et renvoyer un résultat (si la commande return a été utilisée dans la déclaration de la fonction).

En javascript : nomDeLaFonction(liste,des,parametres);

Voir un exemple

function carre(nombre){
  return nombre*nombre ;
}
var num = carre(3) + 1; //num vaut 10
num = carre(num) + carre(5); //num vaut 125, car 10×10 + 5×5 = 125

Fonction anonyme

Définition

Une fonction anonyme est une fonction déclarée à la volée sans être nommée.

Voir aussi, le le patron de conception ci-dessous.

Voir une explication

Explication

En JavaScript, une fonction est une variable comme une autre :

function plus1(p1){
   return p1+1 ;
}
console.log(typeof plus1,plus1(1)); //→ "function", 2

est équivalent à

var plus1 = function(p1){
   return p1+1 ;
}
console.log(typeof plus1,plus1(1)); //→ "function", 2

Sauf que dans la deuxième version, la fonction qui renvoie p1+1 n'a pas de nom, elle est anonyme. On crée une variable plus1 et on lui affecte comme valeur la fonction anonyme.

Ce mécanisme est très utilisé. Il permet par exemple d'utiliser la même méthode .sort() avec n'importe quel tableau, quel que soit l'ordre qu'on veut utiliser. En effet, si l'ordre par défaut ne nous convient pas, on peut fournir à sort une fonction de comparaison.

De la même manière, c'est ce mécanisme qui permet d'affecter aux différents événements déclenchés par le DOM des comportements ad hoc. Par exemple :

function init(){
   //init est une fonction qui va permettre d'initialiser la page
   var elt=document.getElementById("compteur");
   //on veut qu'à chaque clic sur l'élément d'id #compteur
   //sa valeur soit incrémentée de 1 
   elt.onclick = function(){elt.innerHTML = Number(elt.innerHTML)+1;} ;
}
window.onload = init;
Dans le code ci-dessus, on affecte la fonction init à l'attribut onload de l'objet window (qui devient est donc une méthode). On ne met pas de parenthèses après init lors de cette affectation, car on veut la fonction et non le résultat de son appel. De la même manière, on affecte à l'attribut onclick de l'élément d'id #compteur, une fonction anonyme. Celle-ci prend le contenu de l'élément, le convertit en nombre, ajoute 1 et remplace le contenu de l'élément avec cette nouvelle valeur.

Structures de contrôle

if

On peut définir des structures de contrôle pour n'exécuter certaines instructions que dans certaines conditions.

En javascript :
if(expr){
  //code à exécuter si expr est évaluée à true
}
else{
  //code à exécuter si expr est évaluée à false
}
Voir un exemple

expr est une expression booléenne (même si ce n'est pas un booléen) : l'expression sera évaluée, puis transtypée pour avoir un booléen.

Exemple

function pair(nombre){
  return (nombre % 2 == 0) ; // renvoie un booléen
}

if(pair(2)){
  console.log("Va s'afficher");
}
else{
  console.log("Ne va pas s'afficher");
}
if(pair(3)){
  console.log("Ne va pas s'afficher");
}
else{
  console.log("Va s'afficher");
}

for

On peut également répéter des instructions jusqu'à ce qu'une condition soit réalisée, en utilisant une boucle.

En javascript :
for(/*initialisation*/;/*condition de bouclage*/;/*incrément*/){
  //code à exécuter si condition de bouclage est évaluée à true
}
  • L'exécution d'une telle boucle commencera toujours par l'initialisation,
  • Si la condition de bouclage est respectée
    • on exécutera le code situé entre les accolades,
    • une fois l'accolade fermante atteinte on va exécuter l'incrément,
  • Si la condition de bouclage est respectée
    • on exécutera le code situé entre les accolades,
    • une fois l'accolade fermante atteinte on va exécuter l'incrément,
  • et ainsi de suite.

Voir un exemple

expr est une expression booléenne (même si ce n'est pas un booléen) : l'expression sera évaluée, puis transtypée pour avoir un booléen. Il faut toujours s'assurer que la condition de bouclage peut changer jusqu'à être évaluée à false, sinon le programme peut boucler à l'infini.

Exemple

for(var i=1;i<=10;i=i+1){
  console.log(i);
}/*Va afficher :
1
2
3
4
5
6
7
8
9
10
*/

Objets et Classes

Les objets permettent sont des éléments structurants qui permettent de regrouper dans la même entité :

  • des données (les attributs) ;
  • des traitement (les méthodes).

JSON

La notation JavaScript Object Notation définit une manière synthétique d'écrire des instances d'objets :

Tableau en notation JSON : ["liste","des","valeurs"]

Objet en notation JSON : {"attribut1":"valeurs","attribut2":12}

Classes

Une classe permet de définir le fonctionnement (données et traitements) d'une famille d'objets. À chaque fois que l'on crée un objet qui suit cette définition, on dit que l'on instancie la classe.

En JavaScript, la déclaration d'une classe se fait avec le mot clé Class. Quand on crée une instance de la classe, le constructeur est appelé automatiquement. Pour définir un constructeur on utilise le mot clé contructor. Lors de la définition des méthodes d'une classe, on utilise le mot clé this pour désigner l'objet qui sera manipulé.

Pour instancier une classe on utilise le mot-clé new

Pour un exemple voir l'exercice de la classe Equipe.

Influence du contexte

Exemple de la visibilité de variables.
Le mot clé var ou let est surligné. La portée de chaque variable est représentée par la couleur des blocs.
Attention, pour exécuter le programme jusqu'au bout, il faut supprimer les lignes qui utilise une variable inaccessible à cet endroit du code.

Portée d'une variable

Les variables déclarées avec var sont accessibles

  • dans tout le programme, si elles n'ont pas été déclarées dans une fonction (on parle alors de variable globale)
  • dans la fonction où elles ont été déclarées sinon.

Un bloc d'instructions est un ensemble d'instructions délimitées par une accolade ouvrante et une accolade fermante. Une fonction est donc un bloc, mais c'est aussi le cas des instructions correspondant à un else ou à une boucle.

Les variables déclarées avec let sont accessibles uniquement dans le bloc où elles ont été déclarées.

Polysémie de this

Selon l'usage de la fonction/méthode ou this est utilisé, il n'a pas la même sémantique.

Dans une fonction déclenchée par un événement, this représente l'élément du DOM qui a déclenchée l'événement.

Dans une méthode déclarée dans une classe, this représente une instance de la classe appelant la méthode.

Patron de conception : self + fonction anonyme

Problème

Dans le cas où on veut faire référence à l'instance d'un objet de la classe que l'on définit à l'intérieur même de cette classe…

class carteMemoryDOM{
  constructor(img,parent){
    var imgElt = document.createElement('img');
    imgElt.src = src ;
    this.elt = document.createElement('div');
    this.elt.appendChild(imgElt);
    parent.appendChild(this.elt);
    this.addEventListener("click",
      /*Je veux pouvoir appeler la méthode retourner
        mais ici this sera l'objet qui déclenche l'événement
        comment faire ?*/);
  }
  retourner(){
    if(this.elt.classList.contains("turned")){
      this.elt.classList.remove("turned");
    else{
      this.elt.classList.add("turned");
    }
  }
}

Solution

On aura recours à la méthode suivante, qui utilise les fonctions anonymes.

class carteMemoryDOM{
  constructor(img,parent){
    var imgElt = document.createElement('img');
    imgElt.src = src ;
    this.elt = document.createElement('div');
    this.elt.appendChild(imgElt);
    var self = this ; //je crée une variable temporaire qui pointe vers l'objet courant
    //la portée de cette variable fait qu'à partir de ce point elle est accessible
    //dans tout le constructeur
    this.addEventListener("click", function(){//déclaration d'une fonction anonyme appelée au moment du clic
      //this ne désigne plus l'objet mais la cible du clic… mais ce n'est pas grave car self est visible
      self.retourner();  
    );
    //this désigne à nouveau l'instance de l'objet (mais on pourrait continuer d'utiliser la variable créée
    parent.appendChild(this.elt); 
  }
  retourner(){
    if(this.elt.classList.contains("turned")){
      this.elt.classList.remove("turned");
    else{
      this.elt.classList.add("turned");
    }
  }
}

Notes et références

  1. convertir une variable d'un type à un autre
  2. Quand une variable contient un objet, on ne copie pas la valeur mais une référence vers l'objet. Cela veut dire que :
    class objet{
      constructor(entier){
        this.val=entier;
      }
      mod(entier){
        this.val=entier;
      }
    }
    var obj1 = new objet(22),
        obj2 = obj1;
    obj2.mod(35) ;
    console.log(obj1); // affiche Object { val: 35 }
    
    // mais
    var int1 = 22,
        int2 = int1;
    int2 = 35 ;
    console.log(int1); // affiche 22
    
  3. Attention, il suffit d'une opérande String pour que + transtype l'autre.
  4. Attention au transtypage (cf. diapo 11 & 12)