I am making an app using Node.js, Express.js and MongoDB. I am using a MVC pattern and also have separate file for routes. I am trying me make a Controller class, in which a method calls another method declared within it. But I cannot seem to be able to do this. I get "Cannot read property '' of undefined".
index.js file
let express = require('express');
let app = express();
let productController = require('../controllers/ProductController');
app.post('/product', productController.create);
http.createServer(app).listen('3000');
ProductController.js file
class ProductController {
  constructor(){}
  create(){
   console.log('Checking if the following logs:');
   this.callme();
  }
 callme(){
  console.log('yes');
 }
}
module.exports = new ProductController();
When I run this I get following error message:
Cannot read property 'callme' of undefined
I have ran this code by itself with little modification as following and it works.
class ProductController {
  constructor(){}
  create(){
    console.log('Checking if the following logs:');
    this.callme();
  }
  callme(){
    console.log('yes');
  }
}
let product = new ProductController();
product.create();
Why does one work and not the other? HELP!
To make a public method private, you prefix its name with a hash # . JavaScript allows you to define private methods for instance methods, static methods, and getter/setters. The following shows the syntax of defining a private instance method: class MyClass { #privateMethod() { //... } }
Class methods are created with the same syntax as object methods. Use the keyword class to create a class. Always add a constructor() method. Then add any number of methods.
There are two types of Class in ES6: parent class/super class: The class extended to create new class are know as a parent class or super class. child/sub classes: The class are newly created are known as child or sub class. Sub class inherit all the properties from parent class except constructor.
The call() method is a predefined JavaScript method. It can be used to invoke (call) a method with an owner object as an argument (parameter). With call() , an object can use a method belonging to another object.
When you pass create method as method it is probably called in different context (this) as you expect. You can bind it:
app.post('/product', productController.create.bind(productController));
There are many other ways how to ensure this refers to correct object. 
E.g. wrap it with function (either arrow or classical):
app.post('/product', (...args) => productController.create(...args));
Or bind methods in constructor:
constructor() {
    this.create = this.create.bind(this);
}
                        Your method is being rebound to the Layer class within express, losing its original context. The way that express handles routes is by wrapping each one in a Layer class, which assigns the route callback to itself:
this.handle = fn;
That is where your problems arise, this assignment automatically rebinds the function context to Layer. Here is a simple example demonstrating the problem:
function Example() { 
   this.message = "I have my own scope"; 
} 
Example.prototype.logThis = function() { 
   console.log(this); 
}
function ReassignedScope(logThisFn) { 
   this.message = "This is my scope now";
   // simulation of what is happening within Express's Layer
   this.logThis = logThisFn; 
}
let example = new Example()
let scopeProblem = new ReassignedScope(example.logThis);
scopeProblem.logThis(); // This is my scope now
Others have already pointed out the solution, which is to explicitly bind your method to the ProductController instance:
app.post('/product', productController.create.bind(productController));
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With