Aide-mémoire JS

Un mémo des manipulations courantes en JavaScript

a marqué ce sujet comme résolu.

Reprise du dernier message de la page précédente

Tu devinera que je parlais en ES5 et d'un truc destiné aux débutants, j'aurai peut être dû le préciser, en effet. Je ne crois pas qu'une personne qui utilise les fonctions fléchés ai besoin d'aide pour comprendre ce qu'est une closure si ? :p

“Your manuscript is both good and original. But the part that is good is not original, and the part that is original is not good.” Samuel Johnson

+0 -1

Tu devinera que je parlais en ES5 et d'un truc destiné aux débutants, j'aurai peut être dû le préciser, en effet. Je ne crois pas qu'une personne qui utilise les fonctions fléchés ai besoin d'aide pour comprendre ce qu'est une closure si ? :p

Demandred

Je ne vois pas le rapport. Si tu ne comprends pas l'ES2015, je te la refais en ES5 :

1
var f = function () { return 1; }

Aussi, quand on écrit un truc destiné aux débutants, le but c'est qu'ils comprennent le concept, pas qu'ils apprennent un truc faux. Donc il vaut mieux leur expliquer c'est qu'est une closure avec 2 phrases et un exemple que les embrouiller en leur parlant de variables libres, en répétant trois fois des anneries du genre "toutes les fonctions sont des closures" alors que c'est pas le cas, etc.

Bref, si je devais expliquer à un débutant ce qu'est une closure, je donnerais cet exemple avec cette explication : ```

Un exemple minimal de closure serait plutôt ceci : (attention c'est très moche)

1
2
3
4
var x = 1;
function add1 (y) {
  return y + x;
}

Une closure est une fonction qui référence/utilise des variables qui n'appartiennent pas au scope de la fonction en question.

victor

Et comme tu peux pas expliquer ce qu'est une closure avant d'avoir abordé la notion de scope, tout va bien.

Vous aimez le frontend ? Il y a un tas de petites tâches faciles si vous voulez contribuer à ZdS : https://github.com/zestedesavoir/zds-site/issues?q=is%3Aissue+is%3Aopen+label%3AC-Front

+0 -0

En fait tu réponds presque à ta propre erreur :

Toutes les fonctions sont des closures, même si on ne l'utilise pas toujours.

C'est pas vraiment ça.

N'importe quelle function peut être une closure si elle fait appel à des variables du scope de son parent.

Dans la pratique, la distinction est extrêmement importante. Savoir ce qu'est une closure et notamment par opposition à une fonction pure (pas de variables "externes" est nécessaire mais pas suffisant : pas d'effet de bord - écriture sur le disque, … -, pas d'appel à new Date(), random, …) permet de savoir sur quelles fonctions on peut faire de la mémoïsation ou non.

Et ça, quand on commence à aller chercher des perfs assez importantes (en JS : éviter des manipulations sur le DOM, côté serveur : répondre extrêmement vite sans désérialiser les données reçues, …) c'est extrêmement important.

La currification ou les fonctions de haut-niveau sont un exemple (très intéressant) d'utilisation des closures mais il me semble important de faire comprendre aux débutants ce qui fait le charme certes, mais aussi le danger des closures.

Happiness is a warm puppy

+0 -0
Auteur du sujet

@EtienneR : Oui… mais non

  1. On peut faire ça en CSS pur avec une checkbox cachée
  2. Ce HTML n’est pas accessible (span au lieu de button, div au lieu de nav…)
  3. Tu interceptes la touche Esc qui peut avoir d’autres usages dans le documents
  4. Plutôt que d’ajouter une bête class, autant utiliser l’attribut hidden et/ou aria-hidden
  5. onkeyup, c’était bien il y a 10 ans, maintenant on préfère ajouter un EventListener proprement ;)

Édité par viki53

Mes tutos — Architecte technique : JS/Node/Angular/Mongo, PHP/MySQL — Consultant qualité, ergonomie et UX

+0 -0

Rien sur es6?

Fonctions
1
2
3
4
let myFunction = (firstArg, secondArg='world') => {
    console.log(`Le premier argument est: ${firstArg}, et le deuxieme est ${secondArg}`)
}
myFunction('hello') // Le premier argument est: hello, et le deuxieme est world

Ces fonctions flechee on sont differentes des "normales": on ne peux pas changer sa valeur de this.

1
2
3
document.body.addEventListener('click', e => {
    console.log(this)
})

Quand on click sur body, ca log l’object window (parce que au moment ou j’ai creer ma fonction, this avait cette valeur)

C’est tres pratique quand on travaille avec des classes, et des nested evenements.

Si il n’y a qu’un seul argument, vous n’etes pas oblige de mettre des paranthese.

Récupérer les valeurs d’un select

Select simple

1
2
3
4
5
6
<select name="agrumes">
    <option value="citron">citron</option>
    <option value="clementine">clémentine</option>
    <option value="orange">orange</option>
    <option value="pamplemousse">pamplemousse</option>
</select>

On récupère la valeur avec la fonction change dans addEventListener.

1
2
const el = document.querySelector('[name="agrumes"]')
el.addEventListener('change', () => console.log(el.value))

Mutliselect

1
2
3
4
5
6
<select name="agrumes" multiple>
    <option value="citron">citron</option>
    <option value="clementine">clémentine</option>
    <option value="orange">orange</option>
    <option value="pamplemousse">pamplemousse</option>
</select>

On récupère la ou les valeur(s) dans un tableau.

1
2
3
4
5
6
7
const el = document.getElementsByName('agrumes')[0]
el.addEventListener('change', () => console.log(
  Array
    .from(el.options)
    .filter(option => option.selected)
    .map(option => option.value))
)

Edit : prise en compte des remarques de victor et de viki53. Merci à vous :)

Édité par EtienneR

HTTP/1.1 418 I’m a teapot

+0 -1
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// pas de raison que ce soit `let`
let el = document.getElementsByName('agrumes')[0]
// pas nécessaire d'avoir `function` au lieu d'une arrow function
el.onchange = function () {
    // pas besoin de tout ça mais commentons quand même :
    let result = [] // `const` à nouveau, pas let
    for (i in el.options) { // attention, `i` n'est pas déclaré, si y'a un `i` dans le scope parent…
        if (el.options[i].selected) {
            result.push(el.options[i].value)
        }
    }
    console.table(result)
}

// =>

const el = document.getElementsByName('agrumes')[0]
el.onchange = () =>
  Array
    .from(el.options)
    .filter(option => option.selected)
    .map(option => option.value)

// et si tu tiens à `console.log`
el.onchange = () => console.log(
  Array
    .from(el.options)
    .filter(option => option.selected)
    .map(option => option.value))

;)

(Je fais pas les autres parce que bon, un exemple suffit !)

[edit] Boarf remontons un peu quand même :

Ces fonctions flechee on sont differentes des "normales": on ne peux pas changer sa valeur de this.

1
2
3
document.body.addEventListener('click', e => {
    console.log(this)
})

Quand on click sur body, ca log l’object window (parce que au moment ou j’ai creer ma fonction, this avait cette valeur)

C’est pas une question de changer this, on peut très bien le faire :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(function () {
  console.log(`${this.a} ${this.b}`) // undefined undefined
  this.a = "foo"
  const x = () => {
    this.a += " bar"
    this.b = "baz"
  }
  x()
  console.log(`${this.a} ${this.b}`) // foo bar baz
})()

Et si ça log window dans ton cas, c’est parce que dans un navigateur this est toujours window dans le scope de base, et t’as probablement tapé ça dans la console de ton navigateur.

Une arrow function ne bind jamais this, donc this est toujours celui du premier scope parent bindant this.

Édité par cepus

Vous aimez le frontend ? Il y a un tas de petites tâches faciles si vous voulez contribuer à ZdS : https://github.com/zestedesavoir/zds-site/issues?q=is%3Aissue+is%3Aopen+label%3AC-Front

+2 -0
Auteur du sujet

On récupère la valeur avec la fonction native onchange.

EtienneR

À noter qu’il vaut mieux utiliser addEventListener que d’user d’une propriété qui ne permet d’avoir qu’un seul écouteur à la fois.

Édité par viki53

Mes tutos — Architecte technique : JS/Node/Angular/Mongo, PHP/MySQL — Consultant qualité, ergonomie et UX

+2 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte