title: JavaScript de zéro
slug: javascript-zero
date: 2016-01-18
chapo: Enseigner JavaScript ET la programmation à partir de zéro est un moyen d’identifier les forces et faiblesses du langage.

> When it comes to problem-solving in general (and JavaScript in particular), I have a similar bias towards single-purpose solutions. Rather than creating a monolithic framework that attempts to solve all possible problems, I prefer a collection of smaller scripts that only do one thing, but do it really well; [the UNIX philosophy](https://en.wikipedia.org/wiki/Unix_philosophy).
> 
> <cite>*[Small lessons, loosely learned](https://adactio.com/journal/10078)* ([cache](/david/cache/5ca3d2195e5b23f6dca45fcab9327040/))</cite>

En un temps relativement restreint (8 heures [de cours](/david/pro/enseignement/)), j’ai essayé d’enseigner JavaScript à des étudiants n’ayant aucune notion de programmation en ne partant finalement [d’aucun niveau d’abstraction](/david/blog/2015/javascript-abstraction/). Pour seuls outils : le navigateur et son inspecteur/console et un fichier `HTML` de test, l’objectif étant d’alterner entre du théorique avec ce fichier et du pratique en manipulant des pages existantes. J’appréhendais un peu suite [aux désillusions de l’année dernière](/david/blog/2015/cours-iut-comprendre-javascript/) mais j’avais gagné en expérience à la fois en JS et en réduisant mes prétentions sur ce que je voulais leur transmettre.

La première heure, compréhension des notions de variable et d’opérateur puis introduction de `console.log` pour faire la différence entre un script et son exécution dans la console. La deuxième heure a été consacrée à `document.querySelector` et `document.querySelectorAll` où l’on parle forcément de tableaux/listes et c’est peut-être à ce moment là que j’aurais dû introduire la conversion d’un `NodeList` en `Array` mais on n’en avait pas encore le besoin… En troisième heure, on commence à jouer avec les styles avec `Element.style` et surtout `Element.classList` et ça commence à être ludique d’aller modifier des pages existantes. Enfin pour clôturer la session, on expérimente avec `innerHTML` et `outerHTML` pour introduire du dynamisme. Et de manière transverse on parle de `NaN`, d’`undefined` et des commentaires.

À la fin de cette première demi-journée j’étais très optimiste car tous les étudiants avaient compris et savaient appliquer ce genre de code (valide) :

    :::html
    <!doctype html>
    <meta charset="utf-8">
    <title>Test JavaScript</title>
    <style>
        .turn-red { color: red; }
        .turn-green { color: green; }
        .turn-blue { color: blue; }
    </style>
    <h1>red</h1>
    <h1>green</h1>
    <h1>blue</h1>
    <script>
        var titles = document.querySelectorAll('h1')
        titles[0].classList.add('turn-' + titles[0].innerHTML)
        titles[1].classList.add('turn-' + titles[1].innerHTML)
        titles[2].classList.add('turn-' + titles[2].innerHTML)
    </script>

Mine de rien ça fait énormément de concepts à assimiler pour les 24 personnes n’ayant jamais fait de programmation ! Et la transition est toute trouvée pour parler de la répétition avec les boucles et les fonctions. Hop, une semaine de repos pendant laquelle ils n’ont… rien fait :’(.

Voir ces 3 lignes répétées doit faire bondir un développeur, j’ai commencé par introduire la notion de fonction avec un nom suffisamment explicite pour limiter les commentaires puis l’usage d’une boucle `for` pour itérer sur les éléments. Au passage on a besoin d’`Array.length` et de comprendre les conditions. Jusque là tout allait bien, j’en profite pour montrer qu’il est possible de le faire avec un `while` et déjà ça amène de la confusion mais alors là où ça a vraiment bloqué c’est au passage à `forEach`. Je ne sais pas si c’est la syntaxe ou la conversion en `Array` ou le fait d’avoir des fonctions anonymes ou la fatigue cognitive mais toujours est-il que ça a commencé à décrocher à ce moment là. Il faut dire qu’un `Array.prototype.slice.call` en plein milieu n’arrange pas les choses. Peut-être qu’un `Array.from` ou un `for(… of …)` eut été plus explicite mais limité en terme de support. Dur.

Pour finir, j’ai montré qu’une fonction pouvait retourner une valeur avant d’enchaîner sur les évènements à base d’`addEventListener` ce qui ouvre la porte des interactions avec l’utilisateur. On arrive à cet enchaînement :

    :::javascript
    function addClassFromHTML(element) {
        element.classList.add('turn-' + element.innerHTML)
    }
    function dealWithTitleOnClick(title) {
        title.addEventListener('click', function() {
            addClassFromHTML(title)
        })
    }
    var titles = document.querySelectorAll('h1')
    titles = Array.prototype.slice.call(titles)
    titles.forEach(dealWithTitleOnClick)

Je retiendrai qu’il faut un peu plus de temps pour découvrir certains concepts. Travail demandé pour la semaine suivante : faire une fonction qui permette à partir d’un article de presse d’avoir une version lisible avec uniquement le titre et le contenu sans images. Une sorte de *bookmarklet* à la [readability](https://github.com/mozilla/readability). Et [jouer](http://codecombat.com/) aussi.

**Enseigner JavaScript ET la programmation à partir de zéro est un moyen d’identifier les forces et faiblesses du langage.** D’un côté on a le [TDD du pauvre](/david/blog/2013/tdd-conception-emergente/) avec un feedback visuel immédiat et la possibilité d’utiliser la console du navigateur. De l’autre les plusieurs façons de faire la même chose et les restrictions liées au non-support d’ES6 par les navigateurs. J’ai presque envie de troller sur la programmation fonctionnelle mais je vais plutôt ajouter [une couche d’abstraction](/david/blog/2015/javascript-abstraction/) pour la prochaine fois, ce sera plus simple en demi-groupes. En espérant que ça devienne davantage compréhensible et utilisable par des néophytes, le code précédent devenant :

    :::javascript
    $('h1').on('click', function(event) {
        addClassFromHTML(event.target)
    })
