Introduction à Javascript

Partie 1 : premiers pas

Javascript, que j’appellerai souvent JS en abrégé, c’est un langage de programmation qui est utilisé dans les navigateurs internet pour rendre les pages dynamiques. On l’utilise aussi dans les serveurs pour réaliser les backends des applications. C’est un langage dynamique qui évolue chaque année, avec un écosystème de librairies très riche et qui a de bonnes performances d’exécution, au moins 4x meilleures que celles de Python par exemple

Pour faire des expérimentations en JS et écrire des petits programmes sans avoir à installer quoi que ce soit, on va utiliser un ‘bac à sable’ JS en ligne, qui est accessible à l’adresse suivante :

https://runjs.jcbuisson.dev

Dans la partie gauche on écrit du code javascript, et dans la partie droite on voit le résultat de l’exécution.

Ici “1+1” constitue une expression JS valide ; elle est évaluée, et sa valeur s’affiche à droite sur fond orange. Si j’ajoute l’instruction " console.log(“Hello World”) “, on a maintenant l’affichage du texte sur la”console" sur fond vert, puis la valeur de la dernière expression. La console, c’est un espace d’affichage sur lequel s’écrivent en continu les messages de console.log() Si on met plusieurs instructions " console.log ", les textes s’afficheront sur la console séparés par un saut de ligne

Ici on a mis les 2 instructions l’une sous l’autre ; jusqu’à il y a peu on devait terminer chaque instruction par ‘;’ C’est une question de préférence ; le ‘;’ est obligatoire si on met plusieurs instructions sur la même ligne (démo : console.log(‘hello’) ; console.log(‘world’))

Quand on écrit un programme il faut respecter strictement la syntaxe ; en cas d’erreur un message d’explication s’affiche en rouge. Les espaces et les sauts de ligne sont en général ignorés

Variables et affectations

Avant de présenter les principaux types de données manipulés par JS, je vais présenter le concept de ’variable" Si j’écris :

let a = 'hello'

‘a’ s’appelle une variable, et je lui affecte la valeur ‘hello’.

On peut aussi utiliser console.log pour afficher la valeur de a :

let a = 'hello' ; console.log('a =', a)

Si on donne plusieurs arguments à console.log, il les affiche tous séparés par un espace

Une variable comme ‘a’, c’est un réceptacle pour une valeur ; on peut l’écraser et lui affecter une autre valeur :

let a = 'hello'
a = "world"

Si on déclare une variable dont on sait que la valeur ne va pas changer, on remplace ‘let’ par ‘const’ Par exemple:

const pi = 3.1415

Ce n’est pas une obligation, mais cela fournit une information au programmeur et cela permet d’optimiser l’exécution

Le nom d’une variable doit commencer par une lettre ou ‘’ et être suivi de lettres, chiffres et ’

Maintenant on va regarder les principaux types de données manipulés par JS

Chaînes de caractères

On peut commencer par le type de données “chaine de caractères” qu’on a déjà vu : “Hello World” est une chaine de caractères (en anglais : ‘string’). On peut l’écrire entre double-quotes ou entre simple-quotes, au choix. Tous les caractères sont possibles, y compris les emojis

Une opération simple qu’on peut faire sur les chaines, c’est la concaténation avec ‘+’ (démo : ‘hello’ + “World” ) On pourrait être étonné qu’il n’y ait pas d’espace, mais en fait c’est normal puisqu’il n’y en a ni dans ‘hello’, ni dans ‘world’. On peut l’écrire aussi : let a = ‘hello’ + “world”

Une autre opération importante, c’est d’obtenir le nombre de caractères d’une chaine : a.length

Nombres

L’autre type de données de base très important, ce sont les nombres. Ils s’écrivent à l’anglo-saxone, avec des ‘.’ pour les nombres à virgule (démo) On écrit les expressions arithmétiques comme au collège, avec des ‘()’ si nécessaire multiplication : ’‘, division :’/’ (démo : (12 + 20)7 ) En JS on ne fait pas de différence entre les nombres entiers et les nombres à virgule ;

Math.floor -> entier inférieur Math.ceil -> entier supérieur Math.round -> entier le plus proche

Affichage sur la console

On va avoir rapidement besoin d’afficher des choses à l’écran, on utilisera pour ça la fonction console.log() :

console.log('hello')
console.log('hello', 'chris', 123)
console.log(2*3+7)

L’affichage a lieu dans un espace appelé ‘console’, où les messages s’affichent les uns derrière les autres. Un saut de ligne est affiché à la fin de chaque exécution de console.log()

Première structure de contrôle : while

Jusqu’ici on n’a vu que des expressions JS et des instructions console.log() Avec ça on ne peut écrire que des successions finies d’instructions console.log() Pour écrire des programmes plus complexes, on va utiliser la structure de contrôle ‘while’ Sa forme générale, c’est :

while (condition) { instructions }

Premier exemple : somme des 100 premiers entiers

let sum = 0
let index = 1
while (index <= 100) {
   sum = sum + index
   index += 1
}
console.log('sum', sum)

Deuxième exemple : affichage de la table de multiplication de 3

const n = 3
let index = 1
while (index <= 9) {
   console.log(n, 'x', index, '=', n*index)
   index += 1
}

Partie 2 : booléens et expressions booléennes

Dans cette partie il va être question des expressions booléennes et des structures de contrôle if et for

Un booléen, c’est un objet JS qui n’a que deux valeurs possibles, true ou false On les a rencontrés dans la condition du while : index <= 100

index <= 100 est une expression booléenne, c’est à dire qu’elle s’évalue un peu à la façon d’une expression arithmétique, pour donner un résultat booléen, true ou false

Un booléen peut être stocké dans une variable comme n’importe quel autre type de données :

let index = 10
let inf100 = (index <= 100)

inf100

Le test d’égalité s’écrit ===, il est valable pour tester l’égalité des chaines, des nombres, des booléens, tous les types

"hello" + "world" === "helloworld"
1+2 === 2
true === false

On peut composer des expressions booléennes entre elles :

index > 1 && index < 9
index === 0 || index > 5
!(index > 1 && index < 9)

Structure de contrôle if

L’écriture générale d’une structure de contrôle if, c’est :

if (condition) {
   instruction
   instruction
   ...
} else {
   instruction
   instruction
   ...
}

A titre d’exemple on va écrire un programme qui affiche tous les nombres entre 1 et 100 qui sont des multiples de 3 et de 5 :

let n = 1
while (n <= 100) {
   if (n % 3 === 0 && n % 5 === 0) {
      console.log(n, "est multiple de 3 et de 5")
   }
   n += 1
}

Structure de contrôle for ; ;

Un exemple :

for (let n = 1; n <= 100; n += 1) {
   if (n % 3 === 0 && n % 5 === 0) {
      console.log(n, "est multiple de 3 et de 5")
   }
}

On utilise plutôt cette écriture au lieu du while lorsqu’on a des itérations basées sur des indices. On verra après d’autres formes de for plus concises

Partie 3 : les fonctions

Cette partie va être centrée sur la notion de fonction

Une fonction, c’est un bloc d’instructions qu’on peut exécuter avec des variables paramètres, et ensuite ré-exécuter avec d’autres valeurs de paramètres, autant qu’on le veut.

Par exemple :

function square(x) {
   return x*x
}

Par cette écriture avec le mot clé ‘function’, j’ai défini une function appelée square. Elle a un seul paramètre, la variable x Elle renvoie une valeur, par utilisation du mot-clé ‘return’

Le corps de la fonction peut comporter plusieurs instructions, des structures de contrôle, etc. J’aurais pu écrire :

function square(x) {
   console.log('x', x)
   const value = x*x
   return value
}

La fonction est seulement définie, mais pas encore exécutée. Pour l’exécuter, on écrit par exemple :

square(2)
square(3)

Ici on a exécuté (on dit aussi ‘appelé’) la fonction deux fois, avec des valeurs différentes pour les paramètres. On appelle ces valeurs les ‘arguments’ : ‘2’ est un ‘argument’ d’appel, et ‘x’ est un ‘paramètre’

On peut reprendre l’exemple de la table de multiplication et en faire une fonction :

function displayMultiply(n) {
   for (let i = 1; i <= 9; i++) {
      console.log(n, 'x', i, '=', n*i)
   }
}

for (let n = 2; n < 10; n += 1) {
   displayMultiply(n)
}

On voit que cela rend le code plus lisible, sans répétition.

On peut créer des fonctions qui appellent d’autres fonctions :

function distance(x1, y1, x2, y2) {
   return Math.sqrt(square(x1 - x2), square(y1 - y2))
}

Il est fréquent aussi de définir des fonctions récursives, qui s’appellent elles-mêmes :

function factorial(n) {
   if (n < 2) {
      return 1
   } else {
      return n * factorial(n-1)
   }
}

On peut l’écrire aussi :

function factorial(n) {
   if (n < 2) return 1
   return n * factorial(n-1)
}

C’est un mode de conception de code très important, mais qui demande du temps pour être maitrisé.

On peut essayer sur un autre exemple numérique, la suite de Fibonacci : 1, 1, 2, 3, etc. Les deux premiers éléments sont 1 et 1, ensuite chaque élement suivant est la somme des deux précédents

function fibo(n) {
   if (n <= 1) return 1
   return fibo(n-1) + fibo(n-2)
}

En fait les fonctions sont des valeurs comme les autres en JS, comme les nombres, les chaines, les booléens. Si je tape ça :

square

square est devenu le nom d’une variable dont la valeur a le type ‘function’

typeof(square)

On peut les affecter, les passer en paramètre, etc. Je peux écrire :

const f = square
f(2)

Partie 4 : les objets

Cette partie va être centrée sur la notion d’objet et de dictionnaires

Un objet javascript, c’est essentiellement un dictionnaire clé/valeurs

Par exemple:

const person = {
   lastname: "Potter",
   firstname: "Harry"
}

Ces éléments à gauche s’appelent les ‘propriétés’ de l’objet (on dit parfois ‘clé’); les valeurs à droites sont les valeurs associées aux propriétés.

Pour accéder aux valeurs, on écrit :

person.firstname
person.firstname = "James"

Les propriétés sont toujours de chaînes et on peut d’ailleurs l’écrire :

const person = {
   "lastname": "Potter",
   "firstname": "Harry"
}

On doit le faire d’ailleurs si la propriété comporte des caractères spéciaux comme des espaces : "best friend": "Ron"

On peut aussi écrire :

person['firstname']
person['best friend']

Cette écriture permet d’accéder à une propriété dont la valeur est calculée, par exemple

const key = 'lastname'
person[key]

Les clés sont toujours des chaines de caractères, les valeurs peuvent être n’importe quoi : nombres, chaines, autres objets, tableaux, fonctions etc.

Par exemple dansMath.round(3.14), Math est un objet JS et round est une clé (on dit aussi une propriété) de Math, dont la valeur est une fonction

Dans l’exemple suivant, des objets sont emboités :

const fred = {
   fullname: "Frédérique Arnal",
   income: 34500,
   partTime: false,
   employer: {
      name: "Acme",
      address: "23 rue des arts, 75001 Paris",
   }
}
fred.fullname
fred.employer
fred.employer.address

Pour tester si un objet obj possède la clé key :

(key in obj)
'round' in Math
'address' in fred.employer

Pour itérer sur les propriétés d’un objet :

for (const key in fred) {
   console.log('key', key)
}

for (const key in fred) {
   console.log('key', key, 'value', person[key])
}

Les objets comme librairies

On se sert souvent des objets pour mettre ensemble des fonctions :

function fact(n) {
   if (n < 2) return 1; else return n*fact(n-1)
}
function fib(n) {
   if (n < 2) return 1; else return fib(n-1)+fib(n-2)
}

const MyMath = {
   fact,
   fib,
}

Ici on a utilisé un raccourci, car cette notation est équivalente à :

const MyMath = { fact: fact, fib: fact, }

MyMath.fact(5)
MyMath.fib(6)

Math.sqrt(25)
Math.round(3.4)

Partie 5 : les tableaux

Cette partie va être centrée autour de la notion de tableau et d’itérables

En JS un tableau, c’est une suite de valeurs quelconques, par exemple :

const array = [1, 2, "hello", 3.14]
array

Pour accéder au nombre d’élements du tableau, c’est comme pour les chaines, .length

array.length

Pour accéder au premier élément: array[0] ; le dernier : array[3]

On peut modifier un élément : array[0] = 11

Pour ajouter un nouvel élement à la fin d’un tableau, il faut appeler la méthode push :

array.push(100)
array

Pour enlever le dernier, pop()

Trier un tableau : array.sort() Par défaut sort() trie les tableaux de chaines, ou d’éléments qui sont convertis en chaines

const array = ['a', 'y', 'u', 'o', 'i']
array.sort()
"az" < "as"

Pour tester la présence d’un élément dans un tableau : array.includes(2)

Pour obtenir l’index d’un élément : array.indexOf(2) (-1 si non présent)

Les itérables

Un tableau est un itérable, ce qui permet de parcourir la liste de ses valeurs avec la structure for...of

const vowels = ['a', 'e', 'i', 'o', 'u', 'y']
for (const vowel of vowels) {
   console.log('vowel', vowel)
}

Une chaine de caractères est également un itérable :

const vowels = "aeiouy"
for (const vowel of vowels) {
   console.log('vowel', vowel)
}

On va terminer en reprenant les différents types de structure for

for ; ;

S’adapte à toutes les situations, mais peu lisible avec sa gestion des indices Par exemple:

for (let i = 0; i < 9; i++) {
   console.log("3 x", i, "=", 3*i)
}

for ... of

Uniquement pour les itérables : tableaux, chaines de caractères Par exemple:

for (const letter of "azertyuiop") {
   const isVowel = "aeiou".includes(letter)
   console.log(letter, isVowel ? "est une voyelle" : "est une consonne")
}

for ... in

Rarement utilisé, uniquement pour les objets (dictionnaires) : énumère seulement les clés

Exemple :

function stringify(obj) {
   let result = ""
   for (const key in obj) {
      if (result.length > 0) result += ", "
      result += '"' + key + '": "' + obj[key] + '"'
   }
   return "{" + result + "}"
}

break / continue

Toutes ces structures for, et ausisi ‘while’, permettent d’utiliser break pour sortir avant la fin, et continue pour interrompre l’itération courante et passer à la suivante. Exemple :

function stringify(obj) {
   let result = ""
   for (const key in obj) {
      if (key === 'id') continue
      if (result.length > 0) result += ", "
      result += '"' + key + '": "' + obj[key] + '"'
   }
   return "{" + result + "}"
}
let word = ""
for (let letter of "azer,tyuiop") {
   if (letter === ',') break
   word += letter
}