route class not able to access local function #typescript #express

Issue

In the code below I get ‘undefined’ error for ‘loglogMePleasePlease’ function.

Could someone please help me out with this.

TypeError: Cannot read property ‘logMePleasePlease’ of undefined

I am at flabbergasted, this kinda error makes me question everything I have coded so far.

import {Router, Request, Response, NextFunction} from 'express';
import * as fs from 'fs';
import { db } from '../db/lowDb'

export class employeeRoute {
    router: Router
    constructor() {
        this.router = Router();
        this.init();
    }
    init() {
        this.router.get('/', this.default);
        this.logMePleasePlease('SFDSFSDF');/*This call works fine!*/
    }
    public logMePleasePlease(err){
        console.log(err);
    }
    public default(req: Request, res: Response, next: NextFunction) {
        /*****Error when execution gets to follwing line:
        TypeError: Cannot read property 'logMePleasePlease' of undefined
        ******/
        this.logMePleasePlease('asdad');
        res.send({
            status:'ok',
            message:'employee api home'
        });
    }
}
const employee = new employeeRoute();
export default employee.router;

Solution

This is caused by the way JavaScript binds this when calling a function.

Let’s take a couple of examples and show what I mean as well as how to go about fixing it.

class BindingTest {
  func() {
    console.log(this)
  }
}

const test = BindingTest()
const testFunc = test.func

Now, as you can see in this example, we have the test object which presents the func method, as well as the testFunc variable which holds a reference to that method.

It is important to keep in mind the way that JavaScript moves values around (and adds functions to classes), specifically that everything is a value. In this case, when we assign const testFunc = test.func, what we’re doing is taking the BindingTest.prototype.func value (the function we defined on the class) and referencing it directly.

As a consequence, when we run the following:

testFunc()

We will see that it prints out undefined rather than the BindingTest context…

That’s rather odd, because when we run the following:

test.func()

We get the context printed!

So as I alluded to, this is the result of calling the function via the object’s prototype invocation strategy (in which case this is bound to test) and calling the function as an isolated value (in which case this is undefined).

The fix is actually very simple, JavaScript provides the .bind() method which allows you to associate a this context with a function value.

const boundTestFunc = test.func.bind(test)

Now, if we go and call boundTestFunc, we’ll get our BindingTest context printed out as we would expect.

I hope this clarifies the “why” behind what you’re seeing. In your case: the fix will be to simply use the following code in your constructor.

this.router.get('/', this.default.bind(this));

Answered By – Benjamin Pannell

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published