I’m starting to get my head around prototyping and closures, within Javascript, but not quite. This example below, my two objects, the second object seems to lose scope/context and takes over the first objects identity.
function broker()
{
var _q = [];
this.add = function(delegate) {_q[_q.length] = delegate; }
this.broadcast = function(message)
{
for(qi = 0; qi < _q.length; qi++)
{
_q[qi](message);
}
}
}
function subscriber(abroker, yourname)
{
me = this;
this.myprop = yourname;
this.subby = function(message){ alert(message + " " + me.myprop + me.dosomething() + secret()); };
this.dosomething = function() {return "...abc";};
function secret(){return "...def";}
abroker.add(this.subby);
}
var thebroker = new broker();
var mysub = new subscriber(thebroker, 'mysub');
var myothersub = new subscriber(thebroker, 'myothersub');
thebroker.broadcast("hello from");
The idea is that there is a common broker object that can invoke a delegate on subscriber objects and execute functions within. But I’m losing scope within the invoked function called by the broker.
output: 2 alerts windows, both output: “myothersub”, mysub seems to lose scope?
I have successfully achieved the correct response by explicitly declaring the subby delegate outside of the original object, and referencing the entire object, e.g:
Instead of declaring this.subby within the subscriber object:
mysub.subby = function(message)
{
alert(message + " " + mysub.myprop); // obv the dosomething his hidden
}
thebroker.add(mysub.subby);
Excuse me if any of the above syntax is wrong, from typing directly from memory. It does work in practice, but loses the encapsulation I’m used to.
How can I encapsulate using the original technique within out losing scope/context of the object?
SHORT ANSWER: It looks as though the problem is simply to do with your declaration of
mein thesubscriberconstructor. At the minimum you need to put avarin front of it to make it a local/private variable for each object. Sovar me = this;instead ofme = this;.EXPLANATION: In JavaScript, when you don’t explicitly declare a variable with
var, it makes the variable global. So what was happening in your original script is that you createdmysubwhich declaredmeas a global reference to thethisinside themysubobject. But as soon as you createdmyothersubthe globalmewas overwritten to thethisinside the newmyothersubobject.Because your
subbymethod created an alert that was based onmeit didn’t matter which object you called it from since the method in both objects was not using anything local or specific to the object but merely referencing the same global variable — thethisinside the last such object to be createdBy simply writing
var me = this;instead ofme = this;you create a local version ofmewithin a closure each time for each new object you create and not one that is overwritten.…
PS. Extra tip. You should do this with all variables to ensure that you have as few globals as possible, especially when you don’t mean them to be global! Therefore I’d make the same declaration for the variable
qiinside thebrokerconstructor. You could do this simply by declaring inside the loop conditions, e.g.,for (var qi = 0; qi < _q.length; qi++). That would be enough to stopqibeing a global variable.However, in the interests of keeping your code easy to read it’s best to declare all variables at the top of a function. So I would recommend simply rewriting the
broadcastmethod thus:If you haven’t come across him before, Douglas Crockford is a really good go-to writer on JavaScript when it comes to closures, object creation and just good code writing conventions. There’s a bunch of tips on this page and you can find videos of him lecturing on the topic quite easily. All this really helped me when I started looking into closures and other aspects of JavaScript more closely; hope it helps you too.