11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous,

Voici un comportement de Javascript que j'ai (encore) du mal à comprendre. Il concerne la portée des variables locales et les gestionnaires d'événements.

Exemple - Code HTML
<a href="#" id="lien0">Lien 0</a>
<a href="#" id="lien1">Lien 1</a>
<a href="#" id="lien2">Lien 2</a>
<a href="#" id="lien3">Lien 3</a>
<a href="#" id="lien4">Lien 4</a>


Code Javascript (utilise Jquery mais ça ne change pas grand chose)
$(function(){
	for(var i=0; i<5; i++){
		$("#lien"+i).click(function(){
			alert("J'ai cliqué sur le lien "+i); 
		});
	}
});


On s'attend "logiquement" à ce que lorsqu'on clique sur un des liens, le message d'alerte contienne la valeur de "i" correspondant au numéro du lien. Mais ce n'est pas le cas, l'alerte affichera toujours "5", soit la dernière valeur qu'a eu "i" dans ma boucle.

Il me semblait avoir déjà résolu ce genre de cas en passant par une variable intermédiaire, comme ceci:
$(function(){
	for(var i=0; i<5; i++){
		var moni = i;
		$("#lien"+i).click(function(){
			alert("J'ai cliqué sur le lien "+moni); 
		});
	}
});


Mais ça ne change pas grand chose. Cette fois, l'alerte affichera "4" pour chaque lien, soit la dernière valeur de la variable "moni".

Pourquoi ce phénomène ? Y a-t-il une solution pour le contourner ?

Merci d'avance Smiley biggrin
Modifié par jiber2fr (04 Jun 2011 - 10:05)
Bonjour, c'est extrêmement simple.

En javascript les variables ont une portée égale à la fonction dans laquelle elle sont déclarées Donc ta variable "i" a une portée égale à ta fonction anonyme externe (en rouge)

a écrit :
$(function(){
for(
var i=0; i<5; i++){
$("#lien"+i).click(function(){
alert("J'ai cliqué sur le lien "+i);
});
}
}
);


Quand tu invoque la fonction anonyme interne sur le click, cette fonction vachercher la variable "i" dans la fonction anonyme externe. Et ce pour tes cinq fonctions !!! Tu as cinq fonctions associés à cinq clics, mais une seule variable "i" déclarée un niveau au dessus !
Il est donc tout à fait logique que cette variable retourne la dernière valeur qu'on lui as attribuée, en l'occurence "5".
Merci Smiley smile

Pour avoir une variable locale, j'ai donc sorti l'intérieur de ma boucle dans une autre fonction, ce qui fonctionne parfaitement. En reprenant mon exemple simpliste, ça donne:


$(function(){
	for(var i=0; i<5; i++){
		appliquerEvenement(i);
	}
});

function appliquerEvenement(index){
	$("#lien"+index).click(function(){ 
		alert("J'ai cliqué sur le lien "+index);  
	});	
}


Smiley cligne