10

I have a problem programming object-oriented in Javascript. I have the following:

class Foo{
    constructor(){...}
    ...
    a_needed_method(){...}
    ...
    a_method(){
        ...
        jsObject.on("click",function(params){
            this.a_needed_method();
        });
    }  
}

The problem is, if I call the a_needed_method method using this there, then this is referencing the anonymous function that controls the onclick event. How I can call a_needed_method() from this anonymous function?

Carlos
  • 889
  • 3
  • 12
  • 34
  • That depends. Is the event handler using jQuery? How is `a_method` called *(`this` depends on execution context)* ? – adeneo May 07 '17 at 15:35

4 Answers4

19

ES6

You can use an arrow function to preserve the lexical this:

jsObject.on("click", params => {
  this.a_needed_method();
});

ES5

You can use the good old that = this:

var that = this;
jsObject.on("click", function (params) {
  that.a_needed_method();
});
Badacadabra
  • 8,043
  • 7
  • 28
  • 49
  • Thanks for your response, I've used the updated version: __arrow function__, and works fine. I don't know this exists, because I'm just a beginner, so... Could you explain me what is an __arrow function__ and when I should use it? Thank you so much again! – Carlos May 07 '17 at 21:25
  • You're welcome! :) If you want to learn more about **arrow functions**, I recommend you to read my in-depth answer here: http://stackoverflow.com/questions/43588722/arrow-functions-vs-fat-arrow-functions/43593587#43593587 – Badacadabra May 07 '17 at 22:13
1

you can use bind:

    jsObject.on("click",function(params){
        this.a_needed_method();
    }.bind(this));

let jsObject = $(this);

class Foo {
  constructor() {

  }

  a_needed_method() {
    console.log('That works !');
  }

  a_method() {
    jsObject.on("click", function(params) {
      this.a_needed_method();
    }.bind(this));
  }
}

let x = new Foo();
x.a_method();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Click anywhere

or arrow function from es6:

    jsObject.on("click",(params) => {
        this.a_needed_method();
    });

let jsObject = $(this);

class Foo {
  constructor() {

  }

  a_needed_method() {
    console.log('That works !');
  }

  a_method() {
    jsObject.on("click", (params) => {
      this.a_needed_method();
    });
  }
}

let x = new Foo();
x.a_method();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Click anywhere
Pengyy
  • 37,383
  • 15
  • 83
  • 73
  • You need to bind `this` to the function passed as a parameter to `on` not to the `on` function's return value. – Titus May 07 '17 at 15:38
  • @Titus thanks for remind me about that, I have updated with a twice bind. :) – Pengyy May 07 '17 at 16:11
  • Why do you think the last bind is needed at all? In fact, the last one is the deprecated jQuery `.bind()` method, not the `Function.prototype.bind`, and passing `this` to it wouldn't do anything useful. –  May 07 '17 at 16:56
1

In your constructor you can say:

constructor(){
  this.a_needed_method = this.a_needed_method.bind(this);
}
Sventies
  • 2,314
  • 1
  • 28
  • 44
  • 1
    I don't think this solves the issue because inside the anonymous function, `this.a_needed_method` will still be `undefined`. – Titus May 07 '17 at 15:42
0

Assuming this is the class inside a_method, and that it's called with that execution context, and assuming the event handler is using jQuery, you could simply use event.data to pass anything you'd like to the event handlers callback, that's what event.data was meant to do

a_method(){
    ...
    jsObject.on("click", {klass : this}, function(params){
        params.data.klass.a_needed_method();
    });
}  

let jsObject = $(this);

class Foo{
    constructor(){
    
    }

    a_needed_method(){
      console.log('That works !');
    }

    a_method(){
        jsObject.on("click", {klass : this}, function(params){
            params.data.klass.a_needed_method();
        });
    }  
}

let x = new Foo();
x.a_method();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Click anywhere
adeneo
  • 312,895
  • 29
  • 395
  • 388