0

I am working on a web app that is modular with its root component being the Editor Object. This Editor object handles the creation of multiple components. One of these component objects is the Filebar component which has the ability to reference the functions from the Editor object. Since there are a lot of buttons in the menu within the Filebar, I have created a table named "index" in my code that I use to reference functions within the Editor object. I am able to get the reference to the function itself, but I am having trouble executing the function as if it were being executed in the original object itself. So here are my questions:

Question 1: How do I correctly reference the Editor object if I am calling the function from the Filebar object in order to pass the correct "this" into the new Inspector that I am creating?

Question 2: (A hopefully small side question) Is this a good practice to be referencing functions for my event listener in a table like the one I show in my code below?

function Editor() {

    // Initializes the Object. Called at end.
    this.Initialize = function() {
        thisCreateFileBar();
    }


    this.createFilebar = function(){
        this.file = new Filebar(this);
    };

    // Creates a Scene Object. 
    this.createScene = function() {
        this.scene = new Scene(this);
    };

    // Create an Inspector.
    this.createInspector = function(){
        this.inspector = new Inspector(this);
    };

    // Create a Hierarchy.
    this.createHierarchy = function(){
        this.hierarchy = new Hierarchy(this);
    };

    let thisCreateFilebar = this.createFilebar.bind(this);
    let thisCreateInspector = this.createInspector.bind(this);
    let thisCreateHierarchy = this.createHierarchy.bind(this);
    let thisCreateScene = this.createScene.bind(this);

function Filebar(editor){

    // Initializes the Object. Called at end.
    this.Initialize = function(){
        this.editor = editor;
        this.menu = document.getElementById("Engine_UI:Menu");
        this.menu.addEventListener("mouseup", thisChoice);
    }

    this.choice = function(event){
        // Question 2 Should I be referencing functions for my event listeners like this? 
        let index = {
            "Add Inspector": this.editor.createInspector,
            "Add Hierarchy": this.editor.createHierarchy,
            "Add Scene": this.editor.createScene
        };

        let element = event.target;
        if (element.innerHTML != null){
            let func = index[element.innerHTML];
            func(this.editor);
        } else return;
        event.stopPropagation();
    }

    let thisChoice = this.choice.bind(this);
    this.Initialize();
}

function Inspector(editor){
    console.log(editor) // Question 1 When passed directly from the editor object 
    // which passes in a reference to this, it passes itself
    // but when referenced from filebar it references the Window instead. 

    //other stuff happens here.
}

The one thing that I have done to make this work is pass in an extra variable for the reference. This ends up working the way I would like it to, but in my mind this feels a bit hacky and I wanted to see if there was a way to correctly bind the objects to make this work. Or maybe passing in a variable instead would be better practice than using a this reference, I am not sure. Please let me know your thoughts!

slyduda
  • 15
  • 3
  • Yes, this looks a bit weird. But it mostly does look weird because you are abusing the constructor to create all the methods as instance properties - [put them on the prototype instead](https://stackoverflow.com/q/310870/1048572)! Then it would make much more sense to `bind` them in the constructor. But if for some reason (closures) you really have to define them in the constructor, you should just close over the instance as well, using either the `var that = this` pattern or arrow functions. – Bergi Aug 01 '19 at 18:56
  • Also, you should not have an `Initialise` method that you call from the constructor. Just put that code in the constructor right away! Similarly, all those `createXY` methods - the properties should be initialised in the constructor, not from some method. At least create the properties in the constructor with the value `null`, and use a `setXY` method later, if there is any reason to defer the object creation. – Bergi Aug 01 '19 at 18:58
  • That makes sense. I will change that right away. Thank you for the help :) – slyduda Aug 01 '19 at 23:07

1 Answers1

0

In order to pass this to those functions, you have two options:

var myEditor = this;

this.createFilebar = function(){
    myEditor.file = new Filebar(myEditor);
};

Or you can use lambda functions, which will retain the this-ness.

this.createFileBar = () => this.file = new FileBar(this);
Michael Bianconi
  • 5,072
  • 1
  • 10
  • 25
  • Thank you. Arrow/Lambda functions are perfect for this. I should have been using them since the beginning. – slyduda Jul 31 '19 at 18:26