2010-11-26 15 views
0

Ich habe eine Chat-Klasse mit zwei Methoden: UpdateChat und sendChat.jquery Variable Umfang Problem

//chat.js 
var state; 
var room; 

function Chat (theRoom) { 
    this.update = updateChat; 
    this.send = sendChat; 
    this.room = theRoom; 
} 

function updateChat(){  
     alert('ROOM: '+this.room); 

     $.ajax({ 
      type: "POST", 
      url: "/chat/process.php", 
      data: { 
       'function': 'update', 
       'state': state, 
       'room': this.room 
      }, 
      dataType: "json", 
      success: function(data){ 
       if(data.text){ 
        for (var i = 0; i < data.text.length; i++) { 
         $('#chat-area').append($("<p>"+ data.text[i] +"</p>")); 
        } 
       } 
       if(data.state) 
        state = data.state; 
      } 
     }); 
    } 
} 

//send the message 
function sendChat(message, nickname) 
{ 

    alert('A'+state); //20 

    //XXX   
    updateChat(); 

    alert('B'+state); //20 

    $.ajax({ 
     type: "POST", 
     url: "/live-event/chat/process.php", 
     data: { 
      'function': 'send', 
      'message': message, 
      'nickname': nickname, 
      'room': this.room 
     }, 
     dataType: "json", 
     success: function(data){ 

alert('C'+state); //wrong!: 2 //it should be 20! 

        //XXX   
      updateChat(); 

alert('D'+state); //21 

     }, 
    }); 
} 

Der Konstruktor des Chat-Objekt:

var chat = new Chat(4); //4 = the number of the chat room 

chat.send('test', 'tester'); 

Mein Problem sind die Verfahren bei den mit XXX markierten Stellen aufruft. In der updateChat() -Methode ist this.room nicht definiert, wenn ich die updateChat-Methoden wie diese aufrufen. Aber ich muss die Raumnummer übergeben, um den richtigen Status zu erhalten (Status ist einfach die Anzahl der Zeilen in der Textdatei des Chatrooms).

Ich denke, dass es ein Problem mit dem Variablenbereich oder mit den Methoden ist, die im Kontext des Objekts nicht aufgerufen werden.

Antwort

2

Sie müssen this halten, wenn diese Methoden aufrufen, so statt dies:

updateChat(); 

Sie können .call() verwenden Kontext zu halten (so this nicht zu window innerhalb der aufgerufenen Funktion nicht zurückkommen), wie diese :

updateChat.call(this); 

Oder Sie das folgende Verfahren auf dem Objekt als @casablanca Punkte nennen:

this.update(); 

Es gibt auch ein weiteres Problem wird this nicht sein, was Sie in Ihrem $.ajax() Rückrufe wollen, wird es die Ajax-Einstellungen Objekt standardmäßig, so dass Sie die context Option festlegen müssen sie aufrecht zu erhalten, wie folgt:

$.ajax({ 
    context: this, 
    type: "POST", 
    //...rest of your current options/methods 
+0

In diesem Fall 'this.update() 'würde genauso gut funktionieren. – casablanca

+0

@casablanca - +1 - yup auch wahr, wird aktualisiert, um –

+0

Vielen Dank Nick (und Casablanca) zu enthalten. Das hat mein Problem gelöst. Wenn ich das erst ein paar Stunden vorher ausprobiert hätte. :-( – user478419

0

Sie können das leichter finden, wenn Sie Klassen vergessen. Was du dort geschrieben hast, ist keine Klasse. In JavaScript gibt es keine Klassen. Sie haben eine Konstruktorfunktion geschrieben, die aber etwas zweifelhaft ist, weil Sie die Elemente für jede Instanz einzeln zuweisen. Der Hauptzweck von Konstruktorfunktionen besteht darin, die Vererbung von Prototypen zu nutzen, sodass Sie die "Methoden" dem Prototyp der Konstruktorfunktion zuweisen.

function Chat (theRoom) { 
    this.room = theRoom; 
} 

Chat.prototype.send = sendChat; 
Chat.prototype.update = updateChat; 

Auf diese Weise jeweils mit new Chat(r) erstellte Objekt wird nur die Zimmernummer speichern müssen, und nicht die beiden Methoden als Eigenschaften speichern müssen.

Alternativ schreiben Sie einfach eine createChatRoom Funktion:

var createChatRoom = function(room) { 

    return { 
     update: function() {  
      alert('updating: ' + room); 
      // ... other stuff 
     }, 

     sending: function() {  
      alert('sending: ' + room); 
      // ... other stuff 
     } 
    }; 
}; 

Die Schönheit das ist wohl klar: Sie etwas mit this nicht Präfix müssen. Der room Parameter ist im Bereich der Methodendefinitionen und ist auch wirklich privat (kann nicht geändert werden, außer durch Aufrufe an die Methoden. Und der Anrufer muss nicht daran denken, new zu setzen. Sie rufen nur die Funktion und erhalten ein frisches zurück Objekt mit zwei Methoden drin.

Sie können sogar das sicher tun:

setTimeout(chatRoom.update, 10); 

Die update Funktion „weiß“, welches Objekt es verknüpft ist. Es muss nie gesagt werden, welches this zu verwenden ist.

Dies ist so bequem und nützlich, wenn ich nicht sehr große Mengen von Objekten erstellen gehe davon aus, ich habe nicht mit Konstruktorfunktionen stören, new, prototype usw.