Home > Software design >  Is there an easier way to refer to Javascript class methods from within the class?
Is there an easier way to refer to Javascript class methods from within the class?

Time:11-18

I come from a non-javascript coding background and one of the things that I am used to doing is encapsulating code in a class.

So I have a class file and it works but the constant reference to this. is lacks a certain elegance that makes me think that I am doing things the wrong way. Especially when I try to reference this. from within a "level" of code in a method and I have to carry the reference in a local variable to make it work.

So here is an example of what I have

class catalogue {

    constructor () {

        this.currentDoc = null;
        this.dataDirectory = "data/";

    }
    
    loadJSON(filepath) {
        // there is actual code in the real class
    }
    
    loadHTML(filePath) {
        // there is actual code in the real class
    }
    
    loadExternalData() {

        let filePath = `${this.dataDirectory}${this.currentDoc.filepath}`;
        let dataIsJson = this.currentDoc.filepath.indexOf('.json') != -1;

        let me = this; // this again :-(
        
        if (dataIsJson) {
            me.loadJSON(filePath);
        } else {
            me.loadHTML(filePath);
        }

    }
    
}

The loadExternalData() method is called from the code that creates an instance of the class. It then determines how to load the data that it required and it calls various methods depending on the type of data.

Back in the 'old days' I would have stored a reference to the class as a property of the class and then used that to call methods. The main problem is that, as we know, this. is contextual and as soon as you use a conditional or anything similar the context, for some bizarre reason, changes and this. is not useful to my class any more.

So all of this makes me think that I am not doing things in a Javascripty fashion.

Is there an easier way to refer to methods and properties without using this. or do I need to look at reworking the code?

CodePudding user response:

What you're doing is perfectly normal and common. If what you're worried about it:

The main problem is that, as we know, this. is contextual and as soon as you use a conditional or anything similar the context, for some bizarre reason, changes and this. is not useful to my class any more.

A very simple tweak is to use arrow function class fields instead, so that this will always refer to the instance, without having to worry about a changing calling context.

class catalogue {
    constructor () {

        this.currentDoc = null;
        this.dataDirectory = "data/";
    }
    loadJSON = (filepath) => {
        // there is actual code in the real class
    }
    loadHTML = (filePath) => {
        // there is actual code in the real class
    }
    loadExternalData = () =>  {
        let filePath = `${this.dataDirectory}${this.currentDoc.filepath}`;
        let dataIsJson = this.currentDoc.filepath.indexOf('.json') != -1;
        if (dataIsJson) {
            this.loadJSON(filePath);
        } else {
            this.loadHTML(filePath);
        }

    }
    
}

Is there an easier way to refer to methods and properties without using this

Not particularly, though I suppose if the functions are bound to this properly, you could also extract them into standalone variables first, maybe in the first line of the function. IMO it's not an improvement, but YMMV. Eg

    loadExternalData() {
        let filePath = `${this.dataDirectory}${this.currentDoc.filepath}`;
        let dataIsJson = this.currentDoc.filepath.indexOf('.json') != -1;

could change to

    loadExternalData() {
        const { dataDirectory, currentDoc } = this;
        let filePath = `${dataDirectory}${currentDoc.filepath}`;
        let dataIsJson = currentDoc.filepath.indexOf('.json') != -1;

Could also probably change the last line to

const dataIsJson = currentDoc.filePath.endsWith('.json');

to be precise.

  • Related