Issue with Typescript: When inside a non-arrow class method, the keyword "this" is undefined

Many questions have addressed the topic of "this" in both JS and TS, but I have not been able to find a solution to my specific problem. It seems like I might be missing something fundamental, and it's difficult to search for an answer amidst the sea of inquiries related to arrow function scoping rules.

Just to provide some context, the code causing me trouble is running on a Node back-end.

So, I have a controller class with a method not defined as an arrow function (simplified for demonstration):

class UserController extends AbstractController {

    constructor() { ... }

    public async getUsers(x, y): Promise<any> {
        return this.processRequest( ... ); //processRequest is a protected async definition on AbstractController
    } 
}

// ...
export default new UserController()

The problem I'm encountering is that this inside getUsers() is undefined, whereas I would expect it to be the instance of UserController on which it is being executed.

If I were to convert getUsers to an arrow function...

class... {
    public getUsers = async (x, y): Promise<any> => {
        return this.processRequest( ... );
    }
}

...then it behaves as anticipated.

I comprehend how arrow function this captures work in terms of the surrounding scope, but in this scenario, I sense that there are two crucial concepts that are eluding me:

  • Why does the initial method lack any this? I believe this should refer to the instance of UserController, or at the very least, it should point to some broader object.
  • Why does the second method function at all? There doesn't seem to be a "surrounding scope" from which to capture this - or is there?

Here's how getUsers() is being invoked:

import UserController from 'user.controller';

userRouter.get('/', authMiddleWare, UserController.getUsers);

Answer №1

The behavior of the 'this' keyword in JavaScript can vary depending on how you call your method. In a regular function, the internal value of 'this' is dynamic and changes based on how the function is invoked. However, arrow functions operate differently. They do not have their own 'this' binding, and instead, they inherit the 'this' value from the closest non-arrow parent function. The 'this' value in an arrow function is set at the time of declaration and remains constant, unaffected by methods like call, apply, or bind.

For a comprehensive explanation on how to correctly access 'this' inside a callback function, check out this post: How to access the correct `this` inside a callback

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to highlight text within an iframe using the mouse and displaying the selected text in a separate div

I'm currently able to select text with the mouse and display that selection in a div. However, I'm struggling to do the same thing when dealing with an iframe displaying a page on the same domain. Despite trying various solutions found here, I h ...

jQuery fails to modify HTML according to its intended purpose

I've been struggling to update a price using JQuery. Even though the code seems fine when I check the console, the HTML doesn't reflect the changes. Additionally, when I try to log console.log(newPrc), it gives an error saying "newPrc" is not def ...

The quirk of Angular 2 routing when refreshing the page

Being completely new to Angular 2, I find myself facing a routing dilemma that I can't seem to wrap my head around. @Component({ selector: 'app', templateUrl: 'app/app.template.html', directives: [ROUTER_DIRECTIVES] }) ...

Utilizing AngularJS to dynamically inject HTML content into $scope

In my possession are the following files: index.html //includes instructions for passing arguments to the btnClick function in app.js <div ng-bind-html="currentDisplay"></div> app.js app.factory('oneFac', function ($http){ var htm ...

Using jquery to dynamically change audio source on click

Is there a way to dynamically change the audio src using jquery? <audio id="audio" controls="" > <source src="" type="audio/mpeg" /> </audio> <ul id="playlist"> <?php if($lists) { foreach ($lists as $list) { ?> ...

Angular Bootstrap uibModal is failing to resolve attributes

Issue with Roles in AngularJS Bootstrap uiModel var modalInstance = $uibModal.open({ animation: $scope.animationsEnabled, templateUrl: 'myModalContent.html', controller: 'ModalInstanceCtrl', size: 100, resolve: { roles: f ...

Error: The jasmine framework is unable to locate the window object

Currently, I am testing a method that includes locking the orientation of the screen as one of its functionalities. However, when using Jasmine, I encountered an error at the following line: (<any>window).screen.orientation.lock('portrait&apos ...

React - group several elements within a wrapping container

I am dealing with an array of words that make up sentences: let words = [ { "start_time": "2.54", "end_time": "3.28", "alternatives": [ { "confidence": "1.0", ...

I have successfully populated a text box with information pulled from a select option, however

When I try to select from my list, only one of the two fields is being picked up by the text field. Can anyone help me with this issue? Here is the code I am using: <script> function ProdValue(data) { document.getElementById("ProdName"). ...

Utilize MaterialUI's stepper component to jazz up your design with

Is there a way to customize the color of a material ui Stepper? By default, the material UI stepper's icons use the primary color for both "active" and "completed" steps. class HorizontalLinearStepper extends React.Component { state = { activeS ...

When the disk space is insufficient, the createWriteStream function will not trigger an error event if the file is not completely written

One challenge I'm encountering involves using createWriteStream: Imagine I have a large 100mb file that I want to write to another file on the disk. The available space on the disk is only 50mb. Here's my code snippet: const fs = require(&a ...

When a radio button is checked, add a class to its parent element that has a specific class assigned to it

In order to dynamically add a class to a specific div element higher up the DOM hierarchy when a radio button is clicked, I am in need of assistance. There are multiple instances of these div elements with different radio buttons, so it is crucial that on ...

Popup Triggered by a JavaScript Timer

Seeking assistance in creating a straightforward timer-based popup. Once the timer hits 10 seconds, the popup should become visible. The timer should pause or stop, and after clicking the 'ok' button on the popup, the timer should reset to 0. Can ...

I've received an array of objects, but I require the objects to be consolidated into a single array using a MongoDB query

Hello, I am a newcomer to mongodb and I am attempting to generate a specific output using the mongodb aggregate function. I am aiming for a unified array of objects rather than multiple arrays of objects. Can someone assist me in achieving this desired out ...

Animated dropdown feature spanning the entire width of the screen

I successfully developed a basic dropdown menu with full-width sub-menu functionality. Check it out on jsFiddle: $(document).ready(function(){ $(".drop").hide(); $(".link-1").mouseenter(function(){ $('.link-1-drop').slide ...

What is the best way to incorporate images from JSON responses into an HTML document?

I successfully managed to populate an HTML table with the json responses. However, I'm encountering an issue when it comes to displaying the images associated with the json variables. I'm only able to display the URL links for the images. Below ...

Leveraging ES6 Generators for Efficient XMLHttpRequests

My goal is to simplify AJAX calls using ES6 generators, but I've encountered some issues: let xhr = new XMLHttpRequest() function *statechange() { yield xhr.readyState; } let gen = statechange(); xhr.open("GET", myUrl, true); xhr.onreadystatec ...

What is the correct way to declare the mongoose _id in a TypeScript interface?

I have a question about utilizing Mongoose and TypeScript using the interface+class+schema approach. When it comes to storing the _id field, what is the best method? I understand that the database stores it as a bson ObjectID. However, I've come acr ...

Extracting data on an AngularJS platform by using web scraping techniques

I have been working on an AngularJS application that currently retrieves JSON data from an API using http.get, and it's been working really well. Recently, I've been exploring the idea of passing a URL to a static webpage and scraping the result ...

TypeScript recursive object mapping utility

I am currently developing a type-safe object mapper in TypeScript. So far, I have successfully implemented this at a single level of depth using this playground. enum TransformerActions { Delete = 'delete', } type TransformerMap<S> = ...