1. Prise en main

Pour prendre en main le language, nous allons exécuter des scripts Javascript directement dans la console à l’aide de Node.js (mais nous n’utiliserons que du javascript "pur", sans les spécificités de Node).

Téléchargez et installez Node.js via ce lien : https://nodejs.org/en/download/

En cas de problème vous pouvez aussi utiliser JS Bin pour écrire les programmes en ligne : http://jsbin.com/?js,console

Pour tester l’installation, créez un fichier javascript (exercice_1.js) contenant :

console.log("Hello world!");

Puis exécutez le fichier avec node:

> node exercice_1.js
Hello world!

2. Variables

Déclaration

En javascript les variables peuvent être déclarées de 3 façons différentes :

  • var

  • const (ES6)

  • let (ES6)

Les 3 mots clés s’utilisent de la même façon :

var a = 42;
const b = 42;
let c = 42;

Une variable déclarée avec const doit toujours être initialisée.

Lorsque la variable n’est pas initialisée (var a; ou let a;), la valeur de a est undefined.

Scope

Une variable déclarée avec var est accessible dans l’ensemble du contexte courant (la fonction actuelle), tandis qu’une déclaration avec let ou const rendra la variable accessible uniquement dans le bloc courant.

function ex_var() {
    var a = 5;
    if(true) {
        var b = 8;
        console.log(b); // 8
    }
    console.log(b); // 8
}
function ex_let() {
    var a = 5;
    if(true) {
        let b = 8;
        console.log(b); // 8
    }
    console.log(b); // error, b n'existe pas
}

3. Fonctions

Pour déclarer une fonction :

function name() {
    // contenu
}

name(); //appel de cette fonction

Une variable peut aussi contenir une fonction (tout comme n’importe quel autre type) :

let name = function() {} //fonction anonyme
name(); //appel

Les fonctions anonymes sont très utiles pour être passées en callback d’une autre fonction :

function exemple1() {
    //contenu
}
fonctionQuiAccepteUneAutreFonction(exemple1)
//OU
fonctionQuiAccepteUneAutreFonction(function(){
    //contenu
})

Lors de l’appel d’une fonction, vous pouvez passer un paramètre de deux façons :

const obj = { a : 1 }

maFonction(obj) // la variable

maFonction({ a : 1 }) // directement un nouvel objet

this

La variable this est accessible partout dans votre code mais ne représente pas toujours la même chose.

Cette variable sera très utile lorsque nous utiliserons javascript avec Vue.js et Node.

Dans l’environnement global (à l’extérieur de toute fonction) this va pointer vers le contexte global :

this.a = "Hello";
console.log(a); //Hello
console.log(this.a); //Hello

Lors de l’appel d’une fonction, on distingue deux cas de figure :

Appel classique

Par défaut, this à l’intérieur d’une fonction va pointer vers l’objet global :

function f() {
    console.log(this.a);
}
global.a = 8;
f();

On peut appeler cette fonction avec un autre contexte, en utilisant call ou apply :

function f(param1, param2) {
    console.log(this.a)
    console.log(param1+param2)
}
f.call({a: 24}, 1, 2) //24 (les arguments sont 1 et 2)
f.apply({a: 42}, [5, 6]) //42 (les arguments sont 5 et 6)

Bind

L’appel à la méthode bind va créer une nouvelle fonction où this est lié pour toujours à l’objet passé en paramètre.

function f() {
    console.log(this.a)
}

let g = f.bind({a: 24})
g() //24
let h = f.bind({a: 42})
h() //42
f.call({a: 112}) //112

Arrow-functions (ES6)

ES6 a apporté les arrow-functions (ou fonctions flêchées), une nouvelle manière de définir une fonction anonyme :

() => {
    //contenu
}

//au lieu de :

function() {
    //contenu
}

Les paramètres se situent à gauche de la flêche (on peut omettre les parentèse si on passe un seul paramètre).

À droite de la flêche se trouve le corp de la fonction.

let f = (e,f) => { return e+f }
let f = e => { return e+1 } // 1 seul paramètre = parenthèses non nécessaires
let f = e => e+1 // Pas d'accolade = retourner la valeur de l'expression

L’intérêt principal de cette notation : Une fonction flêchée garde la valeur this du contexte parent.

//Avant pour qu'un callback puisse modifier le contexte il fallait faire :
function f() {
    //...
    let self = this; // on garde une référence au contexte
    loadData(function() {
        //this = cette fonction anonyme et non plus la fonction f
        self.mydata = "...";
    })
    //...
}

//Maintenant
function f() {
    //...
    loadData( () => {
        //this = l'objet englobant
        this.mydata = "...";
    })
    //...
}

Questions

3.1. On commence doucement : créez une fonction qui retourne le triple de l’entier passé en paramètre

3.2. Analysez dans votre tête (ou sur papier) le code suivant (sans l’exécuter). Quelle est d’après vous la sortie du programme ?

var b=2;
function a() {
    var e=5;
    console.log(b);
    console.log(c);
    console.log(d);
    console.log(e);
}
var c=3;
a();
var d=4;

Les variables sont accessibles uniquement dans le scope actuel et les scopes enfant

var b=2; //scope global
function a() {
    console.log("a");
    var e=5; //scope a
    console.log(b);
    console.log(c);
    console.log(e);
    console.log(d);
}
function f() {
    console.log("f");
    var d=6; //scope f
    console.log(d);
}
f();
a();
var c=3; //scope global

3.3. Afin de bien comprendre les portées du scope, créez une fonction add accessible uniquement depuis une fonction sum. * La fonction add retourne la somme des 2 nombres passés en paramètre. * La fonction sum utilise add pour additionner les 4 nombres passés en paramètre et retourne le résultat

Le scope global ne doit pas avoir accès à la fonction add.

3.4. Écrivez de deux manières une fonction pow qui prend en paramètre b et n, et retourne b puissance n.

3.5.

function qu3_5(a, b, c) {
    return a * c(b);
}

// Appelez cette fonction avec des paramètres cohérents

4. Chaînes de caractères

Quelques façons d’écrire des chaînes de caractère :

let str1 = "Ceci est une string plutôt simple";
let str2 = 'Une autre string';
let str3 = "Ceci est une string avec \" un caratère échappé";

let number = 8;
let str4 = "Le nombre est " + number;
let str5 = `Le nombre est ${number}`; //particulièrement pratique lorsqu'on a de nombreuses variables à insérer

let str6 = "Multiligne \
string";
let str7 = `Multiligne
string`;

Les chaînes sont des objets et donnent accès à de nombreuses méthodes (cf doc)

let str = "Test de string";
str.length; //14
str.replace(" ", "."); //Test.de.string

Questions

4.1. Créez une fonction qui affiche dans la console l’inverse de la chaîne passée en paramètre. ex: "Hello" → "olleH"

4.2. Faites en sorte que le code suivant remplace les caractères a par b, b par c et ainsi de suite
Indice : Renseignez-vous au sujet de String.fromCharCode() et String.CharCodeAt(), le code ASCII pourrait être utile. Essayez d’utiliser Map.

function replace(str) {
    // votre code
}

replace("Je suis ton père", my_fn);

5. Les tableaux

Les tableaux (objet Array) représentent une liste ordonnée de valeurs. Numérotés à partir de 0, chaque élément peut être d’un type différent.

let arr = new Array(0, 1, 3);
let arr= [0, 1, 3];

console.log(arr[2]); //3

arr.push(8); //[0,1,3,8]

Questions

5.1. Map

var arr = [ { a: 1, b: 2 }, { a:2 , b: 4 }, { a: 9, b: 1 }, { a: 19, b: 29 }, { a: 187, b: 4 } ];

Remplacez tout les éléments de ce tableau par la valeur de la propriété b. Écrivez votre solution de 2 manières : avec et sans map.

5.2. Filter

var arr = [ { a: 1, b: 2 }, { a:2 , b: 4 }, { a: 9, b: 1 }, { a: 19, b: 29 }, { a: 187, b: 4 } ];

Écrivez une fonction qui prend ce tableau en paramètre et garde uniquement les éléments avec a > 3.

5.3. Reduce

var arr = [ "Luke Skywalker", "Maître Yoda", "R2D2", "Padmé Amidala",  "Anakin Skywalker", "Obi-Wan Kenobi" ];

Écrivez une fonction qui retourne la chaîne de caractère Luke Skywalker, Anakin Skywalker, Obi-Wan Kenobi etc…​ en utilisant reduce.

5.4. Écrivez une autre fonction qui retourne cette même chaîne mais sans les membres de la famille Skywalker.

5.5. Écrivez une fonction qui prend une chaîne de caractère et retourne un objet représentant le nombre d’apparition de chaque lettre (hors espaces).
Combinez Filter et Reduce.
ex. countLetters("il dit qu’il voit pas le rapport") // ⇒ { "'" : 1, a: 2, d: 1, e: 1, i: 4, l: 3, o: 2, p: 3, q: 1, r: 2, s: 1, t: 3, u: 1, v: 1 }

var countLetters = function(string){
  // votre code
};

6. Les objets

Le concept d’objet en javascript est le même que dans les autres languages : un conteneur qui englobe des propriétés et des méthodes.

Les méthodes et propriétés d’un objet sont accessible via le . ou les crochets :

object.property
object["property"]
object.method()
object["method"]()

Tout est objet en javascript, même les types primitifs (nombres, chaînes de caratère, booléens etc…​)

console.log("Hello".length) //5

Les objets peuvent être utilisés pour stocker des paires clé/valeur (comme avec un objet JSON ou les structures en C) :

let obj = new Object();
obj.a = 42;
obj.b = 81;

let obj = {
    a: 42,
    b: 81
}

obj.c //undefined

Questions

6.1. Créez un objet représentant un film (titre, synopsys, année de sortie) ainsi que son réalisateur (sous-objet avec nom/prénom/date de naissance).

6.2. Créez un tableau contenant les films Titanic, Interstellar, La ligne verte avec leurs infos. Affichez ensuite le contenu du tableau dans la console (en mettant en forme les infos du film sur chaque ligne)

6.3. Écrivez une fonction prenant en paramètre ce tableau, et un 2ème paramètre search. La fonction retourne un tableau contenant les films dont le champ titre contient ce paramètre search.
Indice : utilisez filter

function search_movie(arr, search) {
    // votre code
}