Javascript – Child object calling a parent’s function through a global variable

event-programmingjavascript

I have a Session object, of which a single global instance session holds the current session, which can persist itself to the server, handle undos redos etc.

The session holds an instance of Objects which is in this example basically a set of Cars objects. When user changes e.g. a marker on a map representing a car's location, I want to update the corresponding Car object AND save the session to be able to redo and persist it to the server.

Incomplete diagram:

enter image description here

Code:

function Session(sessionId, objectsSave){
    this.objects = new Objects();

    if (objectsSave !== undefined)
        this.objects.restore(objectsSave);

Session.prototype.saveSession = function() {
    var save = this.objects.save();
    // persist to server and add to redoStack
}

function Objects() {
    this.objects = [];
}

Objects.prototype.restore = function(save){
    var objects = [];

    save.forEach(function(obj) {
        objects.push(Car.prototype.restore(obj));
    }); 

    this.objects = objects;
};

function Car(){
    this.markerOnMap = new Marker();
    this.markerOnMap.onDrag = this.setLocation;
    this.markerOnMap.onDragEnd = session.saveSession;  // here using the global variable, does not work when instantiating Session with a save object

Car.prototype.setLocation = function(e) {
    this.location = e.location;
}

var session = new Session();

The problem emerges (besides the "bad design" feeling) when I want to instantiate a Session e.g. with data from the server. In Session constructor I create a new Objects instance, and restore it with the save, which will create Car objects, which will try to reference a function of the global variable session. But session is not assigned yet, because this code was called from the constructor of Session.
I could have e.g. changed it to:

        this.markerOnMap.onDragEnd = function(){session.saveSession()};

or pass this from Session constructor all the way down to the constructor of Car.
I don't know what is worse, to have a global variable, all circular references, or is there a better solution?

Best Answer

There is indeed a design flaw in your construction process: the Car requires the Session at its creation. This dependency then becomes an issue when the Car is deserialized during the resort of the Session.

The problem is due to the non respect of the principle of single responsibility: when you construct a Car, you should only create the object, and not insert it into some container. This second step should be the responsibility of the function/object that instantiates the Car for a specific purpose.

In your case, I'd recommend to consider the builder design pattern.. This design separates the building of complex objects (here the Session) into building and assembling its parts. This requires that parts can be constructed independently.

Related Topic