I’m new to Javascript and I just discovered the property keyword for defining functions for objects. I tried to refactor my websocket experiment using objects, but I can’t get it to work.
This works (no objects):
var ws = new WebSocket(something, somethingelse);
ws.onopen = function() {
ws.send("hello");
console.log("works");
}
But this doesn’t:
function MyObject() {
this.ws = new WebSocket(something, somethingelse);
this.ws.onopen = this.onOpen;
}
MyObject.prototype.onOpen = function() {
this.ws.send("hello"); // undefined!
};
Why is ws undefined? Am I assigning the onOpen function incorrectly?
You are assigning functions correctly (there is only one way of assigning functions), your problem is that the context of the function changes.
Consider this line:
Possibility 1:
Now I assume, inside
WebSocket, somewhere this function gets called as a response to an opening connection (like an event handler), probably likeWhat
thisrefers to inside a function is determined by how a function is called on run time (<-read this link, it helps a lot). It is not bound at definition time. In your case,thiswould refer to theWebSocketinstance.So inside if called this way, inside
MyObject.prototype.onOpen,thisrefers tothis.ws, theWebSocketinstance, which does not have awsproperty, and not theMyObjectinstance.This can be solved in two ways:
Since
thisalready refers tothis.ws, you can callsenddirectly onthis:If you want
thisinsideMyObject.prototype.onOpento always refer to theMyObjectinstance, you have to keep an explicit reference to the instance, e.g. through a closure:Now inside
onOpen,thisrefers to theMyObjectinstance which has a propertyws, just like you set it up in the constructor.In browsers supporting ECMAScript 5, functions already have a method for this technique, called
.bind():Possibility 2:
It could also be that
WebSocketcallsonopenin such a way:In that case,
thiswould either refer towindowor would beundefined, depending on whether the code runs in strict mode or not (it does not matter, in any case it is a problem).This situation could only be solved with the second solution from the first possibility.
Why does the first example work?
In this case, the function you assign to
ws.onopenis a closure, closing over the variables defined in this scope, alsows. In this sense it is similar to the second way of solving the problem, butwould probably work as well.