Cyrille Perois
Lead front-end developer @ Wandi Teaches front-end development @ IUT Paris Descartes
Programmation web - Client riche
Les différentes parties
Le langage et ses API
L'environnement dans lequel on l'exécute (API spécifiques)
Ce qu'on va explorer ensemble
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello world</title>
<script type="module" src="./app.js"></script>
</head>
<body>
<h1>Hello world</h1>
</body>
</html>
monprojet ├── app.js └── index.html
// Les commentaires sur une seule ligne
/*
les commentaires
sur plusieurs lignes
*/
// Déclaration de la variable
let myVariable
// Affectation d'une valeur
myVariable = "Hello, world !"
// Déclaration et affectation
let myFirstVar = "Hello"
// Réassignation de la valeur d'une variable
let myVariable = "Hello world !"
myVariable = "Vous voulez un whisky ?"
// Déclaration et affectation
const myVariable = "Hello, world !"
const hello = "Hello world !"
hello = "Vous voulez un whisky ?"
// => ReferenceError
// Impossible de réaffecter une constante
Vous verrez peut-être des scripts utiliser le mot-clef var pour déclarer une variable. C'est l'ancienne méthode. Oubliez totalement ce mot-clef, qui est aujourd'hui remplacé par let
JS est un langage à typage dynamique et faible.
Le type d'une variable est donc :
const integer = 8000
const decimal = 123.456
// addition
8000 + 42 // => 8042
// soustraction
8000 - 42 // => 7958
// multiplication
13 * 37 // => 481
// division
8000 / 42 // => 190.476190476
// exponentiation
2 ** 3 // => 8 (2 puissance 3, quoi)
8000 / 0 // => Infinity
-8000 / 0 // => -Infinity
"Everything but a number" / 8000 // => NaN
"Everything but a number" / 8000 + 42 // => NaN
"Hello, world !"
'Hello, world !'
`Hello, world !`
const who = "world";
"Hello, " + who + " !"
`Hello ${who} !`
// => "Hello, world !"
`The result of 1 + 1 is ${1 + 1}`
// => "The result of 1 + 1 is 2"
const ok = true
const notOk = false
const nullValue = null
let undefinedValue
console.log(undefinedValue) // => undefined
const explicitUndefined = undefined
On a le conteneur (la variable) et quelque chose de vide dedans (null)
On a le conteneur (la variable), mais absolument rien dedans (undefined)
const me = {
firstname: "Cyrille",
age: 28
}
me.firstname // => "Cyrile"
me.age // => 28
me.firstname = "George"
me.firstname // => "George"
me.job = "developer and teacher"
me.job // "developer and teacher"
const number = 123.456
number.toFixed(2) // => 123.46
const str = "Hello world !"
str.toUpperCase() // => HELLO WORLD !
const name = prompt("What's your name ?")
if (name === "Cyrille") {
alert("Me too !")
} else if (name === "Toto") {
alert("Srsly?")
} else {
alert(`Hello ${name} !`)
}
10 < 20 // => true
10 <= 20 // => true
20 > 10 // => true
20 >= 10 // => true
20 == 20 // => true
10 != 20 // => true
"hello" == "hello" // => true
"hello" != "world" // => true
10 == "10" // => true
20 != "20" // => false
😱
10 === "10" // => false
20 !== "20" // => true
🤗
Privilégier les opérateurs stricts (=== et !==) pour éviter la conversion implicite de type
true && true // => true
true && false // => false
true || true // => true
true || false // => true
false || false // => false
!true // => false
!false // => true
10 && "hello" // => "hello"
0 && "hello" // => 0
10 || "hello" // => 10
0 || "hello" // => "hello"
!"hello" // => false
Conversion automatique des valeurs en booléen afin de déterminer si la valeur "correspond" à true (valeur truthy) ou false (valeur falsy)
Renvoi de la première (||) ou de la dernière (&&) valeur truthy
let i = 0
while (i < 10) {
console.log(i)
++i
}
let j = 0
do {
console.log(j)
++j
} while (j < 10)
for (let k = 0; k < 10; ++k) {
console.log(k)
}
// => 0 1 2 3 4 5 6 7 8 9
const addTwoNumbers = (number1, number2) => {
return number1 + number2
}
const addTwoNumbers = (number1, number2) => number1 + number2
addTwoNumbers(8000, 42) // => 8042
const sayHello = (who = "World") => {
return `Hello ${who}`
}
sayHello("Tom") // => Hello Tom
sayHello() // => Hello World
sayHello(null) // => Hello
sayHello(undefined) // => Hello World
La valeur par défaut d'un paramètre est utilisée si ce paramètre reçoit la valeur undefined (explicitement ou implicitement)
const addNumbers = (number1) => {
const addNumber1ToNumber2 = (number2) => {
return number1 + number2
}
return addNumber1ToNumber2
}
const add3 = addNumbers(3)
add3(2) // => 5 (3 + 2)
addNumbers(3)(2) // => 5
Une fonction crée à l'intérieur d'une autre fonction a accès au scope de sa fonction parent (même une fois que la fonction parent a return). On appelle cette fonction une "fermeture" ou "closure"
const applyFunctionOnValue = (value, f) => {
return f(value)
}
const add2 = (n) => n + 2
applyFunctionOnValue(2, add2) // => 4 (2 + 2)
applyFunctionOnValue(2, (n) => n + 2) // 4
Les fonctions sont des valeurs comme les autres : on peut les passer en paramètre d'une fonction
Il existe aussi le mot-clef function pour définir une fonction. Il faut l'avoir en tête, mais nous n'utiliserons que les fonctions fléchées, parce qu'elles sont plus récentes et apportent moins de concepts obscurs et implicites avec elles
const emptyArray = []
const animals = ["cat", "dog", "mouse"]
animals[0] // => "cat"
animals[1] // => "dog"
animals[2] // => "mouse"
animals.length // => 3
animals[1] = "parrot"
animals.push("rat")
// => ["cat", "parrot", "mouse", "rat"] (modifie le tableau)
[...animals, "rat"]
// => ["cat", "parrot", "mouse", "rat"] (crée un nouveau tableau)
["rat", ...animals]
// => ["rat", "cat", "parrot", "mouse"] (crée un nouveau tableau)
animals.slice(0, 2)
// => ["cat", "parrot"] (nouveau tableau)
const fruits = ["Apple", "Banana", "Strawberry"]
for (let i = 0, length = fruits.length; i < length; ++i) {
console.log(fruits[i])
}
for (let fruit of fruits) {
console.log(fruit)
}
fruits.forEach((fruit) => console.log(fruit))
// => "Apple" "Banana" "Strawberry"
fruits.map((fruit) => fruit.toUpperCase())
// => ["APPLE", "BANANA", "STRAWBERRY"] (nouveau tableau)
Un fichier JS est un module, et on peut définir ce que ce module expose au monde extérieur en exportant les valeurs qu'on veut :
export const add = (a, b) => a + b
export const difference = (a, b) => a - b
export const multiply = (a, b) => a * b
On peut ensuite importer ces valeurs à partir d'un autre module :
import { add, difference } from "./math.js"
const mySuperComplicatedFunction = () => {
// do some complicated stuff
const resultAdd = add(3, 2)
const resultDifference = difference(2, 3)
}
Les exports d'un module peuvent être de deux types :
const add = (a, b) => a + b
export default add
import add from "./math.js"
add(3, 2)
Nous préférerons nous contenter des exports nommés. Ils nous garantissent une meilleure stabilité dans les noms utilisés à travers les modules, donc une plus grande facilité de refactoring.
Les exports par défaut existent principalement pour des raisons de compatibilité avec le système de modules CommonJS, utilisé par NodeJS avant que les modules standards n'aient vu le jour
Nous n'utiliserons pas à 100% le système de modules natif, car l'implémentation n'est pas encore optimale dans les navigateurs. On utilisera la syntaxe, mais on utilisera un bundler (Parcel) pour compiler nos modules en bundles prêts à être envoyés dans le navigateur.
By Cyrille Perois