2010-06-11 6 views
9

In dem Codebeispiel protokolliert die Erfolgsrückruffunktion die Eingabe # 04.update viermal statt jeder einzelnen Eingabe individuelle Eingabe mit diesem.AJAX Closures und Targeting '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) 
     } 
    }); 
    }); 
} 

Antwort

12

Sie haben vergessen var

var $this = $(this); 

nicht var Vergessen Sie. Ein Programmierer, der var vergaß, ging nachts ins Bett und wachte auf, um seine brennende Wohnung zu finden. Er fügte var hinzu und das Feuer ging aus. Ein anderer Programmierer verließ var aus komplett kurz vor dem Verlassen auf einer Geschäftsreise nach Europa. Das Flugzeug entwickelte kurz nach dem Start mechanische Probleme während des Fluges und veranlasste den Piloten, Notlandungsverfahren einzuleiten. Von seinem Laptop aus fügte der Programmierer schnell var hinzu und das Flugzeug schaffte es sicher zum Flughafen.

Nicht vergessen var. Wenn Sie var in Ihren Code eingeben, werden Sie jemanden treffen, der heute ist. Versuch es. Es klingt fantastisch, aber es funktioniert wirklich!

+0

Das ist erstaunlich ... aber ... könnten Sie mir einen technischen Grund dafür geben? Ich vergesse manchmal, 'var' hinzuzufügen ... und ich hatte keine Probleme. Aber deine Worte sind gruselig, und von jetzt an werde ich nicht vergessen, 'var' hinzuzufügen. Wie auch immer ... hast du eine technische Erklärung für diese Art von Problemen? – Cristian

+0

Der Grund: Ihr 'success'-Handler, anonyme Funktion, verweist auf eine Variable $ this, die global ist. Jede der 4 Instanzen dieser anonymen Funktion referenziert also die gleiche Variable und daher den gleichen Wert, da sie lange nach der Rückkehr der 'each'-Funktion ausgeführt werden. – Alsciende

+1

@Cristian - Ohne die 'var' ist es eine globale Variable, die Sie jede Schleife aktualisieren, nicht lokal für den Bereich dieser Schließung, den Sie in diesem Fall haben wollen. –

3

Zipfel korrekt ist auf var-Nutzung, eine weitere Alternative ist $.proxy() zu verwenden, wie folgt aus:

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

Dieses Konzept Schließung this beziehen sich auf das Eingangselement machen, wenn Sie in der success Rückruf sind, die in der Regel Was Sie suchen ... also bin ich mir nicht sicher, warum das nicht standardmäßig der Fall ist, aber auf jeden Fall korrigiert $.proxy() die Situation.

+0

+1 für mich auf '$ .proxy()' lesen. – user113716

+0

'$ .proxy()' ist nett, aber ich wünschte, es unterstützt auch die "Parameter Stuffing" oder gefälschte currying, dass Prototype '.bind' unterstützt. Jetzt muss ich überprüfen, ob das neue ECMAScript 5 '.bind' wie das von Prototype ist. – Pointy

+0

@Pointy - Der zweite '$ .proxy()' Ansatz kann einige Mutationen machen, je nachdem, wie Sie ihn strukturieren ... aber ja, es ist kein Prototyp, aber ich denke, es fehlt nicht wirklich viel ... Ich denke, dass die 2 Bibliotheken nur einen ganz anderen Ansatz für die Bindung und Iteration in Bezug auf Verschlüsse nehmen, jQuery neigt dazu, mehr für Sie auf dem Weg zu schaffen, zum Guten oder zum Schlechten. –