2

I have a calculator class. and this has following methods, getInputFields and sum.

const addBtn: HTMLButtonElement = document.getElementById("add") as HTMLButtonElement;;
const subBtn: HTMLButtonElement = document.getElementById("subtract") as HTMLButtonElement;
const multiplyBtn: HTMLButtonElement = document.getElementById("multiply") as HTMLButtonElement;
const divideBtn: HTMLButtonElement = document.getElementById("divide") as HTMLButtonElement;

class Calculator {

    result: HTMLSpanElement;
    inputOne: HTMLInputElement;
    inputTwo: HTMLInputElement;
    numOne:number;
    numTwo:number;

    constructor() {
        this.result = document.getElementById("result") as HTMLSpanElement;
        this.inputOne = document.getElementById("num1") as HTMLInputElement;
        this.inputTwo = document.getElementById("num2") as HTMLInputElement;
    }

    getInputFields() {
        this.inputOne = document.getElementById("num1") as HTMLInputElement;
        this.inputTwo = document.getElementById("num2") as HTMLInputElement;
        this.numOne = parseInt(this.inputOne.value);
        this.numTwo = parseInt(this.inputTwo.value);
    }

    sum() {
        this.getInputFields();
        if (!isNaN(this.numOne) && !isNaN(this.numTwo)) {
            this.result.textContent = (this.numOne + this.numTwo).toString();
        }
    }

Below the above code, I use addEventListener to run sum method.

const calculator = new Calculator();
addBtn.addEventListener('click', calculator.sum);

You can see this.getInputFields is inside sum() method. Why do I have that inside sum method? Because I want to make subtract, multiplication, division methods. But I don't want to repeat the same codes to assign document.getElmentById("num1") as HTMLInputElement in every method.

That's why I put that code into getInputFields. But this doesn't work inside class methods..

Here's error I got,

main.js:20 Uncaught TypeError: this.getInputFields is not a function
    at HTMLButtonElement.Calculator.sum (main.js:20)
  • 3
    The value of “this” changes inside the event listener callback. Bind the class methods to “this” in the constructor – evolutionxbox Jan 31 '21 at 13:58
  • 3
    [How does the “this” keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – Thomas Jan 31 '21 at 14:05

1 Answers1

0

The problem in your code is in the usage of the this keyword. In other languages, like C#, passing a class method around will keep it "linked" to it's originating component. Not in JavaScript (and, by extension, TypeScript).

In JavaScript the this keyword is bound at execution time. So, if you call calculator.sum() this in sum will be bound to calculator, but if you do:

const func = calculator.sum;
func(); // <- inside this call, this is the global object (window)

Basically, when there is no object. in front of a call, this is implicitly bound to the global object (window, in case of browsers).

In your case, you could simply replace the line:

addBtn.addEventListener('click', calculator.sum);

with:

addBtn.addEventListener('click', (_clickEvent) => calculator.sum());
// or
addBtn.addEventListener('click', calculator.sum.bind(calculator));

Refer to the excellent answers linked by @Thomas in How does the "this" keyword work? for many more examples regarding your question.

A. Chiesa
  • 5,367
  • 1
  • 21
  • 43