Variable as a read-only property in object

I have a function constructor and I’m trying to declare some variables as read-only properties, here’s how it looks:

function Stopwatch() {
  let duration = 0;

  let props = {
    startTime: "",
    endTime: "",
    running: ""
  };

  Object.defineProperty(this, "props", {
    get: function() {
      return props;
    }
  });

  Object.defineProperty(this, "duration", {
    get: function() {
      return duration;
    }
  });
}

I am also trying to use prototype to inherit some methods of this object, this is one of the methods:

Stopwatch.prototype.start = function() {
  let { running, startTime } = this.props;
  if (running) throw new Error("Stopwatch has already started.");

  running = true;

  startTime = new Date();
};

If I define a new object const sw = new Stopwatch() and then call sw.start() twice I should get an error in the console, but nothing is happening. It’s like if I’m not reassigning values to the keys of the props object, so it’s like if running is always false…

If instead of the props object I had variables, like this

let startTime, endTime, running;

How can I make these variables public to my methods through prototype inheritance so I could reassign values to them? I know I could use the same process I used with the duration variable, but I don’t want to repeat that for every variable, there must be a better way.

function Stopwatch() {
  this.startTime;
  this.endTime;
  this.running;
  let duration = 0;

  Object.defineProperty(this, "duration", {
    get: function() {
      return duration;
    }
  });
}

Stopwatch.prototype.start = function() {
  let { running, startTime } = this;
  if (running) throw new Error("Stopwatch has already started.");

  running = true;

  startTime = new Date();
};

The above solution is not working either after I define const sw = new Stopwatch() and call twice the sw.start() method. I should get the error in the console after I call the start method the second time, but it’s not doing anything, as if running is still false.

In my second example? But why? I used destructoring, why wouldn’t it work in this scenario? @camperextraordinaire

Your solution works, but I am still confused as why I have to use thethis key word with the running variable when I try to reassign a value to it.

I mean, I want running to have a falsy value at first, so when I call start method the first time the function skips the if statement block of code and execute the other block of code. Here’s my logic:

Stopwatch.prototype.start = function() {
// Use destructuring to get running and startTime
  let { running, startTime } = this;
// The first time I call this method, skip this block of code because running originally has a falsy value
  if (running) throw new Error("Stopwatch has already started.");
// Reassign running to true, so the next time the method is called it throws the error above
  running = true;

  startTime = new Date();
};

If I assign running to 0, would it change anything? 0 is still considered a falsy value if I’m not mistaken.

So… If I do this running = true, I’m creating a global variable, but if I do this instead this.running = true, am I reassigning a value to the running variable that I declared in the parent function StopWatch? The latter is exactly what I tried to do from the beginning.

Yes, my mistake, it is a property, that’s exactly the reason why I used object destructuring to get the properties that I want to work with in each method. In the case of start method, I just need running and startTime. This way, I don’t need to use the this key word every time I use those properties in the given method.

But somehow, I still need to use the this key word when I try to assign a value to the running property, even though I already used destructuring to work with this property?

Umm I think I got things mixed up with React then, people usually use destructing to get the props of a component.

So basically, if I assign a value to a property in the parent object (Stopwatch) I can use destructuring in whatever method to get the value of that property and use it multiple times in said method without the need of using the this keyword. BUT, if I want to reassign a value to a property of the parent object (Stopwatch) in a given method, I need to use the this keyword to change the value of that property in the parent object?

Yes, I do get your point. Thank you very much, now things are starting to make more sense.