2012-04-13 3 views
3

J'enveloppé (-côté client) socket.io dans une classe prototype:contexte original 'ceci' avec Socket.IO

Chat.Client = Class.create(); 

Chat.Client.prototype = { 

    initialize: function() { 
     ... 
     this.socket.on('message', this.on_message); 
     ... 
    }, 

    on_message: function(data) { 
     this.add_chat_message(data.something); 
    } 

    do_something: function(something) { 
     ... 
    } 

Cela ne fonctionne pas parce que 'ceci' dans ON_MESSAGE sera 'SocketNamespace' . Traditionnellement, je voudrais contourner ce problème en passant simplement 'this' dans le callback en tant que paramètre supplémentaire, mais comme j'utilise socket.io, je ne peux pas le faire simplement.

Comment puis-je résoudre ce problème?

Répondre

9

Vous pouvez envelopper dans une autre fonction:

initialize: function() { 
    // ... 
    var client = this; 
    this.socket.on('message', function(data) { client.on_message(data); }); 

Dans les navigateurs les plus récents (ou Node.js), vous pouvez également utiliser une fonction sur le prototype Function appelé "bind":

this.socket.on('message', this.on_message.bind(this)); 

La fonction "bind" renvoie une fonction qui, lorsqu'elle est appelée, forcera la fonction d'origine ("on_message") à être invoquée avec la valeur donnée comme valeur this.

+0

Merci, bind fonctionne. (maintenant je vais devoir attendre 8 minutes pour accepter votre réponse) –

+0

Content de vous aider. – Pointy

+1

Petit ajout: les bibliothèques JS connues fournissent des fonctionnalités de liaison. Si l'on utilise [underscore.js] (http://underscorejs.com), il y a une fonction crossbrowser 'bind':' _.bind (function() {...}, this) '. Il y a aussi la fonction 'proxy' dans jQuery, qui fait la même chose:' $ .proxy (function() {...}, this) '. Voici un [test de performance avec des exemples] (http://jsperf.com/bind-vs-jquery-proxy/5) pour tous les moyens de le faire. – HighCat