Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I call class function inside addEventListener [duplicate]

Why am I unable to return the element_id in the run function? The script works if I set it as let self = this; function(){ self.run() }

Doesn't work:

class clickin {
    constructor(element_id) {
      this.element = document.getElementById(element_id);
      this.element.addEventListener('click', this.run);
    }
    run() {
      alert('Element id: ' + element_id);
    }
}

Works:

   class clickin {
        constructor(element_id) {
          this.element = document.getElementById(element_id);
          let self = this;

          this.element.addEventListener('click', function(){
            self.run();
          });
        }
        run() {
          alert('Element id: ' + element_id);
        }
    }
like image 253
Matt Avatar asked Dec 14 '22 14:12

Matt


2 Answers

Using the addEventListener object, you are setting a callback function which will be called when the event is fired. So, it runs in a different context than your constructor function. In that case, the "caller(this)" object changes, and thus, this.run you mentioned above won't work. But, when you assign "clickin" class object to a variable "self", you are able to run because self is available in callback function as a closure, and when event handler executes, it is able to access that "clickin" object. You might want to look deeper into below topics for better understanding.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

like image 187
tech-y Avatar answered Dec 16 '22 03:12

tech-y


Alternatively, if you don't want to deal with class properties (as mentioned in the comments), just use an arrow function in the constructor instead:

class clickin {
  constructor(id) {
    this.element = document.getElementById(id);
    this.element.addEventListener('click', () => this.run(id));
  }
  run(id) {
    alert('Element id: ' + id);
  }
}

const c = new clickin('a');
<div id="a">aaa</div>
like image 37
Andy Avatar answered Dec 16 '22 03:12

Andy