You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

14 KiB

Table of Contents

[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

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

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 [TODO]

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 :

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 [TODO]

  • destructuration / décomposition / chaînage opt (.?)
  • []
  • in
  • delete

Conversions

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

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 :

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 :

let a: number; // erreur.
let a: number|undefined; // légal

Alias de types

TODO: intérêt

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.

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

// [JS] Javascript

if( $COND2 ) {

} else if($COND2) {

} else {

}
# [🐍] Python
if $COND1:
    pass
elif $COND2
    pass
else
    pass

Opérateur ternaire

// [JS] Javascript

let a = $COND ? $IF_TRUE : $IF_FALSE
let a = $COND
          ? $IF_TRUE
          : $IF_FALSE
# [🐍] Python

a = $IF_TRUE if $COND else $IF_FALSE

Switch

// [JS] Javascript
switch(value) {
    case 'value':
        //...
        break;
    default:
        //...   
}
# [🐍] Python
match value:
    case 'value':
        pass
    case _:
        pass

Boucles

While

// [JS] Javascript
while($COND) {
}
# [🐍] Python
while $COND:
    pass

Do while

// [JS] Javascript
do {
    // s'exécute au moins une fois.
} while( $COND );

For in (parcours les clefs)

// [JS] Javascript
for( let value in $OBJ ) {
}

For of (parcours les valeurs)

// [JS] Javascript
for( let value of $OBJ ) {
}

Exceptions

// [JS] Javascript
try {
    throw new Error($MESSAGE)
} catch(error) {

} finally {

}
# [🐍] Python
try:
    raise Exception($MESSAGE)
except Exception as error:
    pass
finally:
    pass

Fonctions

Déclaration

// [JS] JavaScript
function foo(arg1, arg2 = "2") {
    //...
    return 2.3;
}
foo(1)
# [🐍] Python
def foo(arg1, arg2 = "2", /): # les paramètres positionnel uniquement
    # ...
    return 2.3

foo(1)
//[TS] TypeScript
function foo(arg1: number, arg2?: string = "2"): number {
    // ...
    return 2.3;
}

foo(1)

Paramètre du reste (rest parameter)

// [JS] JavaScript
function foo(arg1, ...arg2) {
    // arg2 = ["2", "3"]
    return 2.3;
}
foo(1, "2", "3")
# [🐍] Python
def foo(arg1, /, *arg2):
    # arg2 = ("2", "3")
    return 2.3

foo(1, "2", "3")
//[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

// [JS] JavaScript
function foo(arg1, arg2, arg3) {
    //...
    return 2.3;
}
const args = ["2", "3"];
foo(1, ...args)
# [🐍] Python
def foo(arg1, arg2, arg3, /):
    # ...
    return 2.3

args = ("2", "3")
foo(1, *args )
//[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

TODO: utilité

// [JS] JavaScript
function * foo(nb) {
    for(let i = 0; i < nb; ++i)
        yield i;
}

for( let val of foo(5) )
    console.log(val);
# [🐍] Python
def foo(nb, /) {
    for i in range(nb):
        yield i;
}

for val in foo(5)
    console.log(val);
//[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

TODO: pas d'équivalent en python + utilité (callbacks)

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 ?