-2

Imagine I have a class with two methods / functions. One method utilizes another class's function - in this case JQuery's ajax-call. Inside this function I want to address a method of my own class.

class priceSearch {


  this foobar = "null";

  loadStuff() {

    $.ajax({url: requestUrl})
      .done(function(response){

        this.processStuff(response);
        console.log(foobar); // -> undefined
      });

  }

  processStuff(stuff) {

    console.log(stuff);

  }

}

But this will lead to

processStuff is not defined

Apparently, because processStuff is not part of ajax.done and "this" references the ajax.done.

So, how do I address parent's class method?

Same for properties: foobar from within the Ajax call will return "undefined".

n.r.
  • 726
  • 1
  • 4
  • 19
  • Try using an arrow function `.done((response) => {/* Body */})`, if I am not mistaken it will bind it to your class instead of the `jQuery` object. – Get Off My Lawn Aug 16 '19 at 20:10
  • 5
    Possible duplicate of [How does the "this" keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – Chris Aug 16 '19 at 20:14

2 Answers2

1

You are passing an anonymous function to ajax.done, this is not shared between a class and an anonymous function. You can either:

  1. Declare a function handleResponse inside your class and pass that by calling ajax.done(this.handleResponse)
  2. Use Function.apply to change the this value inside the anonymous function
  3. Use Arrow Functions, they share the scope and this instance instead of defining their own, something like:
ajax.done(response => {
    // whatever you wanna do
});
Shitiz Garg
  • 605
  • 3
  • 7
  • The fact the function is anonymous is an irrelevance, try giving it a name and you'll see the exact same problem. The problem is that it's passed as a callback to `done`, which therefore controls how the function is called and therefore what its `this` is. (In particular, it won't be called in the context of the `priceSearch` "class") – Robin Zigmond Aug 16 '19 at 20:28
  • thanks. #3 - Arraow functions does the trick. Seems also the cleanest way to me. – n.r. Aug 16 '19 at 20:29
  • @RobinZigmond functions by default have their own ```this```, giving it a name doesn't make a difference. I simply meant to state that ```this``` is not shared between class and a function which is not declared as it's method (or declared as a arrow function). However, passing it to ```ajax.done``` is not what causes it's ```this``` to change. You can declare a function and call it within the class' method and it'll still have a different ```this```. OTOH, you can declare a class method ```handleResponse``` and pass it like ajax.done(this.handleResponse), and it'll have the correct ```this``` – Shitiz Garg Aug 16 '19 at 20:34
  • No function has "its own `this`* though. The value of `this` depends entirely on how the function is called - the same function can appear to have several different values for `this` if it is called in different ways. – Robin Zigmond Aug 16 '19 at 21:24
0

the moment the code enters the anonymous function:

.done(function(response){
   *this* is no longer referring to the class but "this" function
});

ES6 Solution would be to avoid using anonymous functions for your done and use array functions instead.

.done( (response) => {
    this.processStuff(response); *this* still refers to class
});

To give you another perspective, in the olden days we would declare a local variable (local to your method) that holds that other method.

loadStuff() {
    var psHolder = this.processStuff;
    $.ajax({url: requestUrl})
      .done(function(response){
         psHolder(response);  *this should also work*
      });

}
  • thanks, I thought about this, too. But it seems not clean to me, because there are a couple of properties and methods I had to address like this. – n.r. Aug 16 '19 at 20:30