Home > Software engineering >  Why JavaScript getter method make changes before, during and after its execution?
Why JavaScript getter method make changes before, during and after its execution?

Time:02-26

I constructed object using ES6 class, creating make and speed property of any car as follows, and also I put a getter to convert speed into miles.

class CarCL {
  constructor(make, speed) {
    this.make = make;
    this.speed = speed;
  }

  // Converts current speed in mi/h
  get speedUS() {
    return (this.speed /= 1.6);
  }
}

const carFord = new CarCL('Ford', 120);
console.log(carFord);
console.log(carFord.speedUS);

I got weird result in console as following image.

enter image description here

Why speed is converted to 75 before getter method and further it keeps continued to be converted to 46.875 and also again it made changes to on it own in CarCL.prototype object to 29.296875 which is prototype of carFord?

CodePudding user response:

The problem is this line:

    return (this.speed /= 1.6);

/= is division assignment, so you're effectively saying "set this.speed to its current value divided by 1.6".

A mutating getter is extremely confusing, as you've noticed. Instead, say return (this.speed / 1.6); and it'll behave as you'd expect.

CodePudding user response:

In your speedUS() getter, you are using /= which assigns the result back to the left operand. If you don't want that (which you presumably do not), then change /= to just /.

Change this:

 return (this.speed /= 1.6);

to this:

 return (this.speed / 1.6);

Note also that the whole concept of a getter that mutates the property it is getting is generally bad (I assume you didn't mean for it to mutate). A getter should not mutate. It's a getter. Use a setter to mutate.

class CarCL {
  constructor(make, speed) {
    this.make = make;
    this.speed = speed;
  }

  // Converts current speed in mi/h
  get speedUS() {
    return (this.speed / 1.6);
  }
}

const carFord = new CarCL('Ford', 120);
console.log(carFord);
console.log(carFord.speedUS);


To add one further point of explanation, you are also seeing a weirdness in how console.log() works in some browsers. You would think that your code should first show the unmodified carFord object and, then and only then, would the carFord.speedUS getter modify the object. In fact, if you run your code in nodejs, that's what you see.

But, in some browsers, the evaluation and display of an object passed to console.log() is "lazy" meaning it doesn't happen immediately and thus the carFord.speedUS getter runs before the console outputs carFord even though that isn't the order of the statements. This is a weirdness in the console.log() implementation (seen regularly in Chrome) and is probably due to some performance optimizations to try to not slow down execution any more than necessary.

If you changed your code to this:

const carFord = new CarCL('Ford', 120);
console.log(JSON.stringify(carFord));
console.log(carFord.speedUS);

You could then see what you expect:

{ "make": "Ford", "speed": 120 }
75

Of course, all this is moot if you fix the speedUS() getter to not mutate the object.

  • Related