简体   繁体   中英

How can I encapsulate object property so that previous object isn't taken over? (Prototypes/closure.)

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.

2 alerts windows, both output: "myothersub", mysub seems to lose scope? 2个警报窗口,都输出:“ myothersub”,mysub似乎失去作用域?

I have successfully achieved the correct response by explicitly declaring the subby delegate outside of the original object, and referencing the entire object, eg:

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 me in the subscriber constructor. At the minimum you need to put a var in front of it to make it a local/private variable for each object. So var me = this; instead of me = 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 created mysub which declared me as a global reference to the this inside the mysub object. But as soon as you created myothersub the global me was overwritten to the this inside the new myothersub object.

Because your subby method created an alert that was based on me it 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 -- the this inside the last such object to be created

By simply writing var me = this; instead of me = this; you create a local version of me within 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 qi inside the broker constructor. You could do this simply by declaring inside the loop conditions, eg, for (var qi = 0; qi < _q.length; qi++) . That would be enough to stop qi being 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 broadcast method thus:

this.broadcast = function(message) {
    var qi,             // STOPS `qi` BECOMING A GLOBAL
        ql = q.length;  // SO DON'T HAVE TO CHECK LENGTH OF `q` EVERY LOOP
    for(qi = 0; qi < ql; qi += 1) {
        _q[qi](message);
    }
};

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM