|
|
---
|
|
|
gitea: none
|
|
|
|
|
|
include_toc: true
|
|
|
|
|
|
---
|
|
|
|
|
|
[TOC]
|
|
|
|
|
|
# JavaScript et TypeScript
|
|
|
|
|
|
Au semestre précédent, nous avons utilisé Brython afin d'exécuter du Python dans le navigateur. En réalité Brython transforme le code Python en JavaScript qui est ensuite interprété par le navigateur. En effet, le navigateur ne peut exécuter que deux langages :
|
|
|
|
|
|
- **WASM** : une sorte de langage bas niveau vers lequel d'autres languages peuvent être compilés (e.g. C, C++, Rust, Java, etc).
|
|
|
|
|
|
- **JavaScript**
|
|
|
|
|
|
JavaScript signale uniquement les erreurs d'exécutions. Ainsi certaines erreurs de programmations peuvent être silencieuses, ou ne pas être détectées lors de vos tests. Nous utiliserons TypeScript, un sur-ensemble de JavaScript permettant de détecter des erreurs en amont, facilitant grandement les étapes de tests et de développements.
|
|
|
|
|
|
Typescript permet d'indiquer le type des variables permettant à la fois de documenter l'usage des fonctions, mais aussi de vérifier et garantir qu'une fonction est bien appelée avec les bons paramètres. Ainsi en à peine quelques millisecondes, Typescript est capable de vous avertir d'erreurs de programmations que vous pourriez ne pas détecter, puis passer une journée à chercher. Il facilite aussi grandement les étapes de refactoring, e.g. lorsque la signature d'une fonction change, et requiert alors de changer son appel dans l'intégralité de votre code.
|
|
|
|
|
|
Au semestre précédent, nous avons utilisé l'API JS/DOM via Brython. Nous utiliserons la même API ce semestre, i.e. vous réutiliserez les mêmes fonctions et paramètres, seul le langage utlisé change.
|
|
|
|
|
|
## Utilisation de JavaScript
|
|
|
|
|
|
```html
|
|
|
<!DOCTYPE html>
|
|
|
<html>
|
|
|
<head>
|
|
|
<!-- ... -->
|
|
|
<script src="$JS_FILE" type="module" defer></script>
|
|
|
</head>
|
|
|
<body>
|
|
|
</body>
|
|
|
</html>
|
|
|
```
|
|
|
|
|
|
## Utilisation de TypeScript
|
|
|
|
|
|
TypeScript est tout d'abord converti en JavaScript à l'aide de la commande shell `tsc`. Les options sont soient données en paramètre de la commande, ou indiquées dans le fichier `tsconfig.json`.
|
|
|
|
|
|
L'option `--watch` permet de générer les fichiers JS à chaque modifications du fichier TS correspondant. Son avantage majeur est d'intégrer un cache en RAM permettant d'éviter de re-générer les fichiers JS de fichiers TS non-modifiés. Il permet ainsi un gain de temps significatif lors du développement, passant de plusieurs minutes de traduction pour de gros projets, à quelques millisecondes.
|
|
|
|
|
|
## Exécution de TypeScript côté serveur
|
|
|
|
|
|
JavaScript et TypeScript peuvent non seulement s'exécuter sur le navigateur, côté client, mais aussi côté serveur à l'aide d'interpréteurs comme `Node` ou `Deno`. Utiliser le même langage côté client et côté serveur possède plusieurs avantages :
|
|
|
|
|
|
- **factoriser** des parties de codes utilisés à la fois côté client et côté serveur.
|
|
|
|
|
|
- **déplacer** aisément des calculs du côté serveur vers le côté client et inversement.
|
|
|
|
|
|
- évite d'avoir à apprendre et **maîtriser deux langages** différents.
|
|
|
|
|
|
Dans le cadre de ce module, nous utiliserons `Deno` qui permet d'exécuter directement des fichiers TS sans avoir à générer des fichiers JS via `tsc`.
|
|
|
|
|
|
Nous étudierons plus en détails `Deno` dans le cours suivant.
|
|
|
|
|
|
# Types et structures de données natives
|
|
|
|
|
|
## Déclaration d'une variable
|
|
|
|
|
|
Contrairement à Python, JS possède 3 manières de déclarer une variable :
|
|
|
|
|
|
```javascript
|
|
|
let a = ...; // "block-scoped".
|
|
|
var a = ...; // "function-scoped".
|
|
|
const A = ...; // une constante, i.e. ne peut être modifiée.
|
|
|
```
|
|
|
|
|
|
*Note:* contrairement à Python, JS n'a pas besoin du mot clef `global` pour accéder à une variable globale. L'object `globalThis` contient l'ensemble des variables globales.
|
|
|
|
|
|
## Types de bases
|
|
|
|
|
|
JavaScript distingue 6 types de base :
|
|
|
|
|
|
| Déclaration | JS Type | Python Type |
|
|
|
| -------------------- | ----------- | ------------ |
|
|
|
| `let a = 42;` | `number` | `float` |
|
|
|
| `let a = true;` | `boolean` | `bool` |
|
|
|
| `let a = "str";` | `string` | `str` |
|
|
|
| `let a = undefined;` | `undefined` | ≈ `NoneType` |
|
|
|
| `let a = {a: 42}` | `object` | ≈ `dict` |
|
|
|
| `let a = foo;` | `function` | `function` |
|
|
|
|
|
|
Il existe plusieurs valeurs spéciales :
|
|
|
|
|
|
| Valeur | JS Type | En Python | Remarques |
|
|
|
| -------------------------- | ----------- | ----------------- | ------------------------------- |
|
|
|
| `NaN` | `number` | `float('nan')` | Not a Number (e.g. 0/0) |
|
|
|
| `Number.POSITIVE_INFINITY` | `number` | `float('inf')` | |
|
|
|
| `Number.NEGATIVE_INFINITY` | `number` | `float('-inf')` | |
|
|
|
| `0b01010111` | `number` | `0b01010111` | Nombre en binaire. |
|
|
|
| `0o777` | `number` | `0o777` | Nombre en octal |
|
|
|
| `0xFF` | `number` | `0xFF` | Nombre en hexadécimal |
|
|
|
| `1.2e2` | `number` | `1.2e2` | Nombre en notation scientifique |
|
|
|
| `true` | `boolean` | `True` | |
|
|
|
| `false` | `boolean` | `False` | |
|
|
|
| `` `val: ${value}` `` | `string` | `f"val: {value}"` | littéraux de gabarits |
|
|
|
| `null` | `object` | ≈ `None` | valeur "pas de valeurs" |
|
|
|
| `undefined` | `undefined` | ≈ `None` | valeur inexistante |
|
|
|
|
|
|
Pour retrouver le type d'une variable, vous pouvez utiliser `typeof $VAR`, qui est l'équivalent de `type($VAR)` en Python.
|
|
|
|
|
|
# Structures de données <mark>[TODO]</mark>
|
|
|
|
|
|
base object/array (vs tupple list python)
|
|
|
|
|
|
## Opérateurs
|
|
|
|
|
|
JavaScript utilise les mêmes opérateurs que Python à quelques exceptions près.
|
|
|
|
|
|
### Opérateurs bit à bits :
|
|
|
|
|
|
| Opérateur | Nom |
|
|
|
| --------- | ----------- |
|
|
|
| `a\|b` | OU binaire |
|
|
|
| `a&b` | ET binaire |
|
|
|
| `a^b` | XOR binaire |
|
|
|
| `~a` | NOT binaire |
|
|
|
|
|
|
### Opérateurs logique
|
|
|
|
|
|
| JavaScript | Python | Commentaires |
|
|
|
| ---------- | --------- | --------------------- |
|
|
|
| `a\|\|b` | `a or b` | OU logique |
|
|
|
| `a&&b` | `a and b` | ET logique |
|
|
|
| `!a` | `not a` | NON logique |
|
|
|
| `a??b` | | Coallescence des nuls |
|
|
|
|
|
|
💡 *Astuce :* l'opérateur de coallescence des nuls peut être utilisé pour indiquer des valeurs par défauts :
|
|
|
|
|
|
```javascript
|
|
|
let a ??= b; // si a est null ou undefined, a = b.
|
|
|
let a ||= b; // si a est évalué à false, a = b
|
|
|
```
|
|
|
|
|
|
### Opérateurs de comparaison
|
|
|
|
|
|
| JavaScript | Python | Commentaires |
|
|
|
| ---------- | ------------ | ---------------------------- |
|
|
|
| `a == b` | `a == b` | égalité de valeur (à éviter) |
|
|
|
| `a != b` | `a != b` | |
|
|
|
| `a === b` | `a is b` | égalité stricte |
|
|
|
| `a !== b` | `a is not b` | |
|
|
|
|
|
|
Opérateurs communs : `>`, `>=`, `<`, `<=`.
|
|
|
|
|
|
### Opérateurs arithmétiques
|
|
|
|
|
|
Opérateurs communs : `+` (binaire et unaire), `-` (binaire et unaire), `/`, `%`, `*`, `**`
|
|
|
|
|
|
| JavaScript | Python | Commentaires |
|
|
|
| ---------- | ------ | ---------------------------------- |
|
|
|
| `++a` | `a+=1` | incrément |
|
|
|
| `a++` | | retourne la valeur puis incrémente |
|
|
|
| `--a` | `a-=1` | décrément |
|
|
|
| `a--` | | retourne la valeur puis décrémente |
|
|
|
|
|
|
### Opérateurs d'affectations
|
|
|
|
|
|
Comme en python, il s'agit des opérateurs arithmétiques suffixé d'un `=`.
|
|
|
|
|
|
Par exemple `a += b` est équivalent à `a = a+b`.
|
|
|
|
|
|
### Autres opérateurs <mark>[TODO]</mark>
|
|
|
|
|
|
- destructuration / décomposition / chaînage opt (.?)
|
|
|
- []
|
|
|
- in
|
|
|
- delete
|
|
|
|
|
|
### Conversions
|
|
|
|
|
|
```javascript
|
|
|
let a = +$VALUE; // number
|
|
|
let a = !!$VALUE; // boolean
|
|
|
let a = (5).toString(); // string "5"
|
|
|
let a = (5).toString(2);// string "101"
|
|
|
```
|
|
|
|
|
|
📖 `0`, `""`, `null`, `undefined`, sont évalués à `false`.
|
|
|
|
|
|
|
|
|
## Indications de type avec Typescript
|
|
|
|
|
|
### Indication explicite de type
|
|
|
|
|
|
```typescript
|
|
|
let a = 42; // TS déduit que a est un number.
|
|
|
let a: number = 42; // on indique explicitement le type.
|
|
|
```
|
|
|
|
|
|
### Union de types
|
|
|
|
|
|
Il arrive qu'une variable puisse prendre des valeurs de plusieurs types différents :
|
|
|
|
|
|
```typescript
|
|
|
let a = 42; // TS déduit que a est un number.
|
|
|
a = "42"; // erreur, a ne peut être qu'un number.
|
|
|
let a: number | string = 42;
|
|
|
a = "42"; // légal
|
|
|
```
|
|
|
|
|
|
### Valeur optionnelle
|
|
|
|
|
|
Il arrive qu'une variable puisse ne pas avoir de valeurs à l'initialisation :
|
|
|
|
|
|
```javascript
|
|
|
let a: number; // erreur.
|
|
|
let a: number|undefined; // légal
|
|
|
```
|
|
|
|
|
|
### Alias de types
|
|
|
|
|
|
<mark>TODO: intérêt</mark>
|
|
|
|
|
|
```typescript
|
|
|
type X = number | string;
|
|
|
let a: X = 42; // équivaut à let a: number | string = 42;
|
|
|
```
|
|
|
|
|
|
### TS typeof
|
|
|
|
|
|
⚠ Il existe 2 `typeof`, un JS qui déduit le type de la **valeur** à l'exécution, et un TS qui, dans les indications de types, indique le type TS de la **variable**.
|
|
|
|
|
|
```typescript
|
|
|
type A = typeof a; // TS, number | string
|
|
|
console.log(typeof a); // JS, string
|
|
|
```
|
|
|
|
|
|
### Types pour les structures de données
|
|
|
|
|
|
- generics TS `Array<X>` / types array / `Record<x, y>` / typescript []
|
|
|
|
|
|
# Structures de contrôle
|
|
|
|
|
|
## Conditions
|
|
|
|
|
|
```javascript
|
|
|
// [JS] Javascript
|
|
|
|
|
|
if( $COND2 ) {
|
|
|
|
|
|
} else if($COND2) {
|
|
|
|
|
|
} else {
|
|
|
|
|
|
}
|
|
|
```
|
|
|
|
|
|
```python
|
|
|
# [🐍] Python
|
|
|
if $COND1:
|
|
|
pass
|
|
|
elif $COND2
|
|
|
pass
|
|
|
else
|
|
|
pass
|
|
|
```
|
|
|
|
|
|
## Opérateur ternaire
|
|
|
|
|
|
```javascript
|
|
|
// [JS] Javascript
|
|
|
|
|
|
let a = $COND ? $IF_TRUE : $IF_FALSE
|
|
|
let a = $COND
|
|
|
? $IF_TRUE
|
|
|
: $IF_FALSE
|
|
|
```
|
|
|
|
|
|
```python
|
|
|
# [🐍] Python
|
|
|
|
|
|
a = $IF_TRUE if $COND else $IF_FALSE
|
|
|
```
|
|
|
|
|
|
## Switch
|
|
|
|
|
|
```javascript
|
|
|
// [JS] Javascript
|
|
|
switch(value) {
|
|
|
case 'value':
|
|
|
//...
|
|
|
break;
|
|
|
default:
|
|
|
//...
|
|
|
}
|
|
|
```
|
|
|
|
|
|
```python
|
|
|
# [🐍] Python
|
|
|
match value:
|
|
|
case 'value':
|
|
|
pass
|
|
|
case _:
|
|
|
pass
|
|
|
```
|
|
|
|
|
|
## Boucles
|
|
|
|
|
|
### While
|
|
|
|
|
|
```javascript
|
|
|
// [JS] Javascript
|
|
|
while($COND) {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
```python
|
|
|
# [🐍] Python
|
|
|
while $COND:
|
|
|
pass
|
|
|
```
|
|
|
|
|
|
### Do while
|
|
|
|
|
|
```javascript
|
|
|
// [JS] Javascript
|
|
|
do {
|
|
|
// s'exécute au moins une fois.
|
|
|
} while( $COND );
|
|
|
```
|
|
|
|
|
|
### For in (parcours les clefs)
|
|
|
|
|
|
```javascript
|
|
|
// [JS] Javascript
|
|
|
for( let value in $OBJ ) {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### For of (parcours les valeurs)
|
|
|
|
|
|
```javascript
|
|
|
// [JS] Javascript
|
|
|
for( let value of $OBJ ) {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
## Exceptions
|
|
|
|
|
|
```javascript
|
|
|
// [JS] Javascript
|
|
|
try {
|
|
|
throw new Error($MESSAGE)
|
|
|
} catch(error) {
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
}
|
|
|
```
|
|
|
|
|
|
```python
|
|
|
# [🐍] Python
|
|
|
try:
|
|
|
raise Exception($MESSAGE)
|
|
|
except Exception as error:
|
|
|
pass
|
|
|
finally:
|
|
|
pass
|
|
|
```
|
|
|
|
|
|
# Fonctions
|
|
|
|
|
|
## Déclaration
|
|
|
|
|
|
```javascript
|
|
|
// [JS] JavaScript
|
|
|
function foo(arg1, arg2 = "2") {
|
|
|
//...
|
|
|
return 2.3;
|
|
|
}
|
|
|
foo(1)
|
|
|
```
|
|
|
|
|
|
```python
|
|
|
# [🐍] Python
|
|
|
def foo(arg1, arg2 = "2", /): # les paramètres positionnel uniquement
|
|
|
# ...
|
|
|
return 2.3
|
|
|
|
|
|
foo(1)
|
|
|
```
|
|
|
|
|
|
```typescript
|
|
|
//[TS] TypeScript
|
|
|
function foo(arg1: number, arg2?: string = "2"): number {
|
|
|
// ...
|
|
|
return 2.3;
|
|
|
}
|
|
|
|
|
|
foo(1)
|
|
|
```
|
|
|
|
|
|
## Paramètre du reste (rest parameter)
|
|
|
|
|
|
```javascript
|
|
|
// [JS] JavaScript
|
|
|
function foo(arg1, ...arg2) {
|
|
|
// arg2 = ["2", "3"]
|
|
|
return 2.3;
|
|
|
}
|
|
|
foo(1, "2", "3")
|
|
|
```
|
|
|
|
|
|
```python
|
|
|
# [🐍] Python
|
|
|
def foo(arg1, /, *arg2):
|
|
|
# arg2 = ("2", "3")
|
|
|
return 2.3
|
|
|
|
|
|
foo(1, "2", "3")
|
|
|
```
|
|
|
|
|
|
```typescript
|
|
|
//[TS] TypeScript
|
|
|
function foo(arg1: number, ...arg2: readonly string[]): number {
|
|
|
// arg2 = ["2", "3"]
|
|
|
return 2.3;
|
|
|
}
|
|
|
|
|
|
foo(1, "2", "3")
|
|
|
```
|
|
|
|
|
|
## Opérateur de décomposition (spread operator) comme argument
|
|
|
|
|
|
```javascript
|
|
|
// [JS] JavaScript
|
|
|
function foo(arg1, arg2, arg3) {
|
|
|
//...
|
|
|
return 2.3;
|
|
|
}
|
|
|
const args = ["2", "3"];
|
|
|
foo(1, ...args)
|
|
|
```
|
|
|
|
|
|
```python
|
|
|
# [🐍] Python
|
|
|
def foo(arg1, arg2, arg3, /):
|
|
|
# ...
|
|
|
return 2.3
|
|
|
|
|
|
args = ("2", "3")
|
|
|
foo(1, *args )
|
|
|
```
|
|
|
|
|
|
```typescript
|
|
|
//[TS] TypeScript
|
|
|
function foo(arg1: number, arg2: string, arg3: string): number {
|
|
|
return 2.3;
|
|
|
}
|
|
|
const args = ["2", "3"] as const; // ou as ["string", "string"]
|
|
|
foo(1, ...args)
|
|
|
```
|
|
|
|
|
|
## Fonctions génératrices
|
|
|
|
|
|
<mark>TODO: utilité</mark>
|
|
|
|
|
|
```javascript
|
|
|
// [JS] JavaScript
|
|
|
function * foo(nb) {
|
|
|
for(let i = 0; i < nb; ++i)
|
|
|
yield i;
|
|
|
}
|
|
|
|
|
|
for( let val of foo(5) )
|
|
|
console.log(val);
|
|
|
```
|
|
|
|
|
|
```python
|
|
|
# [🐍] Python
|
|
|
def foo(nb, /) {
|
|
|
for i in range(nb):
|
|
|
yield i;
|
|
|
}
|
|
|
|
|
|
for val in foo(5)
|
|
|
console.log(val);
|
|
|
```
|
|
|
|
|
|
```typescript
|
|
|
//[TS] TypeScript
|
|
|
function * foo(nb: number): Generator<number> {
|
|
|
for(let i = 0; i < nb; ++i)
|
|
|
yield i;
|
|
|
}
|
|
|
|
|
|
for(let val of foo(5) )
|
|
|
console.log(val);
|
|
|
```
|
|
|
|
|
|
## Fonctions fléchées
|
|
|
|
|
|
<mark>TODO</mark>: pas d'équivalent en python + utilité (callbacks)
|
|
|
|
|
|
```javascript
|
|
|
const foo = arg => arg[0]; // est équivalent à :
|
|
|
const foo = function(arg){ return arg[0]; }
|
|
|
|
|
|
// si plusieurs paramètres, utiliser des parenthèses ().
|
|
|
// si valeur retournée plus complexe, utiliser des accolades {}.
|
|
|
const foo = (arg1, args) => { ... ; return x; } // est équivalent à :
|
|
|
const foo = function(arg1, arg2){ ... ; return x; }
|
|
|
```
|
|
|
|
|
|
# Asynchronisme
|
|
|
|
|
|
/!\ Diff with Python
|
|
|
|
|
|
- Promise
|
|
|
|
|
|
- motivation + pas bloquer thread principal
|
|
|
|
|
|
# CM2
|
|
|
|
|
|
## Fonctions avancées ?
|
|
|
|
|
|
## Classes
|
|
|
|
|
|
- class + getter/setter + private/protected + interface + iterator / async inter / héritage + fonctionnement prototype (méthode => fct et inversement + bind)
|
|
|
|
|
|
- - ts enum + mixins
|
|
|
- + well-known symbols
|
|
|
|
|
|
## Importations et exportations (CM2?)
|
|
|
|
|
|
## Quelques API utiles (CM2 ?)
|
|
|
|
|
|
- Math API
|
|
|
- Crypto
|
|
|
- Date / RegExp
|
|
|
- object / array / Map / Set / string APIs
|
|
|
|
|
|
## Futur
|
|
|
|
|
|
- Manipuler URL => move 2 JS-DOM API ?
|
|
|
|
|
|
- console/assert => move 2 JS-DOM API ?
|