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

De EduTech Wiki
Aller à la navigation Aller à la recherche
mAucun résumé des modifications
Ligne 267 : Ligne 267 :
  var a = 2 + 3; //5
  var a = 2 + 3; //5
  var b = 10 - 5; //5
  var b = 10 - 5; //5
  var c = 2 * 3 //6
  var c = 2 * 3; //6
  var d = 9 / 3; //3
  var d = 9 / 3; //3



Version du 28 septembre 2016 à 10:24

JavaScript
◀▬▬▶
à améliorer intermédiaire
2016/09/28
Prérequis
Voir aussi

Introduction

Cette page propose un survol sur les éléments fondamenteaux du langage JavaScript. Les notions présentées dans cette page sont valable 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.

Console JavaScript

Les exemples présentés dans ce tutoriel utilise les éléments fondamenteaux 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 votre navigateur. Vous pouvez ouvrir la Console et garder en même temps cette page ouverte :

  • Internet Explorer : Menu Outils > Outils de développement (ou F12)
  • Firefox : F12 ou plus de fonctionnalités via l'extension Firebug
  • 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 :

  • 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.


  • 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 une 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 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 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 var 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 ;
  • 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ôles, les fonctions et les cycles/boucles (voir plus bas)

Commentaire

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
*/

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 examples:

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 liste ici : http://www.w3schools.com/js/js_reserved.asp)
  • Peut se composer exclusivement de caractères alphanumériques, underscore (_) et signe du dollar ($)
  • Le premier caractère ne peut pas être un chiffre
//Exemple de variables correctes
var monWiki123 = "EduTechWiki";
var $monWiki123 = "EduTech Wiki";
var _____monWiki123 = "EduTechWiki";
//Exemple de variables non correctes
var 123wiki = "Faux";
var aujourd'hui = "Faux";

Même si ce n'est pas une règle, il est cependant une 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

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.

Les types de variables acceptés sont :

  • String : chaîne des caractères
    • var a = "Bonjour"
    • var b = 'Hello'
    • var c = "Il m'a dit \"Bonjour\" quand je l'ai vu";
    • var d = 'Ajourd\'hui';
    • var e = "Pour faire apparaître un \\ il faut en mettre deux";
  • Number : chiffres et décimales
    • var a = 12
    • var b = 3.14
    • var c = -12
  • Boolean : vrai/faux
    • var a = true
    • var b = false
  • 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"

Les objets sont :

  • Object
  • Array
  • Function

Contrairement à d'autres langages de programmation, les variables en JavaScript ne sont pas liée à 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

Objets

Un objet est un élément qui se compose d'une ou plusieurs associations "clé-valeur" (key-value). On déclare un objet 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";
 monObjet.key1= "value1";

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 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.

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 utile 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. 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. JavaScript permet de déclarer également ses propres fonctions de cette manière :

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

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

Operateurs

Les opérateurs permettent de manipuler des valeurs.

//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 exist é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
a *= 10; //--> 100
a -= 20; //--> 80
a /= 8; //-->10

Dans chaque cas, cette forme est l'équivalent de :

a = a + 5;
a = a * 10;
a = a - 20;
a = a / 8;

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

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 à l'aide des éléments if, else if et else. 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 ou -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
    • ...

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

Le code suivant exécute 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 dans leurs valeurs
  • != détermine si les deux éléments sont différents dans leurs valeurs
  • === détermine si les deux éléments sont similaires dans leurs valeurs et types
  • !== 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

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

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 à AND : implique que les deux conditions liées par cet opérateur soient vraies
  • || équivaut à OR : implique que 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é 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!");
 }

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.

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).

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 incrementer 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);
}

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.

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 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.

À 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 dispoPartout = "Je suis disponible aussi dans les fonctions";

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

logMesVariables(); //--> affiche les deux messages

console.log(dispoPartout); //Le message de la variable dispoPartout sera affiché dans la console
console.log(dispoIci);//La variable dispoIci n'est pas définie --> Erreur dans la console

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 examples 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 addition(a, b) {
     console.log(a + b);
 }
 //2.
 function addition() {
     console.log(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 :

 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, 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 return. 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) {
     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 renvoié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));

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 languages 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 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".

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 function 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 fonction à exécution immédiate, ou Immediately-invoked function expression (IIEF). Comme le nom l'indique, il s'agit de fonctions qui sont exécutée directement lorsqu'elle 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ée à 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")}
)();

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 rétours à 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 dernièrs é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 emboité:

  • 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éré un array en JavaScript. L’un des plus fréquents correspond à l’utilisation d’un cycle for avec una variable qui détermine :

  1. La condition d’entrée qui correspond à 0 car les indices commence à 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(var i=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 example 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 le 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 réç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

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 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:

//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 un exemple pour la méthode toUpperCase() qui transforme les lettres en majuscules.

var msg = "Bonjour";
msg.toUpperCase(); //BONJOUR

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 decimales sont en réalité des approximations, dans la plus part 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 un exemple pour trouver un nombre aléatoire entre 1 et 100 :

var randomNumber = Math.floor((Math.random() * 100) + 1);

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 objects 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 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 :

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 à 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:

//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 fourni 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