Aperçu des sections

  • Syntaxe

    La syntaxe pouvant pas mal varier d'un langage à l'autre, nous verrons les syntaxes selon le langage étudié.

    • Variables et constantes

      Les variables sont un élément extrêmement basique de tout langage de programmation. 

      Techniquement, c'est un espace mémoire qui va être réservé à un usage particulier dans votre logiciel, et plus généralement dans votre système d'exploitation, et finalement, dans les éléments hardware qui composent l'ordinateur. Vous pourrez y stocker des valeurs dont votre programme à besoin pour fonctionner. 


      Dans les langages de haut niveau (type JS et PHP) vous n'avez pas à vous soucier de la "gestion" des variables d'un point de vue système, c'est l'interpréteur JavaScript qui s'en chargera pour vous. En revanche, dans des langages bas niveau, vous devriez gérer les variables avec des notions très pointues d'emplacement et de taille (Quel octets ? Dans quel mémoire ? Gestion des variables inutilisées ? etc...).

      Plus on descend dans le "niveau" des langages, plus on utilise une approche électronique des choses. Ça n'est pas le cas en développement web, et donc en JavaScript et PHP.


      Syntaxe et déclarations

      Pour déclarer des variables et des constantes, c'est très simple :

      • utilisez le mot clé réservé ou l'expression réservée à la déclaration des variables / constantes
      • définissez un identifiant (le nom de la variable)
      • utilisez le signe égal si vous souhaitez lui assigner une valeur (pas obligatoire)
      • et pour finir, vous définissez la valeur


      Exemples en JS :

      const ANNEE_NAISSANCE = 1985;
      let anneeEnCours = 2019;

      Il y a plusieurs façons de déclarer des variables, mais l'exemple du dessus reste un standard.

      var money;
      money = 2000.50;

      Ici, on déclare une variable avant de lui donner une valeur. Dans cet exemple, l'usage du mot clé var est l'ancienne définition des variables JS en ES5. Ça a été modifié avec ES6 pour résoudre des problèmes de scope notamment. La bonne pratique aujourd'hui est d'utiliser le mot clé let (même si var fonctionne toujours). Vous trouverez de nombreux contre-exemples sur Internet, avec des extraits de code qui utilisent le mot clé var. C'est normal, le mot clé var était la norme depuis 1995, tandis que let rentre petit à petit dans les habitudes des développeurs depuis seulement 2015.

      Un dernier exemple :

      let x, y, z;
      x = 5;
      y = 2;
      z = 8;


      Voici une illustration qui fait bien la distinction entre l'initialisation d'une variable, et l'assignation d'une valeur.




      • Typage des variables

        Le typage des variables est aussi un élément clé de nombreux langages de programmation. En théorie, vous devez dire au programme quel type de valeur va devoir stocker une variable. Voici un exemple de différents types de valeurs :

        • un nombre entier (integer en anglais)
        • un nombre à virgule (float en anglais)
        • un caractère (character en anglais)
        • un booléen (boolean en anglais)
        • un tableau de valeurs (array en anglais)
        • une chaîne de caractères (string en anglais)
        • etc...


        Exemple des différents types de variables en JS :



        Exemple des différents types de variables en PHP :



        Suivant les langages, vous aurez accès à différents types. Mais certains sont tellement basique (ex : nombres et lettres), que tous les langages les proposent. Les langages web sont souvent de typage faible. Cela veux dire que vous n'avez pas à déterminer le type d'une variable, et que vous pouvez changer le type d'une variable au cours de votre programme, cela se fera automatiquement et ne posera aucun soucis. 

        Un langage "propre" est supposé avoir un typage "fort", donc certains outils vous permettent de typer vos variables correctement, ce qui veut dire que vous ne pourrez pas mettre du texte dans une variable sensée recevoir des entiers par exemple. C'est un gage de sécurité et de fiabilité, mais cela oblige les développeurs à plus de rigueur dans l'écriture et la conception de leur programme.

        Exemple JS :

        let mot = "Bonjour";
        console.log(typeof mot); /*Affichera "String" */
        mot = 3;
        console.log(typeof mot); /* Affichera "Number" */

        => Exécutez ce script dans votre navigateur, et constatez le résultat dans votre console. 

        Grâce au mot clé typeof, JS vous affichera le type de la variable mot, qui correspond une fois à string, et l'autre fois à number.

        Maintenant, faites le test avec ces valeurs :

        let mot = true;
        console.log(typeof mot);   /* Affichera "Boolean" */
        mot = "3";
        console.log(typeof mot);   /* Affichera "String" */

        => On constate le type boolean en premier. Notez bien le deuxième cas : on stocke le chiffre 3, mais le type de la variable est string. C'est normal, car ici, "3" (entouré de guillemets), est exprimé sous forme de caractère et non d'un nombre entier. 


        Par exemple, dans la phrase "j'ai 3 pommes", bien que 3 soit écrit sous une forme numérique, il est perçu par le langage comme un caractère normal. On aurait pu écrire "j'ai trois pommes", cela reviens sensiblement au même en langage de programmation, on traite une chaîne de caractères.


        Dans les langages de haut niveau (type JS et PHP), les variables se typent "toutes seules", en fonction des valeurs que vous leur assignez. Cela permet de gagner du temps de codage, et contraint moins le développeur à respecter une logique et une syntaxe très rigoureuse. En revanche, cela laisse une grosse place à l'erreur humaine. Dans des langages bas niveau, le développeur est obligé de typer ses variables au moment où il les déclare.

        L'apparition du typage fort apparaît progressivement en JS et PHP, notamment via l'utilisation de Typescript ou PHP7.

        • Types primitifs

          Number

          Le fait de manipuler des types number va vous permettre par exemple de faire des opérations mathématiques sur vos variables. Ce qui est évidemment impossible avec les autres types.

          let a = 3;
          let b = 4
          console.log(a + b); /* Affichera 7 */
          a = "3";
          b = "4";
          console.log(a + b); /* Affichera 34 */

          Je vous laisse cogiter la dessus... Nous verrons les différents opérateurs disponibles sur les types number dans les sections suivantes.

          Suivant les langages, il y a différentes nuances de nombres. Vous pouvez avoir les entiers (int), des petits ou gros entiers (big int et small int), les nombres à virgules "flottante" (float), etc...


          String

          Le type string (donc qui contient des caractères), va vous offrir des possibilités différentes :

          let prenom = "Julien";
          let bonjour = "Salut"
          console.log(`${bonjour} ${prenom}`); /* Affichera "Salut Julien" */

          Le simple fait d'utiliser les guillemets (simple ou double), ou les back-tick permet de signifier à JS ou PHP qu'on va manipuler une chaîne de caractère. Quand on mixe des chaînes de caractères ensemble, c'est ce qu'on appelle la concaténation. Il y a de nombreuses opérations possibles sur les chaines de caractères que nous verrons plus tard (par exemple : mettre tout en majuscule, rechercher un élément dans une chaîne, etc....). 

          Il peut y avoir deux types liés aux caractères : les chaînes de caractères (série de plusieurs caractères, utilisé pour stocker du texte par exemple), ou bien un caractère unique. Certains langages font la distinction entre le type "char" et "string". Mais bien souvent, un caractère unique est considéré comme une chaîne de caractère ne comprenant qu'un seul élément.


          Boolean

          Les booléens sont un type très primitif à l'informatique, car ils correspondent à la vision binaire et logique d'un système informatique. Un booléen n'a que deux valeurs possibles : true ou false (0 ou 1). Suivant les langages, les booléens sont plus ou moins souples (je ne rentrerai pas dans les détails), mais sachez que c'est un type extrêmement répandu et utile. Donc true et false sont des mots réservés par JS.

          let vrai = true;
          let faux = false;
          console.log(`${typeof vrai} ${vrai}`);
          console.log(`${typeof faux} ${faux}`);

          Je ne veux pas vous embrouiller avec ça, mais sachez que dans certains cas, une variable vide peut être considérée comme étant égale à false, tandis qu'une variable qui contient une valeur peut être considérée comme true. Tout dépend de la rigidité du langage. Plus on descend dans les langages bas niveau, plus les les types sont contraints.


          Null et undefined

          En Javascript :

          En JS, il existe les types null et undefined. Ce genre de type servent à exprimer une forme d’erreur dans le type ou le contenu d'une variable. Nous ne nous attarderons pas dessus, mais pour faire bref, ce sont des types primitifs de JS qui peuvent être utiles dans certains cas. Voici les infos précises et exemple sur le MDN :


          En PHP :

          En PHP, seul le type NULL existe. La valeur spéciale NULL représente une variable sans valeur. NULL est la seule valeur possible du type null. Une variable est considérée comme null dans ces cas la :

          • elle s'est vue assigner la constante NULL

          • elle n'a pas encore reçu de valeur.

          • elle a été effacée avec la fonction unset().


          • Types composites

            Comme nous venons de le voir, les types primitifs ne vous permettent d'assigner qu'une seule valeur à une variable. Par exemple : prenom = julien. Ce concept vous permet de faire beaucoup de choses, mais s'avère limité pour représenter des choses plus complexes. 

            Si par exemple je souhaite stocker dans mon programme la liste de tous les noms des élèves de ma classe, avec des types primitifs, je serai obligé de faire quelque chose du genre :

            let prenom1 = 'julien';
            let prenom2 = 'pierre';
            let prenom3 = 'paul';
            let prenom4 = 'jacques';
            let prenom5 = 'maxime';

            Jusqu'ici, ça passe. Mais comment allez vous faire si je vous demande de lister tous les élèves d'un lycée ? Ce serait vite fastidieux d'être obligé de créer une variable pour chaque élève. Et remarquez le nommage des variables, ça n'est pas spécialement logique... (pourquoi 1,2,3,4,5 ?).


            Les langages de programmation offre des alternatives très souples pour résoudre ce genre de problèmes, via l'utilisation de types composites, qui vont simplement stocker des valeurs de types primitifs dans une seule variable représentative. La plupart des langages proposent deux types composites que sont les tableaux et les objets. Ces deux types répondent à des besoins très différents, et ne s'utilisent pas de la même manière.

            L'avantage des types composites, c'est qu'ils peuvent eux même stocker d'autres types composites, et ce, récursivement.


            Les tableaux

            Le tableau (array en anglais) est un type très répandu dans la plupart des langages de programmation. Il sert à stocker de manière contraintes et organisée les valeurs qui le compose. Par exemple, au lieu d'avoir une variable pour chaque prénom d'élève, on pourrait mettre tous ces prénoms dans une seul variable qui serait de type tableau, et qui contiendrait une liste de string (les prénoms des élèves).

            Exemple en JS :

            let listeEleve = ['julien', 'pierre', 'paul', 'jacques', 'maxime']; /* Les crochets [ et ] permettent de signfier le type "tableau" */
            console.log(listeEleve);

            Ici, les crochets [ ] signifie à JS que notre variable listeEleve sera un tableau. Les crochets représentent le type tableau dans d'autre langage aussi (tel que PHP). Les différents éléments qui le compose sont séparés par des virgules. Tout simplement. 

            Les tableaux sont un type composite simple, dans le sens ou leur organisation interne est connu à l'avance. Il y a deux notions importantes à connaitre pour manipuler un tableau :

            1. les index : c'est le "rang" de vos différents éléments qui composent votre tableau. L'index d'un tableau commence à zéro.
            2. les valeurs : c'est la valeur qui est stockée sur un index donné


            Donc, si j'écris :

            console.log(listeEleve[1]);

            Mon programme m'affichera pierre.

            Vous pouvez stocker différents types de variables dans un tableau : des strings, mais aussi des nombres, des booléens, et même d'autres tableaux. Quand un tableau stocke d'autres tableaux, c'est ce que l'on appel un tableau bi-dimensionnel.

            Exemple :

            let notesDuTrimestre = [   /* Ici, un tableau contient d'autres tableaux */
              ['pierre', 8, 12, 14, 5],
              ['paul', 9, 16, 4, 9],
              ['jacques', 18, 10, 9, 12]
            ];
            console.log(notesDuTrimestre);

            Il y a d'autres syntaxes possibles pour déclarer un tableau, cela dépend des langages.

            Exemple :

            let arr1 = new Array(1, 2, 3, 4, 5);
            let arr2 = Array(1, 2, 3, 4, 5);
            console.log(arr1);
            console.log(arr2);

            Une autre notion de base importante sur les tableaux, c'est leur taille. Quand on parle de la taille d'un tableau, on parle du nombre d'éléments qui le compose. On peux accéder à cette propriété via la méthode length en JS:

            let notesDuTrimestre = [
              ['pierre', 8, 12, 14, 5],
              ['paul', 9, 16, 4, 9],
              ['jacques', 18, 10, 9, 12]
            ];
            console.log(notesDuTrimestre.length); /* Affichera 3, car il y a 3 élèves dans le tableau */
            console.log(notesDuTrimestre[0].length); /* Affichera 5, car il y a 5 éléments dans le tableau de pierre */

            Les tableaux disposent de nombreuses méthodes qui permettent de les manipuler. Nous approfondirons ça dans un autre chapitre.


            Les tableaux associatifs

            Comme nous venons de le voir, un tableau stricto-sensus est indexé sur des entiers (0, 1, 2, 3, 4.....). Cela peux suffire dans certains cas, mais souvent, on utilise une forme un peu différentes que l'on appel les tableaux associatifs. Les tableaux associatifs permettent d'accéder à un index particulier non pas par un entier reflétant "le rang", mais par une clé que le développeur déterminera librement. On parle de clés dans ces cas la, mais il s'agit juste de termes choisis par le développeur.

            Exemple en JS :

            let notes = {   /* Ici c'est une accolade, cela représente un objet */
              'julien': [12, 8, 15, 10], /* julien est la propriété, les notes sont la valeur. On parle aussi de clé/valeur */
              'pierre': [10, 18, 14, 11],
              'laure': [10, 9, 7, 18],
              'sarah': [13, 15, 9, 12]
            };
            console.log(notes);
            console.log(notes.julien); /* Quand on travail avec des objets en JS, l'opérateur pour accéder à une propriété est le point */
            En JS, il n'y a pas de type "tableau associatif" à proprement parlé (contrairement à PHP par exemple), donc on va passer par la création d'un objet. Mais en PHP, un tableau associatif se manipule à peu près de la même manière qu'un tableau normal, à la différence près qu'on utilisera l'opérateur => pour associer une valeur à une clé.


            Voici une traduction possible en PHP :

            $notes = [
              'julien' => [12, 8, 15, 10],
              'pierre' => [10, 18, 14, 11],
              'laure' => [10, 9, 7, 18],
              'sarah' => [13, 15, 9, 12]
            ];
            print_r($notes);
            print_r($notes['julien']);


            Les objets

            Dans cette section, nous allons juste effleurer le fonctionnement et la logique de ce qu'on appel un objet en programmation, et donc de la POO. JS ou PHP savent manipuler de nombreux objets nativement, cela veux dire que vous pouvez utiliser tout un tas d'objets à votre disposition, mais sans en modifier la logique. Par exemple le DOM est un objet, mais il y a d'autres objets natifs.

            Voici quelques objets que vous pouvez utiliser nativement :

            • objet Math en JS : pour faire des opérations mathématiques particulières (ex : valeur absolue, trigonométrie, etc...)
            • objet Date en JS : pour manipuler des choses en lien avec le temps (dates, heures, années, millisecondes, etc...)
            • objet XHR en JS : pour faire des appels AJAX (non, ça n'est pas un produit pour nettoyer les vitres)
            • objet PDO en PHP : permet de travailler sur les bases de données
            • etc etc...


            Donc les objets sont un peu comme des tableaux qui, en plus de stocker des variables "classiques" (number, string, etc...) vont pouvoir vous offrir des fonctionnalités. Vous pouvez utiliser des objets natifs, par exemple l'objet Math en JS :

            console.log(Math.ceil(10.75)); /* Affichera 11, car ceil() est une méthode qui permet d'arrondir un nombre à l'entier supérieur */

            On dit ici que ceil est une méthode de l'objet Math. Ce terme est très important par la suite. Je vous laisse imaginer l’algorithme que vous auriez dû écrire pour arriver au même résultat. Vous pouvez voir par exemple toutes les possibilités de l'objet Math sur la page du MDN.


            Maintenant, voyons voir comment créer ses propres objets, au même titre que les variables ou les tableaux. Le signe basique définissant un objet est l'accolade { }

            Voici un exemple d'objet simple en JS:

            let voiture = {
              marque: 'Ferrari',
              annee: 2003,
              roule: () => console.log('Vrouuuum'),
              klaxon: () => console.log('Tût Tût')
            };
            console.log(voiture.marque); /*Affichera la marque*/
            console.log(voiture.annee); /*Affichera l'année*/
            voiture.roule(); /*Exécutera la méthode 'roule'*/
            voiture.klaxon(); /*Exécutera la méthode 'klaxon'*/

            Et voici une traduction possible en PHP, avec une classe anonyme :

            $voiture = new class {
              public $marque = 'Ferrari';
              public $annee =  2003;
              public function roule() { echo 'Vrouuuum'; }
              public function klaxon() { echo 'Tût Tût'; }
            };
            echo $voiture->marque; /*Affichera la marque*/
            echo $voiture->annee; /*Affichera l'année*/
            $voiture->roule(); /*Exécutera la méthode 'roule'*/
            $voiture->klaxon(); /*Exécutera la méthode 'klaxon'*/


            On peux voir ici que notre objet voiture est stocké de la même manière qu'une variable standard (let voiture). En revanche, et au même titre que les tableaux, cette variable peut stocker plusieurs informations (marque et année). Vous remarquerez qu'il n'y a pas d'index automatique (0, 1, 2), mais des clés (marque, année,..), définies par le développeur. 

            La nouveauté, c'est qu'on va pouvoir définir une logique dans un objet. C'est à dire qu'on ne stocke pas des valeurs "figées", mais des fonctionnalités qui peuvent avoir un comportement complexe. Au même titre que l'objet Math dispose d'une méthode ceil(), notre objet voiture dispose d'une méthode roule(). Tout simplement.

            On va pouvoir accéder à ces différentes propriétés et méthodes via le point . en JS, et la flèche -> en PHP. Par exemple : voiture.marque affiche Ferrari. C'est pareil pour les méthodes, sauf qu'ici on ajoute les parenthèses ( ) qui correspondent à l'exécution d'une fonction. Nous verrons ça plus tard dans les cours. 

            Voici un exemple un peu plus sympa en JS. En plus de contenir le prénom et les notes d'un élève, notre objet contient une méthode qui permet de calculer la moyenne des notes. Pratique.

            let eleve = {
              name: 'julien',
              notes: [8, 16, 12, 17, 3, 9, 11],
              moyenne: (notes) => {
                let cnt = 0;
                notes.forEach(function(element) {
                  cnt += element; /* On additionne toutes les notes */
                });
                return Math.ceil(cnt / notes.length); /* puis on divise par le nombre de note (en arrondissant à l'entier supérieur) */
              }
            }
            console.log(`${eleve.name} a une moyenne de ${eleve.moyenne(eleve.notes)}/20 cette année.`); //Affichera la moyenne des notes arrondie à l'entier supérieur. Ici : 11


            Donc pour faire simple, les objets sont des super-variables qui contiennent des données + une logique

            Note : certains objets ne stockent que du contenu statique, tels que les objets JSON. Un objet n'a pas forcément de méthodes. On utilise quand même la notation objet car ils sont parfois plus simples à manipuler que des tableaux dans certains cas.

             

            Voici un exemple d'objet JSON, qui est retourné par l'API Google Maps pour afficher des hôtels sur une carte :

            {
              "markers": [{ /* Liste d'hotels */
                  "name": "Rixos The Palm Dubai", /* Nom de l'hotel */
                  "position": [25.1212, 55.1535], /* Coordonnées GPS de l'hotel */
                },
                {
                  "name": "Shangri-La Hotel",
                  "location": [25.2084, 55.2719]
                },
                {
                  "name": "Grand Hyatt",
                  "location": [25.2285, 55.3273]
                }
              ]
            }

            On voit bien ici les index, clés, valeurs, tableaux, etc... Mais ça n'est que de la donnée, il n'y a pas de fonctionnalités particulières.



            • Opérateurs

              Les opérateurs sont des signes ou des mots qui vont vous permettre d'effectuer des traitements sur vos variables et constantes.  Ce sont un peu les fonctionnalités de base de votre langage. Par exemple, si vous souhaitez effectuer une simple somme, vous allez utiliser l'opérateur +. Cela semble évident, mais comme je vous l'ai dit plus haut, gardez bien en tête qu'il y a toujours une mécanique très profonde derrière ce genre de détails. Pour un ordinateur, le terme + ne signifie rien. Quelqu'un a dû coder, à un moment donné, que lorsqu'il y avait deux nombres séparés par le caractère +, il fallait faire tout un tas d'opérations afin d'arriver au résultat niveau CP : 3 + 3 = 6 !

              Il y a de nombreux opérateurs de bases, tels que les opérations arithmétiques, mais il y a aussi des opérateurs spécifiques pour chaque aspect de la programmation qu'offre JavaScript. Par exemple quand on veut créer un nouvel objet, on utilisera l'opérateur new

              Exemple JS :

              let monTableau = new Array();


              Les opérateurs arithmétiques

              • + : addition => Ex : a + b
              • - :  soustraction => Ex : a - b
              • * : multiplication => Ex : a * b
              • / : division => Ex : a / b
              • % : modulo => Ex : a % b
              • ** : puissance (attention : ES7) => Ex : a ** b

              Petit point sur les deux derniers. Le modulo % représente le reste d'une division entière (9%4 = 1 car 9 = (2*4) + 1) ). L'opérateur puissance ** n'a été intégré que dans des versions assez récentes (ES7 pour JS, et ancienne fonction pow() pour PHP), et il se lit comme ceci : 2**3 (2 puissance 3, sera égal à 8).

              Exemple :

              let a = 2;
              let b = 4;
              console.log(a + b); /* Affichera 6 */


              La concaténation

              La concaténation est très répandue en programmation informatique. C'est le fait de mixer des chaînes de caractères les unes dans les autres. En JavaScript cela se fait avec l'opérateur +, qui réagira du coup différemment selon que les variables sont de type numbers ou strings. En PHP, cela se fait avec l'opérateur point ..

              Exemple en JS :

              let prenom = 'julien';
              console.log('Bonjour ' + prenom + ' !');

              Exemple en PHP :

              $prenom = 'julien';
              echo "Bonjour ".$prenom." !";


              Ces syntaxes sont vraiment les plus basiques. On peut utiliser des guillemets simples ou doubles. Chaque langage a ses propres nuances concernant la concaténation, que nous verrons plus tard.



              Les opérateurs de comparaison

              Les opérateurs de comparaisons sont utiles lorsque l'on veut comparer deux valeurs. Souvenez-vous de l'exemple de l'algorithme des crêpes (si oeuf <= 0).

              • < : strictement inférieur à (a < b)
              • <= : inférieur ou égal à (a <= b)
              • > : strictement supérieur à (a > b)
              • >= : supérieur ou égal à (a >= b)


              Exemple JS :

              let a = 3;
              let b = 5;
              if(a < b){   /* En français : si a est inférieur à b, tout simplement */
                console.log(`a est strictement inférieur à b`);
              }


              Les opérateurs d'égalité

              Les opérateurs d'égalité vous permettent de savoir si une valeur est égale ou non à une autre. 

              • == sert à savoir si deux variables sont égales, sans regarder le type des variables ( if(3 == "3") renvoi true). C'est l'opérateur d'égalité faible.
              • != opérateur d’inégalité faible
              • === opérateur d'égalité stricte. Sert à savoir si deux variables ont la même valeur et le même type ( if("3" === 3) renvoie false)
              • !== opérateur d'inégalité stricte


              Note importante : l'opérateur = n'est PAS un opérateur d'égalité. Il sert à assigner une valeur à une variable ou constante. Ceci est vrai pour la majorité des langages. Beaucoup de débutants font la confusion au début, il vous faut connaître tout ça par cœur, c'est très important.


              Les opérateurs logiques

              Encore une fois, on se rapproche de l'électronique. Les opérateurs logiques vous permettent d'exprimer les expressions logiques OU et ET. De la même manière qu'un circuit électronique peut être branché en série ou en parallèle. Voici comment ils s'écrivent en JS et PHP :

              • && : signifie ET
              • || : signifie OU


              Pour comprendre comment fonctionnent ces opérateurs logiques de base, voici des schémas de circuits électroniques simples qui montrent bien la différence entre un ET et OU :

              Interrupteurs logiques

              Interrupteur ET : les deux interrupteurs doivent être fermés pour que le courant passe et que la lampe s'allume.


              Interrupteurs OU : il suffit qu'un seul interrupteur soit fermé pour que le courant passe et que la lampe s'allume.



              Et voici une retranscription de tous les cas de figures possible, c'est ce qu'on appelle une table de vérité :

              Vous devez vous imprégner de cette logique le plus tôt possible, cela est fondamental en programmation.

              Note : les opérateurs & et | existent, mais ils s'appliquent à des données binaires. Ils sont rarement utilisés pour des projets standard.


              Voici un exemple :

              let oeuf = 10;
              let lait = 3;
              let farine = 5;
              let sucre = 0;
              let beurre = 10;
              if (oeuf && lait && farine) { /*Pour faire des crêpes, on a besoin d’œuf ET de farine ET de lait*/
                console.log(`On va manger des crêpes aujourd'hui !`);
              }
              if (sucre || beurre) { /*Pour faire des bonnes crêpes, il nous faut en plus du sucre OU du beurre*/
                console.log(`...et en plus elles seront bonnes !!`);
              }

              Il y a de nombreux autres opérateurs, mais ceux que nous venons de voir sont les plus utilisés. Voici un lien vers la doc officielle des opérateurs Javascript. On peut mixer tous ces opérateurs afin d'arriver au comportement attendu. 

              Voici un exemple en image qui permet de vérifier si un âge est compris entre 13 et 20 ans (21 étant exclu ici) :

              opérateurs javascript

              opérateurs javascript 2


              • Structures conditionnelles

                Les structures conditionnelles vous permettent simplement d'exécuter une ou plusieurs instructions seulement dans certains cas. C'est une des bases de la programmation.

                conditions JS


                Structure avec if / else

                Littéralement "si", et "sinon", c'est l'expression de base pour exprimer une condition. Il y a plusieurs syntaxes possible, reprenons l'exemple des crêpes :

                if (oeuf <= 0) {
                console.log('Pas d'oeuf : pas de crêpes aujourd'hui');
                } else if (lait <= 0) {
                  console.log('Pas de lait : pas de crêpes aujourd'hui');
                } else if (farine <= 0) {
                  console.log('Pas de farine : pas de crêpes aujourd'hui');
                } else {
                  if (sucre <= 0) {
                    console.log('Pas de sucre : pas grave, on peux faire des crêpes sans sucre');
                  }
                  if (beurre <= 0) {
                    console.log(`Pas de beurre : pas grave, on peux faire des crêpes sans beurre`);
                  }
                  console.log(`Sortir les ustensiles et se mettre au boulot !`);
                } /*suite du programme...*/


                Ici, on peux voir l'utilisation du mot clé if, du mot clé else, du mix else if, et de l'imbrication de conditions. Remarquez les conditions dans le dernier else, elles ne sont pas liées. Cela veux dire que les deux conditions seront exécutées quoi qu'il arrive. En revanche, si on a pas d’œufs, le script "sort" de la chaîne de conditions, et enchaîne sur la suite du programme. Dans ce cas on a une suite de conditions qui s'enchaînent et qui s'imbriquent. Une autre chose importante, on va pouvoir écrire une condition seulement après un "if" ou un "else if". Le "else" seul sous-entends que la condition précédente est fausse (false).

                Voici un exemple plus simple :

                if (!oeuf || !lait || !farine) {  /* Le signe ! exprime la négation en programmation (l'inverse). On pourrait dire : "Si pas d'oeuf" ou "si pas de lait" etc... */
                  console.log(`Pas de crêpes aujourd'hui`);
                } else {
                  console.log(`Opération crêpes : go go go !`);
                }

                Note : remarquez la syntaxe avec le point d'exclamation. C'est une façon d'écrire oeuf == false, ou bien encore oeuf != true, ou bien encore oeuf <= 0. C'est un peu comme si je disais en Français : "Bonjour, comment allez-vous ?", ou "Salut, ça va ?", ou encore "Wesh bro, ça roule ?". Les trois syntaxes sont différentes, mais le messages est (à peu près) le même. A vous de choisir votre style... Attention, cela ne marche pas toujours pareil selon les langages. Certains estiment que 0 équivaut à false, tandis que d'autres sont plus précis. On pourra utiliser des comparateurs stricts dans ces cas de figure si l'on veut un résultat plus précis.


                Conditions ternaires

                Vous pouvez factoriser une condition simple en utilisant l'opérateur de condition ternaire. Cela vous permet d'écrire un if else en une seule ligne. 

                Voici la syntaxe :

                let soleil = false;
                let meteo = (soleil) ? 'Il fait beau' : 'Il fait moche';  /* Condition ternaire */
                console.log(meteo);


                Dans ce cas la, la condition retourne la valeur d'un des blocs, et l'assigne à la variable meteo. Les conditions ternaires n'apporte rien de plus qu'un if else, si ça n'est un code moins lourd à lire, et moins d'accolades et de retour à la ligne. Donc vous pouvez les utiliser sans modération sur des conditions simples. En revanche, elles ne seront pas adaptées à des conditions plus complexes.

                Vous pouvez aussi écrire ça :

                let soleil = false;
                (soleil) ? console.log('Il fait beau'): console.log('Il fait moche');


                Les switch

                Les switch sont beaucoup moins utilisés que les if, mais peuvent s'avérer plus adaptés dans certains cas. Si vous savez d'avance qu'une variable peut avoir une série de valeurs déterminées, cela peut-être une bonne manière d'écrire vos conditions. Prenons le cas des couleurs rouge, vert bleu. Si vous codez un programme qui doit gérer ces trois couleurs, vous allez devoir vérifier à un moment donné que la couleur que vous traitez appartient bien aux différents cas prévus.

                Exemple :

                let color = 'green';
                switch (color) {
                  case 'red':
                    console.log(`Ok c'est bon, la couleur rouge est valide`);
                    break;
                  case 'green':
                    console.log(`Ok c'est bon, la couleur verte est valide`);
                    break;
                  case 'blue':
                    console.log(`Ok c'est bon, la couleur bleue est valide`);
                    break;
                  default:
                    console.log(`Désolé, je ne peux pas traiter la couleur ${color}`);
                }

                On aurai très bien pu traiter ça avec un if else, à vous de voir selon les cas. Voici une page plus détaillée sur les switch.


                • Structure itératives

                  Une autre structure basique, mais très puissante de la programmation, ce sont les boucles (loop en anglais). Une boucle est une structure, qui va permettre d'itérer autant de fois qu'on le souhaite pour atteindre un certain résultat. 

                  Les boucles peuvent être traduite en français par les expressions "tant que", ou bien "pour chaque", selon les syntaxes que l'on utilise. Certaines boucles ont une structure très basique, et vous allez devoir déterminer tous les paramètres nécessaires à sa bonne exécution. Tandis que d'autres ont une structure un peu plus "étoffée", ce qui va vous permettre de boucler plus facilement, selon vos besoins.

                  Pour imager le concept, on peux prendre l'exemple d'un manège pour enfant. Admettons qu'un "tour de manège" représente 10 tours du manège sur lui-même (on fait rarement qu'un seul tour sur ce genre de manège). Donc quand les enfants sont installés, et que le manège démarre, on va compter : 1 tour, 2 tours, 3 tours,......., 10 tours ! On stoppe le manège, tout le monde descend.

                  Bon et bien les boucles permette de représenter ce concept qui nous parait pourtant si simple. Techniquement, on a :

                  1. une valeur de départ (0 tour)
                  2. des valeurs intermédiaires (1,2,3,4,....)
                  3. et une valeur max (10 tours)


                  La ou les boucles sont très puissantes, c'est dans leur vitesse d'exécution. Vous pouvez créer une boucle qui itère 5000 fois, si le code est propre, ça ne prendra qu'une fraction de seconde. Imaginez si je vous demande de compter jusqu'à 5000 dans votre tête, combien de temps cela va t il vous prendre ?


                  Fonctionnement basique d'une boucle


                  Décomposons un peu ce schéma.

                  Start : on peux dire que c'est le point d'entrée de notre boucle. Les enfants sont installés, on a fait 0 tours, et on sait qu'on doit faire 10 tours

                  Condition : c'est le même principe que les if. On vérifie que le nombre de tours effectués est inférieur à 10. Donc on peux dire en français : "tant que tour est inférieur à 10, la condition est vrai (true)". De la même manière qu'un  if, si la condition est "vrai", on rentre dans la boucle.

                  Statements (instructions) : la on va pouvoir exécuter une ou plusieurs instructions :

                  • faire voltiger le pompon
                  • vérifier qu'aucun enfant n'est malade
                  • crier le prix du tour de manège dans un micro pour faire venir d'autres clients

                  On va rajouter une instruction obligatoire et 
                  absolument essentielle : rajouter un tour. Logique.


                  A la différence des if, une fois que toutes ces instructions sont exécutées, au lieu de sortir de notre boucle, on va re-tester notre condition initiale : "est-ce que tour est inférieur à 10 ?". Si c'est le cas : on repart dans la boucle une nouvelle fois. Donc "tant que tour est inférieur à 10", on relance la boucle indéfiniment (pompom, enfant malade, promotion + rajouter un tour a chaque fois).

                  Et donc, en toute logique, quand notre variable tour vaudra 10, notre condition deviendra fausse, et on sortira enfin de notre boucle. Le tour de manège est fini, et on va pouvoir passer à la suite du programme (par exemple : partir à la pêche aux canards).


                  Exemple et contre-exemple de l'implémentation de notre algo "Tour de manège" :

                  CONTRE exemple : avec des if

                  Ce contre exemple n'est pas à reproduire, il est juste la pour vous montrer le lien qu'il y a entre les boucles et les conditions, et l'absurdité de faire certaines choses sans faire de boucles.

                  const MAX_TOUR = 3;
                  let tour = 0;
                  
                  
                  if (tour < MAX_TOUR) {
                    console.log(`Tour ${tour} : on vérifie si tout va bien et on fait voltiger le pompon.`);
                    tour = tour + 1;
                  }
                  if (tour < MAX_TOUR) {
                    console.log(`Tour ${tour} : on vérifie si tout va bien et on fait voltiger le pompon.`);
                    tour = tour + 1;
                  }
                  if (tour < MAX_TOUR) {
                    console.log(`Tour ${tour} : on vérifie si tout va bien et on fait voltiger le pompon.`);
                    tour = tour + 1;
                  }
                  if (tour == MAX_TOUR) {
                    console.warn(`Le tour de manège est fini, direction la pêche aux canards.`);
                  }
                  

                  BON Exemple, avec une boucle :

                  La, c'est OK ! :)

                  const MAX = 25; /*On souhaite faire 25 tours de manège */
                  let tour = 0; /*et on part de zéro*/
                  
                  while (tour < MAX) {   /* Tant que (while) le nombre de tours est inférieur à 25 */
                      console.log(`Tour ${tour} : on vérifie si tout va bien et on fait voltiger le pompon.`); /*Instructions */
                      tour++; /* Incrémentation : on rajoute un tour */
                  }
                  
                  console.warn(`Le tour de manège est fini, direction la pêche aux canards.`);


                  => copiez ce code dans un nouveau script JS, et exécutez-le. Quelle version vous préféreriez coder si on devez faire 100 tours de manèges ? Une fois que vous avez constaté la différence entre les deux (if et while), supprimez le contre-exemple avec les  if (la première partie).

                  Pour cette exemple, j'ai volontairement exagéré une utilisation totalement inadaptée des if. Mais c'est juste pour vous montrer l'aspect "conditionnel" des boucles. On arrive au même résultat avec des if, mais de manière complètement illogique et irrationnelle. C'est pour ça que les boucles existent, et qu'elles sont un élément fondamental de tous les langages de programmation.

                  Donc pour résumé, voici la structure de base de toutes boucles :

                  1. des valeurs d'initialisation
                  2. une condition à vérifier pour savoir si on reste - ou pas - dans la boucle
                  3. une incrémentation afin de faire évoluer une valeur à chaque tour de boucle


                  Types de boucles standard

                  Il existe de nombreuses façon d'implémenter le concept de boucle. En revanche, il y a deux types de boucle qui existent dans de nombreux langages : les while et les for.


                  Le while

                  Le while (littéralement "tant que") est la syntaxe la plus standard. 

                  Voici un exemple en JS :

                  let alphabet = 'abcdefghijklmnopqrstuvwxyz';
                  let i = 0;
                  while (i < alphabet.length) { /*Ici, alphabet.length correspond au nombre de caractères contenu dans la chaîne (26 lettres)*/
                    console.log(alphabet[i]); /* On affichera la lettre correspondant au rang i */
                    i++;
                  }

                  C'est simple et efficace, mais on est obligé de déclarer une variable supplémentaire i, et de l'initialiser à zéro. Le i est une convention pour noter les compteurs des boucles, et ça se réfère au mot increment, car les boucles servent surtout à parcourir des tableaux en incrémentant une valeur de 1 en 1 pour accéder à tous leurs indexes (0, 1, 2, 3, 4...).

                  => copiez ce code dans votre sandbox puis regardez la console. On voit bien que l'instruction console.log est exécutée autant de fois que nécessaire, alors qu'on la "codée" qu'une seule fois.



                  Les do...while

                  Le do...while est une variante très proche du while simple. Personnellement je ne l'utilise pas, à vous de voir celle que vous préférez. A la différence des while, le bloc d'instruction sera exécuté une première fois avant de tester la condition.

                  Voici un exemple en JS :

                  let prenom = 'Julien';
                  let notes = [15, 14, 8, 12, 10, 9];
                  let i = 0;
                  do {
                    console.log(`${prenom} a eu ${notes[i]}/20.`);
                    i += 1; /* Equivaut à : "i = i + 1", ou bien encore "i++" */
                  } while (i < notes.length)

                  Et le tout en image :) (edge = falaise) :




                  Les for

                  Littéralement "pour", ce mot clé - et ses nombreuses variantes - sont très répandus dans les différentes syntaxes de boucles des différents langages. La syntaxe for offre un cadre un peu plus rigide que les while, et a la spécificité d'intégrer les trois éléments de base d'une boucle (initialisation, condition, incrémentation) dans une seule et même expression. Tout est "rassemblé" au même endroit, donc moins de risque d"erreur ou d'oublis.

                  Voici un exemple de for en JS :

                  for (i = 0; i < 10; i++) {
                      if (i % 2 == 0) {
                          console.log(`${i} est un chiffre pair.`);
                      } else {
                          console.log(`${i} est un chiffre impair.`);
                      }
                  }

                  Ici on distingue clairement un changement de syntaxe avec les while. Au lieu de devoir déclarer les variables avant la boucle, on peut les intégrer directement dans la syntaxe du for

                  Voici comment on pourrai le lire en français : 

                  "Pour i égal zéro, tant que i est inférieur à dix, exécute le code de ma boucle, puis incrémente i de un"

                  Notez les points virgules entre chaque éléments, c'est la syntaxe qui a été déterminée comme ça (pareil en JS et PHP). Notez aussi que i est accessible à l'intérieur de la boucle. Et maintenant essayez d'imaginer l'algorithme qui va manipuler tous les octets et tous les bits à l'intérieur de votre machine pour exécuter ça de manière absolue d'un point de vue électronique...


                  => Avant de passer à la suite, voir les autres types de boucles propres à chaque langages.


                  Des boucles dans des boucles

                  Quand on traite des éléments multi-dimensionnels, on sera obligés de faire des boucles dans des boucles. Un peu comme dans certains cas ou l'on doit imbriquer des if dans des if. La gymnastique cérébrale est un peu plus complexe, mais le principe reste le même. Ça marche tout aussi bien avec les while ou les for.


                  Exemple simple en JS (seulement des tableaux) :

                  let notesDuTrimestre = [ /* Tableau à 2 dimensions, cad : un tableau qui contient des tableaux */
                    ['pierre', 8, 12, 14, 5],
                    ['paul', 9, 16, 4, 9],
                    ['jacques', 18, 10, 9, 12]
                  ]; for (let eleve of notesDuTrimestre) { /* Première boucle, pour avoir tous les éleves */
                    for (let note of eleve) { /* Deuxième boucle, pour avoir le prénom et les notes */
                      console.log(note)
                    }
                    console.log('------'); }


                  Mots clés liés aux boucles

                  • break : permet d'interrompre une boucle avant la fin "normale" de son exécution (par exemple : vous avez trouvé la valeur que vous recherchiez, inutile de continuer à itérer pour rien)
                  • continue : permet de continuer le fonctionnement normale de la boucle. Assez peu utilisé si votre code est propre.
                  • label (uniquement en JS) : jamais utilisé. Permet de "nommer" une boucle. Voir la doc MDN sur le label.



                  Boucle infinie

                  Le bug fatal d'une boucle. Si vous omettez d'itérer votre compteur sur les boucles while, ou si votre condition est mal fichue, votre boucle s’exécutera de manière infinie sans jamais s’arrêter, et va finir par faire crasher votre environnement d'exécution. Ça peut prendre parfois de très longues secondes avant de pouvoir relancer son programme. Si vous ne l'avez pas encore fait, vous pouvez faire le test. 

                  Attention, en "production", c’est absolument désastreux. Maintenant les navigateurs récents gèrent ce problème, il vous suffit juste de fermer l'onglet au bout d'un moment, de corriger votre erreur, puis de relancer votre programme. Mais il y a encore peu, il fallait au minimum fermer le navigateur entier, puis le ré-ouvrir. Côté serveur, il va falloir configurer correctement votre moteur PHP afin qu'il arrête tout seul de pédaler dans la choucroute au bout d'un certain temps (directive max_execution_time du php.ini par exemple).

                  En soit, une boucle infinie n'est pas un bug à proprement parlé, donc cela ne vous émettra pas d'erreur d'exécution.


                  • Les fonctions utilisateurs

                    Un autre élément de base de tout langage informatique, ce sont les fonctions. Vous ne pourrez pas vous en passer. Une fonction permet "d'encapsuler" un bout de votre programme dans un bloc bien défini, qui pourra être exécuté quand vous le souhaitez, et à de multiples reprises.

                    Toujours dans l'idée d'être le plus proche possible des mathématiques, une fonction fonctionne à peu près de la même manière que le concept de fonction en math. Il permet de retourner un résultat qui dépend d'une variable. Ça n'est pas toujours vrai, mais c'est l'idée de base.

                    Si je souhaite écrire une fonction qui me renvoie le double d'une valeur, j'aurai quelque chose comme ça :

                    Ma fonction :
                    f(x) = 2x

                    Vous comprendrez que le résultat de la fonction dépend de la valeur de x.

                    Mes calculs :
                    f(2) = 4
                    f(10) = 20
                    etc...

                    En programmation, on peut faire la même chose grâce aux fonctions. 


                    Voici comment on écrirai une fonction double() en JavaScript :

                    function double(x){
                      return 2*x;
                    }


                    Facile non ? Les fonctions sont très pratiques, car cela vous permet de "découper" votre code en plein de petits bouts (comme des fonctionnalités), et de les appeler à votre guise selon les besoins. Par exemple, si vous travaillez sur un programme de facturation, vous pouvez être certains d'avoir les fonctions suivantes :

                    • calculTVA(montantHT, tauxTVA)
                    • prixQuantite(quantite, prix)
                    • etc...


                    Schématisation d'une fonction :

                    structure d'une fonction en js

                    Comme on peut le voir sur l'image, les fonctions ont des entrées et des sorties, donc c'est un peu comme des mini-programmes à l'intérieur de votre programme principal. Cela évite de devoir réécrire le même code de nombreuses fois à de multiples endroits. On définit function calculTVA() une seule fois, mais on peut l'appeler depuis différents endroits du programme.


                    Voici un exemple de fonction qui me dit si on est en week-end :

                    let today = new Date();   /* Ceci représente la date en cours (aujourd'hui) */
                    let dayOfWeek = today.getDay();  /*  Dimanche = 0, lundi = 1, mardi = 2,....., samedi = 6  (système américain) */
                    console.log(isWeekend(dayOfWeek));   /* On exécute la fonction en lui envoyant le bon paramètre */
                    
                    function isWeekend(day) {
                        if (day == 6 || day == 0) { /* Si le jour est le numéro 6 ou 0 */
                            return true;  /* Alors oui, nous sommes en weekend ! */
                        } else {
                            return false; /* Sinon, non nous sommes en semaine :( */
                        }
                    }

                    Dans cet exemple, la fonction est très simple, et ne prends pas en compte l'heure. Seulement le jour. Et elle retourne un booléen, donc ce sera au développeur de prendre les cas en considération, et d'afficher par exemple : "Génial, on est en weeken-end !", ou "Allez, encore quelques jours à tenir...". 

                    On aurait pu affiner notre fonction comme on le souhaite, par exemple :

                    • retourner le nombre de jour/heure/minutes qu'il reste avant le week-end
                    • afficher un texte ou une alert directement à l'intérieur de la fonction
                    • prendre en compte les jours fériés
                    • etc...


                    Note de passionné : c'est la toute la beauté du code, on peut vraiment exprimer tout ce que l'on souhaite, du moment que c'est traduisible en langage informatique.
                    Remarque : la fonction est écrite après qu'on l'appelle dans l'ordre chronologique du script. Ça n'est pas grave, le code fonctionnera très bien. C'est parce que la fonction est détectée par l'interpréteur au moment de l'exécution de votre script, et il la stocke donc dans un endroit à part, réservé aux fonctions, ce qui la rend accessible un peu partout dans le code.


                    Petit point sur le today.getDay() : regardez la doc de l'objet Date() natif en JS sur le MDN. La méthode .getDay() renvoi le rang du jour de la semaine de 0 à 6. Donc getDay() est une sorte de fonction qui va avoir un traitement très spécial sur les dates, et qui va vous retourner un chiffre entre 0 et 6 en fonction du jour de la semaine. Un peu comme  Number.isNaN() pour les nombres, et String.concat() pour les chaînes de caractères, ou encore  Math.min() pour les nombres. Ce sont des fonctions natives, et bien pratiques. Nous approfondirons ça plus tard ensemble.


                    Bref, on fait ce que l'on veut dans une fonction, du moment que c'est nous qui l'avons écrite. Il existe de nombreuses fonctions déjà codées dans tous les langages, elles correspondent à des besoins génériques de développeurs. Pour les besoins "métiers", c’est-à-dire ceux qui sont spécifiques à votre application, vous n'aurez qu'à coder vos propres fonctions !


                    Voici un schéma illustrant la structure de base d'une fonction :

                    Cette fonction JavaScript permet de changer la couleur d'un élément d'une page web en rouge


                    On peut voir dans ce cas là qu'il n'y a pas le mot clé return. Nous verrons ce cas de figure ensemble un peu plus bas. En français, quand on parle du bloc "argument", on parle de paramètres.

                    Aujourd'hui - en JS ou PHP - la déclaration, la syntaxe, et la manipulation des fonctions sont très souples et variés, il y a donc de multiples manières de travailler avec les fonctions. Nous verrons différentes syntaxes possibles, et leurs différences.


                    Le mot-clé "return"

                    Le mot-clé return est obligatoire dans une fonction. Si une fonction ne retourne rien, on appelle cela une procédure. Le mot-clé return permet de renvoyer le résultat d'une fonction, comme vu dans les exemples précédents. Il est assez important, car il va permettre à une fonction d'avoir une valeur. Dans la fonction vu précédemment isWeekend(), si l'on écrit isWeekend(0) on peut traiter ça un peu comme une variable, qui aura la valeur true, car le jour zéro (dimanche) correspond bien au week-end. On pourrait dire : isWeekend('dimanche') => vrai. En revanche, si on écrit isWeekend(2), cette même "variable" vaudrait false (isWeekend('mardi') => faux).

                    On peut mettre plusieurs return dans une même fonction, car le renvoie d'un résultat peut être conditionné à certaines choses par exemple (voir extrait de code  isWeekend(), plus haut dans le cours). En revanche, dès que la fonction va retourner une valeur, elle va stopper son exécution. Donc tout le code qui sera écrit après ce return ne sera pas exécuté.


                    Les paramètres

                    Comme vous l'aurez compris, les paramètres sont un élément clé des fonctions. C'est eux qui vont vous permettre d'avoir un résultat différent avec le même code. Un peu comme une boucle permet d'itérer plusieurs fois la même instruction, les fonctions permettent d'avoir plusieurs résultats avec la même instructions (f(x) = 2x, f(2) = 4, f(1000) = 2000, etc...). Les paramètres sont donc la partie variable de nos fonctions, comme le x en math.

                    On pourrait imaginer une autre fonction, qui comprends deux paramètres :
                    f(x, y) = 2*x + y
                    f(2, 3) = 2*2 + 3 = 7
                    f(4, 5) = 2*4 + 5 = 13
                    etc...


                    L'ordre dans lequel on déclare les paramètres dans notre fonction est très important. Le premier paramètre dans les parenthèses prendra la place du premier paramètre dans la déclaration de la fonction, le deuxième avec le deuxième, etc... Et le résultat peut etre completement différent selon les cas de figure, et vous pouvez aussi faire planter votre fonction si vous n'envoyez pas les paramètres dans l'ordre attendu.


                    Exemple avec des soustractions :

                    function diff(a, b){
                        return a - b;
                      }
                    
                      let x = 2;
                      let y = 5;  
                      console.log(diff(x, y)); /* Affichera -3 */
                      console.log(diff(y, x)); /* Affichera 3 */


                    Exemple avec des divisions :

                      function division(a, b){
                        return a / b;
                      }
                       
                      console.log(division(4,2)); /* Affichera 2 */
                      console.log(division(2,4)); /* Affichera 0.5 */
                      console.log(division(0,4)); /* Affichera 0 */
                      console.log(division(4,0)); /* Affichera Infinity (impossible de diviser un nombre par zéro) */


                    Donc dans les exemples précédents nous avons vu l'usage standard des paramètres. Voici quelques nuances.


                    Aucun paramètre

                    Vous pouvez définir une fonction sans paramètre. 

                    Exemple :

                    function nombreAleatoire() {   /* Aucun paramètre défini dans la déclaration de la fonction (entre les parenthèses) */
                      return Math.floor(Math.random() * 1000);
                    }
                    console.log(nombreAleatoire()); /* On pourra donc l'appeler sans paramètre */

                    => Testez ce code, et rafraîchissez votre page plusieurs fois en vérifiant la console.


                    Paramètres par défaut

                    ES6 a rajouté la notion de paramètre par défaut qui manquait cruellement à JavaScript. Les paramètres par défaut servent à donner des valeurs par défaut à une fonction si vous ne changez pas vous-même la valeur des paramètres. C'est le comportement "standard" de la fonction, mais il est modifiable.

                    Exemple :

                    const displayError = function(str = `Une erreur s'est produite dans le code`) { /* Notez la différence de syntaxe avec l'exemple précédent*/
                      console.error(str);
                    }
                    displayError(); /*exemple sans paramètre particulier*/ displayError("Une erreur s'est produite ligne 345"); /*exemple avec un paramètre déterminé*/

                    => Testez ce code dans votre sandbox, et modifier le texte à afficher dans le paramètre par défaut, puis dans l'appel de la fonction.


                    Vous pouvez déterminer plusieurs paramètres par défaut, de différents types :

                    const displayError = function(str = `Une erreur s'est produite dans le code`, ligne = 0) { /*paramètre 1 : chaîne, paramètre 2 : entier*/
                      let error = str;
                      if (ligne != 0) {
                        error += `, ligne : ${ligne}`;
                      }
                      console.error(error);
                    }
                    displayError();
                    displayError(`Ma variable n'est pas un nombre`, 410);

                    => Testez ce code dans votre sandbox, et modifier le texte et le numéro de ligne à afficher dans le paramètre par défaut, puis dans l'appel de la fonction.


                    Les procédures

                    Les procédures sont une légère variante des fonctions. En réalité, c'est quasiment la même chose à un détail près :

                    • une fonction retourne quelque chose. Donc on utilise le mot clé return
                    • une procédure effectue une série d'instructions, mais ne retourne rien


                    Par exemple, notre fonction displayError() un peu plus haut est en fait une procédure ! En JavaScript, c'est juste une histoire de vocabulaire, il n'y a pas vraiment de différence entre les deux. Par contre avec TypeScript, vous pourrez typer vos fonctions en  function ou void (procédure en anglais), ce qui peut apporter plus de sécurité à votre code. Certains langages font une distinction stricte entre les deux.

                    En JS, vous pouvez avoir une fonction qui retourne quelque chose dans un cas, et rien dans l'autre. C'est les petites ambiguïtés de JS. Vous pouvez appeler ça une foncédure si vous le souhaitez. Ou une functoid si vous êtes à cheval sur l'utilisation de l'anglais :)

                    • Les fonctions natives

                      Tous les langages proposent un ensemble plus ou moins étoffé de fonctions "déjà codées". Comme nous l'avons vu dans les exemples précédents, on peux utiliser les fonctions d'un langage pour réaliser facilement de nombreuses choses, plus ou moins complexes.

                      Si par exemple vous souhaitez générer un chiffre aléatoire entre 1 et 10, vous allez pouvoir utiliser la fonction Math.rand() en JS, ou rand() en PHP. Elles ont un fonctionnement différent, mais l'usage reste à peu près le même.

                      Ces fonctions sont très utiles car elles vont vous permettre de gagner énormément de temps dans l'écriture de votre programme, et de vous concentrer sur l'essentiel.

                      Voici quelques exemples de fonctions natives dans de nombreux langages :

                      • mettre une chaîne de caractère en majuscule
                      • savoir si une clé appartient à un tableau
                      • générer la date du jour
                      • trier une série de données dans un ordre particulier
                      • modifier l'environnement accessible (ex : le DOM en JS, le système de fichier en PHP)
                      • toutes les notions mathématiques (valeur absolue, racine carré, etc....)
                      • etc...


                      Pensez à bien fouiller dans les docs avant de faire vos propres fonctions. Vous y apprendrez de nombreuses choses.


                      Il y en a vraiment de très nombreuses, et il faut avoir le réflexe de rechercher dans les différentes documentations si une fonction native n'existe pas déjà dans un langage avant de coder sa propre fonction. Les fonctions natives sont généralement très bien codées, très souples, et très performantes. Donc à utiliser en priorité.

                      • La notion de scope

                        Dans la plupart des langages de programmation, certains éléments (variables, fonctions,..) sont soumis au concept de scope (portée, ou visibilité en français). 

                        Ce principe permet de déterminer depuis quels "endroits" de votre code vous allez pouvoir lire ou modifier une variable. Par exemple, en JavaScript, vous ne pouvez pas modifier la résolution d'écran de votre système d'exploitation (OS). C'est normal, les variables qui pourraient gérer cela sont protégées par le système d'exploitation, car bien trop sensibles. Elles ne sont donc pas accessibles via JavaScript. En revanche, vous pouvez lire la résolution de la fenêtre du navigateur exécutant un script JS par exemple, mais pas la modifier. Cet exemple permet de voir l'utilité de la notion de scope, que l'on peut comparer aux poupées russes qui s’emboîtent les unes dans les autres. 


                        Tous les langages n'implémentent pas la notion de scope de la même manière. Certains sont très souples, et ont des règles de scope peu contraignantes, et d'autre appliquent la notion de scope rigoureusement.

                        Un langage de programmation "sérieux" se doit d'appliquer les règles de scope de manière nette, car le nommage et les valeurs des variables peuvent vite s’emmêler si on ne respecte pas leur portée, et on risque de faire un programme un peu "plat de spaghetti".


                        Prise en compte du scope dans votre propre code

                        Comme vous l'avez compris, le scope est une règle qui régit normalement tous les logiciels (votre OS, votre navigateur web,...), et donc aussi le votre ! Quand vous allez écrire les lignes de code de votre application, vous allez devoir respecter les problématiques de scope associées au langage que vous utilisez. 

                        Nous verrons ces différentes problématiques à l'usage, selon les langages, mais voici à quoi pourrait ressembler les différents bloc de scope d'un point de vue plus technique.

                        Dans ce schéma, on pourrait dire qu'une variable initialisée dans le bloc "Local Scope", ne sera pas accessible dans le "Global scope". En revanche, l'inverse est possible (si les variables ont été déclarées en globales, mais cela dépend vraiment des langages).

                        Il y a deux types de scope assez facile à comprendre, le scope "global" et le scope "local".


                        Scope global et local

                        Quand vous allez écrire votre code, vous aurez normalement deux scopes bien définis, le scope global et le scope local. Selon les différentes moutures du langage que vous utilisez, les règles de scope ne seront pas forcément les mêmes, donc il faudra vous imprégner de ça à l'usage. 

                        Voici un schéma simple pour illustrer le scope global et le scope local en JS :


                        Dans cet exemple, bien que les deux variables aient le même nom, ce sont deux variables différentes. Et la valeur lue sera différente selon l'endroit ou on les manipule. Ce concept est très important, car il permet de bien cloisonner les éléments de base de votre application.

                        Exemple scope en PHP avec le mot clé global : https://www.php.net/manual/fr/language.variables.scope.php
                        • Les exceptions

                          La gestion d'erreur permet de "border" son code proprement, et de prévenir des comportements qui seraient générateurs de bugs ou de comportements inattendus. Un des exemples les plus courants quand on parle de gestion d'erreur, c'est la division par 0, qui est impossible à réaliser. Si par exemple vous devez faire une division dans votre code (ex : calculer une réduction de prix), sur la base d'une variable (ex : un pourcentage), il va falloir prévoir le fait que si votre diviseur vaut zéro, votre programme ne plante pas, et l'erreur soit correctement gérée.

                          Concrètement, dans les langages de haut niveau, vous ne coderez pas très souvent ce genre de choses. Théoriquement on peux le faire, mais soit ça passe à la trappe, soit on utilise des choses qui gère déjà assez bien les erreurs. On peux souvent faire ce genre de vérification en écrivant un peu de code adapté, sans forcément lever une erreur au sens technique du terme.

                          Les langages informatique ont leur propre mécanique de gestion des erreurs (affichage de message prédéfinis, backtrace, log, etc...), mais grâce à certains mots-clés et certaines syntaxes, vous allez pouvoir gérer vos propres erreurs de manière plus fine. Par exemple, le fait de gérer correctement des erreurs peut permettre au programme de ne pas planter s'il en croise une, et de continuer une exécution normale, malgré l'erreur détectée.


                          Les exceptions

                          Quand on veux déterminer quelque chose comme "anormal", on dit qu'on va lever une exception. La gestion des exceptions diffère selon les différents langages (texte simple, classes et objets dédiées, etc...), mais le concept reste à peu près le même.

                          Voici un exemple de code qui va lever une exception. Ici on imagine une fonction qui va modifier la vitesse d'un véhicule. La vitesse d'un véhicule ne peut pas être négative, donc on va mettre en place un mécanisme qui va détecter cette erreur dans notre programme. Bien que techniquement, la variable pourrait être négative, c'est notre logique qui l'interdit.

                          Exemple en PHP :

                          function setSpeed($speed) {
                            if ($speed < 0){
                              throw new Exception("<b>Erreur ligne ".__LINE__." : une vitesse ne peut pas être négative ($speed).</b>");
                            } else {
                              echo "Avancer à $speed km/h.<br />";
                            }
                          }

                          En PHP, on passe par la classe Exception en utilisant le mot clé throw (lever / jeter), puis on détermine le message que l'on souhaite associer à notre erreur en paramètre.



                          Bloc try/catch


                          Les try/catch servent à gérer les exceptions. C'est à dire que l'on va pouvoir déterminer un comportement particulier si on a croiser une erreur dans le bloc try. Si une erreur est détecté durant l'exécution de code qui se trouve dans un try, alors l'exceptions va être "attrapée" (catch), puis on va rentrer dans un bloc d'instructions prévues à cet effet.

                          Voici la suite de l'exemple précédent, avec l'implémentation d'un try/cacth :

                          function stop(){
                            echo "Un problème est survenu, arret du véhicule.";
                          }
                          try {
                            setSpeed(50);
                            setSpeed(90);
                            setSpeed(-50); /* Ce cas de figure ne devrai pas arriver, mais il arrive... */
                            setSpeed(130);
                            setSpeed(180);
                          }
                          catch (Exception $e) { /*quand une erreur est détectée, on atterri ici*/
                            echo $e->getMessage()."<br />"; /*Affichage de l'erreur via la méthode getMessage() de la classe Exception (PHP)*/
                            stop(); /*Comportement particulier*/
                          }
                          echo "<hr />Malgré l'erreur, le script ne va pas planter et va pouvoir continuer son exécution."; /*La vie continue*/

                          On peux aussi rajouter un bloc "finally" après le catch, mais c'est encore moins utilisé.

                          • Récursivité

                             

                             


                            Le concept de récursivité est assez simple. Il consiste à faire en sorte qu'une fonction se rappelle elle même. Cela va produire un effet similaire aux boucles. La récursivité s'emploie lorsqu'on ne sait pas "combien de fois" à l'avance il va falloir exécuter une fonction. 

                            Voici un exemple simple en JS d'un compte à rebours codé grâce à une fonction récursive :

                            let countDown = function(timer = 30) {
                              if (timer > 0) {
                                console.log(`${timer}s`);
                                timer--;
                                countDown(timer);
                              } else {
                                console.log('Boum !')
                              }
                            };
                            console.log(`Ce message s'autodétruira dans :`);
                            countDown(10);


                            => Copiez ce code dans votre sandbox afin de constater son bon fonctionnement.

                            On peux voir ici qu'on appel la fonction countDown() en bas du script, et qu'elle se rappelle elle-même dans la condition (timer > 0). On aurai pu faire exactement la même chose avec une boucle. Mais dans certains cas, on ne peux pas résoudre un problème via l'utilisation de simples boucles. On pourra donc certainement utiliser la récursivité. Le fait de conditionner le rappel d'une fonction à elle même est un élément structurant à la récursivité en programmation, sinon la récursion ne s'arreterai jamais, et on aurai quelque chose qui ressemblerai à une boucle infinie. Donc à proscrire.

                            En PHP, on peut avoir besoin de récursivité pour diverses choses. Par exemple si on travail sur un arbre de catégories dans un blog, et que chaque catégories peut avoir des sous-catégories "indéfiniment", il va falloir utiliser la récursivité afin de "plonger" dans l'arbre des catégories jusqu’à ce que l'on ai trouvé la dernière sous-catégorie.

                            Illustration représentant les différents types de moteurs électriques existant, et qui pourrait être parcouru de manière récursive :


                            Dans cet exemple, certaines catégories ont seulement 1 niveau de profondeur, tandis que d'autres en ont 5 ou 6.

                            Un autre exemple, plus proche du quotidien, c'est l'organisation de vos dossiers dans votre OS. Rien ne vous empêche de créer des dossiers dans des dossiers dans des dossiers etc.... Les algorithmes qui vous permettent de manipuler toutes ces arborescences dans votre OS utilisent très certainement le concept de la récursivité.