George Reith
George Reith

Reputation: 13476

Accessing an object's parent

Ok, first up I know an object has no reference to it's container unless explicitly defined, so I am looking for a work around here.

Take the following code (heavily simplified from my use case for readability):

var cid = 0;
var Command = function(c) {
    this.id = cid += 1;
    this.transient = false;
    return this;
}

var sid = 0;
var CommandSet = function() {
    this.id = sid += 1;
    this.commands = [];
    this.transients = 0;
    return this;
}

CommandSet.prototype.parent = null;
CommandSet.prototype.recurse = function(callback) {
    callback.call(this);
    if (this.parent instanceof CommandSet) {
        this.parent.recurse(callback);
    }
}

CommandSet.prototype.createSubset = function() {
    var set = new CommandSet();
    set.parent = this;
    set.commands = this.commands;
    set.transients = this.transients;
    return set;
}


CommandSet.prototype.addCommand = function(c) {
    if (c instanceof Command) {
        this.commands.push(c);
        if (c.transient) {
            this.recurse(function() {
                this.transients++;
            });
        }
    }
    return this;
}

CommandSet.prototype.toggleTransient = function(c) {
    if (c instanceof Command) {
        c.transient = true;
        this.recurse(function() {
            this.transients++;
        });
    }
    return this;
}

If I then do the following (http://jsfiddle.net/5KGd8/1/):

var s1 = new CommandSet();
var c1 = new Command();
var c2 = new Command();
s1.addCommand(c1).addCommand(c2);

var s2 = s1.createSubset();
var s3 = s1.createSubset();
s2.toggleTransient(c1);

console.log(s1);
console.log(s2);
console.log(s3);

s1 now has 1 transient, s2 now has 1 transient but s3 still has none despite containing a reference to the same Command objects.

Possible solutions:

  1. I could build a reference into each command which stores all the sets it is located inside and iterate through those, however this is going to cause some serious memory issues as the real nature of my application requires that subsets can be garbage collected (The user will create a lot of them anonymously often without realising) and this will retain a reference to them after they have been used. The parent reference is fine as I want the parent set to exist as long as it has a surviving subset.

  2. I could explicitly force the user to run a delete function on a subset when it is no longer needed which would remove all internal references to it but this complicates things for them and I like things to work automagically. The nature of my application means I would like the user to create subsets at times where they may not even realise they have done so (Through other functions which create and perform on subsets).

Can anyone think of a way to solve this problem without the issues described in my two solutions?

Upvotes: 3

Views: 101

Answers (1)

HMR
HMR

Reputation: 39350

Sorry, this is not an answer but want to make sure I understand the problem.

A CommandSet can have Commands, when you change a Command's transient property you would like the CommandSet(s) that contain that Command to have an updated counter of transient the Commands it contains.

If the story ends here you could simply have Command maintain a list of CommandSet that the Command is in and update it's containers.

This would not work however because you would have CommandSets created in a function and when these go out of scope they won't be garbage collected because the Command(s) they contain would hold a reference to them. These commands would not go out of scope with the CommandSets because they are also contained in other (global) CommandSets.

Re assigning a primitive type (transients) does not re assign that in the subset or main set, but what if transients was not a primitive?

In the constructor:

this.transients = {count:0};

In createSubset

set.transients = this.transients

In the toggleTransient

this.transients.count++; or --

No matter if you fiddle with transients in subset or main set, as long as you use the toggleTransient it'll change count for all.

Upvotes: 1

Related Questions