3

I am using Javascript ES6 classes. I have created a Player class as below:

class Player {

  constructor() {
     .....
     .....
  }
  changeShipDirection(shipName, direction) {
    let redraw = false;
    this.ships.filter(function(ship) {
        if (ship.name === shipName) {
            ship.direction = direction;
            if (ship.location.length > 0) {
                redraw = true;
                let coordinates = this.getCoordinatesOfShip(ship.name);
            }
        }
     });

     return redraw
   }

   getCoordinatesOfShip(shipName) {
      let coordinates = [];
      this.ships.filter(function(ship) {
          if (ship.name === shipName) {
              coordinates = ship.location;
          }
      });

      return coordinates;
   }

}

I get the following error:

Cannot read property 'getCoordinatesOfShip' of undefined

I have cases where I use the same technique i.e. calling a method within the class and it works.

matisetorm
  • 857
  • 8
  • 21
ka222jm
  • 71
  • 1
  • 3
  • 5
  • You should use `some` and `find` instead of `filter`. Also, what do you need those `coordinates` variable for if you don't use it at all? – Bergi May 20 '17 at 19:44

1 Answers1

7

That's because this inside that function you passed to filter is not bound to the class. There are multiple ways to fix it.

One is to use arrow function which retains the this binding of the scope it's defined in

this.ships.filter((ship) => {
        if (ship.name === shipName) {
            ship.direction = direction;
            if (ship.location.length > 0) {
                redraw = true;
                let coordinates = this.getCoordinatesOfShip(ship.name);
            }
        }
     });

Another can be to first retain the this reference for the outer function in some other variable and then use that inside the function passed to filter -

var self = this
this.ships.filter(function(ship) {
        if (ship.name === shipName) {
            ship.direction = direction;
            if (ship.location.length > 0) {
                redraw = true;
                let coordinates = self.getCoordinatesOfShip(ship.name);
            }
        }
     });

Yet another way is to bind that function to the this bound to the outer function -

this.ships.filter(function(ship) {
        if (ship.name === shipName) {
            ship.direction = direction;
            if (ship.location.length > 0) {
                redraw = true;
                let coordinates = this.getCoordinatesOfShip(ship.name);
            }
        }
     }.bind(this));
Mukesh Soni
  • 6,646
  • 3
  • 30
  • 37