javascript: prototypes with callbacks and 'this'

callback, javascript, prototype, websocket

Solution

When you do:

self = this

You are implicitly creating a global variable which (since it's global) will have the same value for all instances. Local variables, must have `var`, `let` or `const` in front of them like one of these:

var self = this;
const self = this;
let self = this;

But, that isn't your solution here. You need to be using `this` instead. And, if you're going to supply a callback for the websocket and you want the person associated with that, I would suggest you just put a reference to the Person object on the websocket so you can then retrieve it from there. And, what's with all the missing semicolons to end each statement? Anyway, here is some fixed up code:

function Person(name){
    this.name = name;
}

Person.prototype = {
    getName : function(){
        return this.name;
    },

    openConnection : function(host, port){
        this.pointCount = 0;
        this.ws = new WebSocket("ws://" + host + ":" + port);
        // save person reference on the web socket
        // so we have access to the person from web socket callbacks
        this.ws.person = this;   
        this.ws.onopen = this.onOpenConnection;
    },

    onOpenConnection : function()   {
        // "this" will be the websocket
        // "this.person" is the person object
        console.log(this); // prints the websocket
        console.log(this.person); // prints the person
        this.send(this.person.name); // works only if one person exists
    }
}

Problem

I've create a prototype based class `Person` that opens a WebSocket connection and defines callback functions as prototype methods. Because inside the callback `this` will refer to the WebSocket object I used another variable to hold on to the `Person`'s `this`. However when I deal with multiple instances the variable gets overwritten. Here is a small snipped that shows the issue: ``` function Person(name){ self = this self.name = name } Person.prototype = { getName : function(){ return self.name }, openConnection : function(host, port){ self.pointCount = 0 self.ws = new WebSocket("ws://" + host + ":" + port) self.ws.onopen = self.onOpenConnection }, onOpenConnection : function() { console.log(this) // prints the websocket console.log(self) // prints the person self.ws.send(self.name) // works only if one person exists } } var p1 = new Person("Jonh") var p2 = new Person("Adam") console.log(p1.getName()) // Prints Adam console.log(p2.getName()) // Prints Adam p1.openConnection("localhost", 7000) // opens connection for p1 p2.openConnection("localhost", 7000) // opens another connection for p1 ``` If more than one `Person` is created, then when trying to send a message via the socket I get the following error: Uncaught Error: INVALID_STATE_ERR: DOM Exception 11 So it seems that `self` is defined globally and my attempt to get a handle to the `Person`'s `this` inside the callback fails. Any suggestions on how to achieve that?

Original source