0

I have a typescript class containing all my express page functions, but get an 'undefined' error, when I try to access its class' member variable using this:

class CPages {
    private Version: string;

    constructor(version: string) {
        this.Version = version;
        console.log(this.Version); // <- now 'this' refers to the class CPages. Output: 1.0
    }

    public async sendPage(req: express.Request, res: express.Response) {
        console.log(this.Version); // <- now 'this' is undefined and so is this.Version. Output: Cannot read property 'Version' of undefined
        res.render('page', {
            version: this.Version
        });
    }
}

/* ... */

const Pages = new CPages("1.0");

App.get('/', Pages.sendPage);

I had a look at the behaviour of arrow functions (here), seem to be similar. But unlike the examples there I can neither access the main programm nor the class by using this. So, how can I access the version variable without sending it as a parameter?

ps: The code is a bit simplified and the App.get(...); is in a class itself.

Alex
  • 27
  • 2
  • 8
  • 1
    Your method is losing its context when you do the `.get()` binding. You can use `App.get('/', Pages.sendPage.bind(Pages))` to fix that. – Pointy Jul 21 '21 at 19:25

2 Answers2

3

class CPages {
    constructor(version) {
        this.Version = version;
        // console.log(this.Version);
    }
    async sendPage(){
        console.log('sendPage', this.Version); 
    }
}


let p = new CPages('1.0');
// p.sendPage(); // good

function middle(req, res, next){
  console.log('middleware')
  next()
}

middle(undefined, undefined, p.sendPage) // bad
middle(undefined, undefined, p.sendPage.bind(p)) // good

This works fine, just for reference, but you're passing your class function to express as middleware, for which at some point later...

   function(req, res, next){
      // next is your function
      next() // "this" is now this function
   }

as others have suggested, you can use .bind(Pages) to bind the correct this

Cody G
  • 8,368
  • 2
  • 35
  • 50
2

When you do this App.get('/', Pages.sendPage);, it means that you are sending in a function to be used on the / route. At this point it is no more bound to your Pages object. It runs in the global context like this :

let obj = {
'val' : 1,
'func1' : function(){
console.log(this.val);
}
}
obj.func1(); //Works fine
let newRef = obj1.func;
newRef(); //Error

You can use bind() to return a modified function with the this value bounded to the Pages object.

App.get('/',Pages.sendPage.bind(Pages));
Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39