Valentin Dupas

💡 If this is the first course you read from me, please read this small thing : about my courses

Plus d'explications

Jusqu'ici tout ce que l'on a vu est soit une variable, soit une valeur, soit une fonction, soit un mot-clef. Pour le moment tout ceci ne vous dis pas grand chose mais expliquer ca est le but de ce chapitre.

Les valeurs

Ça c'est le plus simple, peut être même trop simple. 5 c'est une valeur, false c'est une valeur, "un peu de texte" est aussi une valeur. Le but d'un programme informatique est de manipuler des valeurs (souvent fournies par l'utilisateur) rapidement pour calculer et/ou partager de l'information.

Pour le moment on va se dire qu'il existe 3 type de valeurs différentes. On verra les autres plus tard.

  • Les nombres: 5, -12, 13.37
  • la valeur de vrai true et la valeur de faux false, que l'on appelle "valeurs booléennes" d'après George Boole qui s'est dit "viens on éssaye de faire des maths avec vrai/faux plutôt que des nombres, comme ça on pourra rigouresement calculer si un argumentaire est correct ou non".
  • les textes: "ceci est du texte", "ça aussi", 'on peut aussi mettre ça entre guillemets simples'. Sachez c'est quasiment tout le temps appelé une "string", du terme technique "string of characters" qui veux dire "chaîne de caractères".

Attention au guillemets

J'insiste parceque ça arrive régulièrement que de confondre un nombre 5 avec du texte représentant ce nombre "5". Ce qui n'est pas pareil.

Exécutez le code ci-dessous pour voir le résultat.

console.log(5 + 5);

console.log("5" + "5");

console.log(5 + "5");

Remarquez que l'opération + permet de coller deux bouts de texte ensemble en un plus gros bout de texte, et vu que ça ne fait aucun sense de chercher à additionner un nombre et du texte, javascript prévois dans ce cas de convertir le nombre en texte puis de les coller ensemble. Ce qui fâche beaucoup de programmeurs qui préféreraient qu'on leur refuse et qu'on les avertisse à la place.

undefined

Un nouveau type de valeur à ajouter à votre liste.

undefined (non-defini) est une valeur spéciale. Si on créer une variable sans pour autant lui donner de valeur alors sa valeur initiale sera undefined.

let a;
console.log(a); // undefined

En soi, cette valeur ne vous sert à rien mais au moins quand vous verrez l'erreur ci-dessous ça vous parlera un peu plus.

Uncaught ReferenceError: mySuperVariable is not defined

Trouvez le bug:

let a;
let b;
const c;

a = 5;
b = a + 5;
c = a + b;
Solution

Il est trop tard pour donner a + b comme valeur à c car au moment de sa création il a déjà reçu undefined comme valeur et vu que c'est une variable const on ne peut plus lui donner autre chose.

D'ailleurs, je remarque en écrivant ça que les navigateurs sont suffisamment intélligents et ne vous laissent même pas aller jusqu'à la dernière ligne. Effectivement, ne pas donner de valeur lors de la création d'une constante est littéralement inutile et donc ils ont prévu de crasher dans ce scenario.

Une valeur, certes, mais une valeur complexe

Je vous avais dit qu'une variable permet contenir une valeur, et je ne vous ai pas menti. Mais il existe un type de valeur que nous n'avons pas encore vu, qui est utilisé quasiment partout, et qui représente la majeure complexité du chapitre précédent.

Les objets.

Un objet est une valeur qui contient d'autre valeurs et qui se présente comme ceci.

{
    name: "John Oates",
    birth: 1948,
    retired: false,
    occupation: "out of time",
}

C'est toujours délimité par des accolades {} et chaque chose contenue présente d'abord son nom puis deux-points : puis la valeur et une virgule ,, la virgule de la derniere ligne n'étant pas obligatoire.

Les retours à la ligne ne sont pas obligatoires, on pourrait le marquer comme ceci ...

{ name: "John Oates",birth: 1948,	retired: false,	occupation: "out of time" }

... mais c'est généralement une bonne idée de les mettre dès qu'on dépasse 2~3 valeurs.

Un objet est rarement utile en dehors d'une variable, parce que si l'objet contient plusieurs valeurs on va probablement vouloir l'utiliser plusieurs fois dans le reste du code. Et puis le mettre dans une variable c'est aussi lui donner un nom et c'est toujours mieux.

Un truc sympa, est que ça à beau être un paquet de valeurs, on peut quand même le passer dans console.log() comme n'importe quelle autre valeurs plus simple.

const user = {
  name: "John Oates",
  birth: 1948,
  retired: false,
  occupation: "out of time",
};

console.log(user);

Allez-y, essayez.

Si vous voulez lire ou changer une propriété de votre objet vous pouvez y accedez en y acollant un point . que l'on appelle "l'opérateur d'accession" (un opérateur est juste un sybole qui combine des "opérandes". Par exemple + est l'opérateur d'addition et prend 2 nombres en guise d'opérandes).

const user = {
  name: "John Oates",
  birth: 1948,
  retired: false,
  occupation: "out of time",
};

console.log(user.name);

user.name = "Daryl Hall";

console.log(user.name);

Ça fonctionne exactement comme les chemins de dossier et de fichiers. /documents/counter.js veux dire "le fichier counter.js qui est dans le dossier documents sauf qu'on remplace les / par des .. user.name étant donc la propriété name qui est dans l'objet user.

Et si l'analogie avec le rangement de fichiers ne vous parle pas trop, on peut constater aussi que ça se lit assez bien de droite à gauche en règle générale.

(note de traduction: Waldo = Charlie)

Les fonctions

Du code reutilisable

Si une valeur qui porte un nom est une variable alors un ensemble de quelques lignes de code qui portent un nom est une fonction.

function liftoff() {
  console.log("3");
  console.log("2");
  console.log("1");
  console.log("liftoff!!");
}

En soit ça s'écrit comme ceci. D'abord le mot function pour déclarer que le code qui suit est une fonction. Comme let déclare que ce qui suit est une création de variable. Ensuite le nom de la fonction (qui peut être ce que l'on veut, comme avec les variables). Puis une paire de paranthèses () qu'on expliquera juste après, et enfin le "corps" de la fonction (ce qu'elle fait) entre accolades {}.

Executez le code ci-dessus pour voir.

Il ne se passe rien? Pourtant ça fait bien 5~6 lignes de code, et en plus il y à des console.log()!

Effectivement, tout ce que ce code fait est de créer la fonction liftoff() mais on ne s'en sert jamais.

function liftoff() {
  console.log("3");
  console.log("2");
  console.log("1");
  console.log("liftoff!!");
}

liftoff();
liftoff();
liftoff();

Pour s'en servir il suffit de taper son nom et ses parethèses comme ceci.

Exécutez le code ci-dessus.

Remarquez que la séquence de console.log() se voit autant de fois que l'on a appelé la fonction.

Du code qui s'adapte

Donc, ces fameuses paranthèses, elles servent à quoi?

C'est ce que l'on apelle les "paramètres" de la fonction, c'est assez pratique parce que le code qui appelle la fonction peut maintenant donner des valeurs à la fonction pour qu'elle puisse travailler dessus. Sans paramètres une fonction est condamnée à faire la même chose à chaque exécution.

function twoPartLog(a, b) {
  console.log("Du " + a + " et du " + b);
}

twoPartLog("jambon", "beurre");
twoPartLog("beurre", "jambon");

Donc, via ce code on créer une fonction twoPartLog() qui demande 2 valeurs. Valeurs que l'on donne au moment où on apelle la fonction. Ce qui détermine "quelle valeur va dans quel paramètre" est leur position. La première fois qu'on apelle la fonction, elle va s'exécuter avec a valant "jambon" et b valant "beurre" tandis qu'à la deuxième exécution ce sera l'inverse a vaudra "beurre" et b vaudra "jambon".

On peut nommer les paramètres d'une fonction comme on veux, au même titre que les variables. J'aurais très bien pu utiliser first et second au lieux de a et b. C'est juste que cet example est trop petit pour être concret et c'est donc difficile de leur donner un nom pertinent.

Allez-y exécutez ce code et verifiez par vous même.

function twoPartLog(a, b) {
  console.log("Du " + a + " et du " + b);
}

twoPartLog("jambon"); // "Du jambon et du undefined"

Remarquez que si on ne respecte pas une fonction en lui donnant moins que ce qu'elle doit recevoir elle s'exécute quand même en collant la valeur undefined dans les paramètres qui n'on pas reçus de valeurs (autrement dit, ils n'ont pas été definies). Ne comptez pas là dessus c'est degoutant 🤣, considerez qui si vous ne donnez pas au fonction ce qu'elles attendent est un problème. D'ailleurs je le fait tellement jamais que je m'attendais à ce que ça crash en écrivant ce chapitre, ce qui est le cas dans tous les autres langages que je connais.


Il y a une manière plus propre de faire une fonction qui prend entre 0 et N paramètres, mais ça nous sera pas utile dans un futur proche donc on verra ça plus tard (ou pas du tout).

function twoPartLog(a, b) {
  console.log("Du " + a + " et du " + b);
}

twoPartLog("jambon", "beurre", "cornichons"); // "Du jambon et du beurre"

Si vous en mettez trop ça passe aussi. Les valeurs qui sont en excédent seront recupérables avec une manip', mais pareil, evitez, c'est vraiment ouvrir la porte a des tas de bugs. La manière de faire ça proprement n'est pas utile dans l'immédiat donc on repassera.

Du code qui répond

Il est possible que l'on écrive nos fonction de telle sorte qu'elles nous rendent un résultat quand elles ont finie. Pour ca il suffit d'utiliser le terme return et une valeur comme ceci.

function giveMeFive() {
  return 5;
}

console.log(giveMeFive()); // 5

Ce qui va se passer c'est que lorsequ'on appelle une fonction on va d'abord l'exécuter puis remplacer son appel par la valeur qui aura été retournée, ce qui fait que notre exemple ci-dessus est équivalent à console.log(5).

Voici un exemple un peu plus concret.

function square(x) {
  return x * x;
}

console.log("Le carré de 4 est " + square(4)); // Le carré de 4 est 16

Nottez aussi quelque chose d'important, return stope l'exécution de la fonction. Donc si on rend une valeurs on quitte direcetement la fonction.

D'ailleurs on peut aussi utiliser return sans fournir de valeur si tout ce qui nous intéresse c'est d'arreter l'exécution.

function earlyStop() {
  console.log("vous me voyez");
  return;
  console.log("vous ne me verrez pas");
}

earlyStop();

Exécutez ce code pour vérifier que vous ne voyez pas le deuxième message.

Problème

Écrivez une fonction neg() qui prend un nombre en paramètre et qui renvoie son opposé.

exemple d'utilisation:

console.log(neg(5)); // -5;
console.log(neg(-13)); // 13

Faire des essais dans un projet vide est une bonne idée.

Solution
function neg(x) {
  return x * -1;
}

Les mots-clef

Les mots-clef sont des mots que l'on ne peut pas utiliser pour nommer nos fonction ou nos variables parce que javascript leur a déjà assigné un rôle.

Imaginez que j'éssaye de créer une variable qui s'appellerait let comme ceci:

let let = 5;

En admettant que ce soit accpeté, cette ligne pourrait tenir la route mais le reste du code à partir de là deviendrait un casse-tête catastrophique parce que la machine ne saurais pas si j'éssaye d'utiliser la varibable let ou d'utiliser le mot-clef let pour créer une variable.

Jusqu'ici les mots-clef que nous avons vu sont:

  • let
  • const
  • function
  • return

Donc, pour récapituler:

Si ça fait partie du langage c'est un mot-clef, sinon si il y a des paranthèses c'est une fonction sinon c'est une variable

Nottez aussi que la coloration des mots dans votre éditeur de code devrait donner une couleur différente à chacun de ces éléments.

Là où c'est possiblement difficile, c'est de faire la différence entre les variables/fonctions définies par le navigateur et les mot-clefs. Dites vous que si vous pouvez le passer dans une console.log() ce n'est pas un mot-clef. console.log(document) fonctionne mais console.log(let) ou console.log(return) est du charabia pour la machine.

if

La raison pour laquelle on cherche d'abord à déterminer si il s'agit d'un mot-clef dans le diagramme ci-dessus est d'abord parce que c'est facile vu qu'il y en a un nombre limité et que ça bouge très rarement (2~3 fois par décénnie). Mais aussi parce que certains mots-clefs on aussi des paranthèses comme if.

if ressemble un peu à une fonction sauf que ça s'exécute tout de suite si la condition qui est entre ses paranthèses () est vraie true.

exemple simple

if (6 > 0) {
  console.log("6 est positif"); // ce console.log() s'exécutera
}

if (42 > 50) {
  console.log("42 est plus grand que 50"); // mais pas celui-ci
}

Symboles utiles avec le if:

  • < : plus petit que
  • > : plus grand que
  • <= : plus petit ou égal à
  • >= : plus grand ou égal à
  • == : égal à
  • === : strictement égal à

La différence entre == et === est que == sera vrai si les deux éléments comparés sont équivalents tandis qu'avec === le résultat sera vrai si les deux comparées ont la même valeur et le même type.

exemple

console.log(5 == 5);      // true
console.log(5 == "5");    // true
console.log("5" == "5");  // true

console.log(5 === 5);     // true
console.log(5 === "5");   // false
console.log("5" === "5"); // true

Nottez qu'il faut que la valeur finale entre les paranthèses du if soit vraie, mais il n'est pas nécessaire que ce soit via une comparaison.

if (true) {
  console.log("je m'executerais toujours");
}

if (false) {
  console.log("je m'executerais jamais");
}

// donc
const maVar = true;
if (maVar == true) {
}
// et
if (maVar) {
}
// sont entièrement équivalents

Aussi, si la valeur entre paranthèses n'est pas un booléen (true ou false) alors elle sera convertie automatiquement.

if ("un peu de texte") {
  console.log("je m'executerais toujours");
}

if ("") {
  console.log("je m'executerais jamais");
}

Les valeurs qui sont automatiquement converties en false sont des valeurs que l'on apelle "falsy". Il en existe très peu et ceux qui vont nous intéresser sont:

  • une string vide ""
  • undefined
  • 0

Un objet est equivalent a true et undefined est équivalent à false, donc on rentrera dans if(myMain) seulement si l'élément existe.

Problème

Écrivez une fonction max() qui prend deux nombres en paramètres et qui rend le plus grand des deux.

exemple d'utilisation

console.log(max(-1, 1)); // 1
console.log(max(1238, 2)); // 1238
Solution

Vous pourriez écrire ...

function max(a, b) {
  if (a > b) {
    return a;
  }

  if (b > a) {
    return b;
  }
}

... mais si on se rapelle que return arrête la fonction on peu simplifier comme ceci

function max(a, b) {
  if (a > b) {
    // a est plus grand que b?
    return a; // oui? tient prend a
  }

  return b; // on ne t'as pas donné a? donc prend b.
}

Problème

Reprennez le code du compteur au chapitre d'avant et ne laissez pas l'utilisateur descendre en dessous de 0 ni aller au dessus de 10.

indice

Au moment de changer le compteur vous pouver toujours tester la valeur du compteur et si elle dépasse dans un sens ou dans l'autre, vous la ramenez à la bonne valeur.

Solution
<script>
  let count = 0;

  document.querySelector("#minus-button").addEventListener("click", countDown);
  document.querySelector("#plus-button").addEventListener("click", handleClick);

  function handleClick() {
    count = count + 1;

    // ça depasse? oui?
    if (count > 10) {
      count = 10; // ça depasse plus
    }

    document.querySelector("#count").textContent = count;
  }

  function countDown() {
    count = count - 1;

    // ça depasse? oui?
    if (count < 0) {
      count = 0; // ça depasse plus
    }

    document.querySelector("#count").textContent = count;
  }
</script>

Altenativement:

<script>
  let count = 0;

  document.querySelector("#minus-button").addEventListener("click", countDown);
  document.querySelector("#plus-button").addEventListener("click", handleClick);

  function handleClick() {
    // est-ce que je suis encore en dessous du maximum?
    // oui? donc je peux me permettre de mettre à jour
    if (count < 10) {
      count = count + 1;
      document.querySelector("#count").textContent = count;
    }
  }

  function countDown() {
    // est-ce que je suis encore au desssus du minimum?
    // oui? donc je peux me permettre de mettre à jour
    if (count > 0) {
      count = count - 1;
      document.querySelector("#count").textContent = count;
    }
  }
</script>

else

Le mot-clef else permet de mettre un bloc après le bloc du if qui s'exécutera si la condition du if est fausse.

if (true) {
  console.log("je m'executerais toujours");
} else {
  console.log("je m'executerais jamais");
}

if (false) {
  console.log("je m'executerais jamais");
} else {
  console.log("je m'executerais toujours");
}