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:
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
parentreference is fine as I want the parent set to exist as long as it has a surviving subset.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?
return thising from the functions called as constructors?commandsis an array and you are only copying the reference to it buttransientsis a number which is really copiedthis.commands. If you can't then maybe turn transient into a function that returns transient commands (not sure if that will greatly affect performance)