1

I have a code for this function. I started learn js classes, and I want to remake this function into class. but I don't understand how to set start and remaining value into constructor correctly. also i don't understand how pass callback function into class

function Timer(callback, delay) {
    /* privates properties */
    let timerId, start, remaining = delay;

    /* Public methods */
    this.resume = () => {
        start = new Date();
        timerId = setTimeout( () => {
            remaining = delay;
            this.resume();
            callback();
        }, remaining);
    };

    this.pause = () => {
        clearTimeout(timerId);
        remaining -= new Date() - start;
    };

    this.become = () => {
        clearTimeout(timerId);
        remaining = delay;

        this.resume();
    };

    /* Constructor */
    this.resume();
}

I want to get a class identical to this function

Andrey
  • 49
  • 8
  • Possible duplicate of [How to set javascript private variables in constructor?](https://stackoverflow.com/questions/6799103/how-to-set-javascript-private-variables-in-constructor) – Ryan Wilson Oct 19 '19 at 17:13

1 Answers1

0

You can do something like this.. Keep in mind, a class in JavaScript is syntactical sugar for a function - under the hood a class is just a function (prototype, really)..


Edit: @georg is right - I shouldn't have used experimental features.. I have updated my answer on how to use class methods and binding them to the class (aka old school way)..

This article explains why you should bind methods to classes.. I have also included an example below (that is commented out) that shows why not binding methods can get you into some trouble.


Edit #2: This answer is incredibly succinct and beautifully explains why binding is important.

class Timer {
  constructor(callback, delay) {
    this.callback = callback;
    this.timerId;
    this.start;
    this.remaining = delay;
    
    // bind methods to this class
    this.resume = this.resume.bind(this);
    this.pause = this.pause.bind(this);
    this.become = this.become.bind(this);
    this.begin = this.begin.bind(this);
  }

  resume() {
    this.start = new Date();
    this.timerId = setTimeout(() => {
      this.resume();
      this.callback();
    }, this.remaining);
  };

  pause() {
    clearTimeout(this.timerId);
    this.remaining -= new Date() - this.start;
  };

  become() {
    clearTimeout(this.timerId);
    this.remaining = this.delay;

    this.resume();
  };

  begin() {
    this.resume();
  }
}


function timerCallback() {
  console.log("Hello from callback!");
}

let timerDelay = 2000; // 2 seconds

let myTimer = new Timer(timerCallback, timerDelay);
myTimer.begin();

/**
 *
 * This is an example of why you should bind methods to classes.
 * If you removed the bindings from the class, this would not work:
 *
 * let myTimer = new Timer(timerCallback, timerDelay);
 * const { begin } = myTimer;
 * begin();
 * 
 */

// This just prevents the timer from running forever.
setTimeout(() => {
  myTimer.pause()
}, 10000);
Matt Oestreich
  • 8,219
  • 3
  • 16
  • 41
  • Class fields is a new feature and is not official yet. Normal methods would be better for compatibility, – georg Oct 19 '19 at 17:51
  • 1
    @MattOestreich, thank you very much! I didn't know that we can set properties in the constructor without a value. your answer really helped me understand some points in building JS-classes! – Andrey Oct 19 '19 at 18:24