Why is "this" undefined in this class method? Why is "this" undefined in this class method? node.js node.js

Why is "this" undefined in this class method?


When you do this:

router.get('/users', userController.list);

what gets passed to your router is just a reference to the .list method. The userController instance gets lost. This is not unique to routers - this is a generic property of how things are passed in Javascript. To understand further, what you are essentially doing is this:

let list = userController.list; // at this point the list variable has no connection at all to userControllerrouter.get('/users', list);

And, in Javascript's strict mode, when you call a regular function without any object reference such as calling list() above, then this will be undefined inside the function. That is what is happening in your example. To fix it, you need to make sure that your method is called with a proper object reference as in userController.list(...) so that the interpreter sets the this value appropriately.

There are multiple ways to solve this problem:

Make your own function wrapper

router.get('/users', function(req, res)  {    userController.list(req, res);});

This works in any version of Javascript.


Using .bind() to make a wrapper for you that calls it with the right object

router.get('/users', userController.list.bind(userController));

This works in ES5+ or with a .bind() polyfill.


Use an ES6 arrow function shortcut

router.get('/users', (...args) => userController.list(...args));

This works in ES6+


Personally, I prefer the .bind() implementation because I think it's just simpler and more declarative/clearer than any of the others and the ES6 "shortcut" isn't really shorter.


router.get() won't call your class the way you think it will. You are giving it a reference to a function which it will call in the context of the router.get meaning, it won't be in the context of your userController.

You can fix this by doing:

router.get('/users', function(){userController.list(...arguments)});

In other words, don't have express use userController's reference to list, have express use a closure that will have userController call list with the given arguments.