Dans des cas comme celui ci-dessous, où l’on souhaite créer des éléments et leur attribuer un événement
onclick dépendant d’une variable de boucle :
1 2 3 4 5 6 7 8
| function foo() {
for (var i = 0; i < 10; i++) {
var MonDiv = document.createElement("div");
MonDiv.textContent = "div " + i;
MonDiv.onclick = function () { alert(i); };
document.body.appendChild(MonDiv);
}
} |
Cette fonction est censée permettre de créer 10 nouveaux divs contenant les textes « div 1 », « div 2 », etc. et de les insérer dans la page. On leur attribue également un
onclick avec pour but de faire un
alert() de « 1 » sur le premier div, « 2 » sur le second, etc.
Malheureusement cela ne fonctionne pas : les divs sont correctement créés et insérés mais au clic, tous affichent le message « 10 ». En fait, la valeur de
i n’est pas évaluée au moment de la mise en place du
onclick, mais seulement au moment où celui-ci est appelé. Or à ce moment, sa valeur vaut bien 10, la dernière valeur de la boucle.
La solution moderne (fin 2017) est d’utiliser le mot-clé
let, apparu avec ECMAScript 2015, qui fonctionne un peu comme
var mais qui limite la portée des variables au bloc courant, en l’occurence le corps de la boucle
for.
1 2 3 4 5 6 7 8
| function foo() {
for (let i = 0; i < 10; i++) {
let MonDiv = document.createElement("div");
MonDiv.textContent = "div " + i;
MonDiv.onclick = function () { alert(i); };
document.body.appendChild(MonDiv);
}
} |
Si vous développez dans un environnement où
let n’est pas disponible, il faut recourir à une fonction anonyme :
1 2 3 4 5 6 7 8 9 10 11 12
| function foo() {
for (var i = 0; i < 10; i++) {
var MonDiv = document.createElement("div");
MonDiv.textContent = "div " + i;
(function (arg) {
MonDiv.onclick = function () { alert(arg); };
}(i));
document.body.appendChild(MonDiv);
}
} |
Cela fonctionne car la fonction anonyme copie la valeur de
i dans son argument
arg au moment où elle est appelée, c’est-à-dire au moment où la boucle
for est exécutée.
Partager