2010-06-11 5 views
9

Dans l'exemple de code ci-dessous, la fonction de rappel de succès enregistre quatre fois l'entrée # 04.update 'plutôt que chaque entrée individuelle, ce qui est logique pour voir comment fonctionnent les fermetures. entrée individuelle en utilisant cela.AJAX Fermetures et ciblage 'this'

<input type="text" name="" id="01" class="update"> 
<input type="text" name="" id="02" class="update"> 
<input type="text" name="" id="03" class="update"> 
<input type="text" name="" id="04" class="update"> 

function updateFields(){ 
$('input.update').each(function(){ 
    $this = $(this); 
    $.ajax({ 
     data: 'id=' + this.id, 
     success: function(resp){ 
     console.log($this); 
      $this.val(resp) 
     } 
    }); 
    }); 
} 

Répondre

12

Vous avez oublié var

var $this = $(this); 

Ne pas oublier var. Un programmeur qui a oublié var est allé au lit la nuit et s'est réveillé pour trouver son appartement en feu. Il a ajouté var et le feu s'est éteint. Un autre programmeur a quitté var sur complètement peu avant de partir en voyage d'affaires en Europe. L'avion a développé des problèmes mécaniques en vol peu après le décollage, ce qui a amené le pilote à lancer des procédures d'atterrissage d'urgence. De son ordinateur portable le programmeur a rapidement ajouté var et l'avion l'a fait en toute sécurité à un aéroport.

N'oubliez pas var. Si vous mettez var dans votre code, vous rencontrerez quelqu'un de spécial aujourd'hui. Essayez-le. Cela semble incroyable mais ça marche vraiment!

+0

C'est incroyable ... mais ... pourriez-vous me dire une raison technique de le faire? Je veux dire, j'oublie parfois d'ajouter 'var' ... et je n'ai pas eu de problèmes. Mais vos mots sont effrayants, et à partir de maintenant je n'oublierai pas d'ajouter 'var'. De toute façon ... avez-vous une explication technique pour ce genre de problèmes? – Cristian

+0

La raison: votre gestionnaire 'success', la fonction anonyme fait référence à une variable' $ this' qui est globale. Ainsi, chacune des 4 instances de cette fonction anonyme fait référence à la même variable et donc à la même valeur, puisqu'elles sont exécutées longtemps après que la fonction 'each' soit retournée. – Alsciende

+1

@Cristian - Sans le 'var', c'est une variable globale que vous mettez à jour chaque boucle, pas locale à la portée de cette fermeture que vous voulez qu'elle soit dans ce cas. –

3

correct de Pointy sur l'utilisation var, une autre alternative est d'utiliser $.proxy(), comme ceci:

function updateFields(){ 
$('input.update').each(function(){ 
    $.ajax({ 
     data: 'id=' + this.id, 
     success: $.proxy(function(resp){ 
       $(this).val(resp); 
       }, this) 
    }); 
    }); 
} 

Ce créateur de fermeture fera this référence à l'élément d'entrée lorsque vous êtes dans la fonction de rappel success, qui est habituellement ce que vous cherchez ... alors je ne sais pas pourquoi ce n'est pas le cas par défaut, mais dans tous les cas $.proxy() rectifie la situation.

+0

+1 pour me faire lire sur '$ .proxy()'. – user113716

+0

'$ .proxy()' est sympa mais je souhaite qu'il supporte aussi le "bourrage de paramètres" ou fausse currying que supporte '.bind' de Prototype. Maintenant, je vais devoir vérifier si le nouveau '.bind' d'ECMAScript 5 est semblable à celui de Prototype. – Pointy

+0

@Pointy - La seconde approche '$ .proxy()' peut faire une mutation comme celle-ci en fonction de la façon dont vous la structurez ... mais ouais ce n'est pas à la hauteur du prototype, mais je pense qu'il ne manque pas beaucoup ... Je pense que les deux bibliothèques adoptent une approche très différente de la liaison et de l'itération en ce qui concerne les fermetures, jQuery a tendance à créer plus pour vous en cours de route, pour le meilleur ou pour le pire. –