-1

I am trying to create an object that each property is a class property.

This means I have a class named Ship which has 3 properties: type, length, orientation. I am trying to create an object named shipObj that all its properties are getting values from these class properties. Apart from the id property (which is the id of an event target).

Look at the code below.

class Ship{

  constructor(type, length){
    this.type = type
    this.length = length
    this.orientation = 'horizontal'
    const self = this
  }

  // Deploying ships by dragging them into the grid
  deployShip = () => {

    self.addEventListener('dragstart', function(e) {

      // Ship object for json
      let shipObj = {
        id: e.target.id,
        type: self.type,
        length: self.length,
        orientation: self.orientation
      }

      e.dataTransfer.setData( 'text/plain', JSON.stringify(shipObj) );
    });

  }

}

For example, when I create this Ship Object let carrier = new Ship("Carrier", 5),

I want shipObj to be like this {id: 'carrier-chris', type: 'Carrier', length: '5', orientation: 'horizontal'}.

How can I do that?

The result I currently get is {id: 'carrier-chris', type: 'undefined', length: '0', orientation: 'undefined'}. As you can see I am creating a constant named self at the constructor but for some reason its scope is limited only inside the constructor.

  • 2
    _“but for some reason its scope is limited only inside the constructor”_ — Yes, that’s what variable scope is limited to. See [What is the scope of variables in JavaScript?](/q/500431/4642212). – Sebastian Simon Oct 13 '22 at 01:41
  • it's like that. You can't use a `const` this way. you cannot replace the `this`, because it allows you to refer to the instance created. – Mister Jojo Oct 13 '22 at 01:46
  • 1
    `self.addEventListener()` makes no sense. `self` would be a `Ship` object, not a DOM element that you can add event listeners to. – Barmar Oct 13 '22 at 01:47
  • Don't use arrow functions as class methods. They don't receive `this` context. – Barmar Oct 13 '22 at 01:48
  • Thank you everybody for your answers! I thought a constant had scope inside the whole class. – Christophoros Anthoulakis Oct 13 '22 at 10:17

1 Answers1

0

You'll need to put the const self = this declaration inside the deployShip method, so that it is in scope where it is used:

class Ship {
  …

  // Deploying ships by dragging them into the grid
  deploy() {
    const self = this;
//  ^^^^^^^^^^^^^^^^^^
    window.addEventListener('dragstart', function(e) {
//  ^^^^^^ ???

      // Ship object for json
      let shipObj = {
        id: e.target.id,
        type: self.type,
        length: self.length,
        orientation: self.orientation
      }
      e.dataTransfer.setData( 'text/plain', JSON.stringify(shipObj) );
    });
  }
}

Alternatively, don't use self = this but just an arrow function:

class Ship {
  …

  // Deploying ships by dragging them into the grid
  deploy() {
    window.addEventListener('dragstart', (e) => {
//                                       ^^^^^^^^
      // Ship object for json
      let shipObj = {
        id: e.target.id,
        type: this.type,
//            ^^^^
        length: this.length,
//              ^^^^
        orientation: this.orientation
//                   ^^^^
      }
      e.dataTransfer.setData('text/plain', JSON.stringify(shipObj) );
    });
  }
}

Here, this inside the event handler will still refer to the same this value that the deploy() method was called, i.e. the Ship instance if you did call ship.deploy();.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thank you so much for your solution and explanation. I didn't know arrow function `this` was different than `this` of a regular function and had different scope. This really helps me a lot! Thanks once again! – Christophoros Anthoulakis Oct 13 '22 at 10:21
  • @ChristophorosAnthoulakis That's [what arrow functions are all about](https://stackoverflow.com/q/34361379/1048572) – Bergi Oct 13 '22 at 21:39