There is a class, the necessary part of which looks like this:

class ApiController { constructor() { this.all_languages = 'boards'; this.all_boards = 'languages'; } langs(req, res, next) { console.log(this); res.end(this.all_languages); } }; var api_controller = new ApiController(); module.exports = api_controller; 

Next, an instance of this class is imported into another file, where it is called in a router like this:

 var api = require('../controllers/api'); router.get('/langs', api.langs); 

However, the request [TypeError: Cannot read property 'all_languages' of undefined] error, and in this in the console it is displayed as undefined . If you call this method on the instance in the same class where it was created, then everything works fine. What can be wrong?

    1 answer 1

    The essence of the problem is that you call the langs method in isolation from the context .

    What really happens?

    Even though you define langs as a method (in the terminology of the Object Oriented Approach), it can be invoked both in the context of an object and by itself.

    For example:

     class Person { constructor(name) { this.name = name; } sayHi() { console.log('Hi from ' + this.name + '!'); } } // Вызов в контексте объекта var john = new Person('John'); john.sayHi(); // Выведет 'Hi from John!'; // Вызов в контексте другого объекта var f = john.sayHi; f.call({name: 'James'}); // Выведет 'Hi from James!' // Вызов без контекста f(); // [TypeError: Cannot read property 'name' of undefined] 

    The examples above show that even despite the fact that you define a function as a class method, it still remains a function .

    What to do?

    In JavaScript, starting with ES 5.1, there is a native way to bind a function to an object. This is done using the Function.prototype.bind method:

     // Объект john взят из примера выше var f = john.sayHi.bind(john); f(); // Выведет 'Hi from John!'; 

    For older JavaScript implementations, you can easily do the bind function yourself (an example implementation can be found, for example, in Underscore.js ).

    UPD:

    As rightly noted in the comments, when used to define classes of ES6 syntax, all methods are executed in strict mode . Therefore, instead of referring to a global object (as it happens outside of strict mode), the this variable is undefined .

    • You can also add that inside the functions (class methods) the machine puts "use strict"; so this is undefined , not a global object - Grundy
    • @Grundy added the mention of strict mode. However, I do not think that it will be useful for beginners who do not know how to work with classes without ES6 syntax. For those who are in the subject line, the whole answer could be reduced to one sentence: " bind + strict default mode " =) - Dmitriy Simushev