1

I'm trying to create a clock Class with infinite loop upon start function , by using explicitly declared variable for temp, it works normal.

class Clock{
    constructor({template}){ //template  = "h:m:s"
        this.template = template;
        this.timer;
    }

    render() {
        var temp = 'h:m:s';
        let date = new Date();
    
        let hours = date.getHours();
        if (hours < 10) hours = '0' + hours;
    
        let mins = date.getMinutes();
        if (mins < 10) mins = '0' + mins;
    
        let secs = date.getSeconds();
        if (secs < 10) secs = '0' + secs;
    
        let output = temp
        .replace('h', hours)
        .replace('m', mins)
        .replace('s', secs);
    
        console.log(output);
      }

    stop(){
        clearInterval(this.timer);
    }

    start(){
        this.render();
        this.timer = setInterval(this.render,1000);
    }
}

var clock = new Clock({template :'h:m:s'});
clock.start();  

Output:

13:53:54
13:53:55
13:53:56
13:53:57
13:53:58
13:53:59
...

Well as you can see, i have declared a constructor named template for future purpose in case the users want to use another form of time template , but when i'm trying to use the this.template variable on temp, it shows error like this

class Clock{
    constructor({template}){ //template  = "h:m:s"
        this.template = template;
        this.timer;
    }

    render() {
        var temp = this.template;
        let date = new Date();
    
        let hours = date.getHours();
        if (hours < 10) hours = '0' + hours;
    
        let mins = date.getMinutes();
        if (mins < 10) mins = '0' + mins;
    
        let secs = date.getSeconds();
        if (secs < 10) secs = '0' + secs;
    
        let output = temp
        .replace('h', hours)
        .replace('m', mins)
        .replace('s', secs);
    
        console.log(output);
      }

    stop(){
        clearInterval(this.timer);
    }

    start(){
        this.render();
        this.timer = setInterval(this.render,1000);
    }
}

var clock = new Clock({template :'h:m:s'});
clock.start();  

Output:

13:56:17
c:\Users\Asus\Desktop\IM-Sanbercode-Reactjs-Batch-27\Tugas-Harian-Part-1\Tugas-7\tugas7.js:94   
        .replace('h', hours)    
         ^

TypeError: Cannot read property 
'replace' of undefined
    at Timeout.render [as _onTimeout] (c:\Users\Asus\Desktop\IM-Sanbercode-Reactjs-Batch-27\Tugas-Harian-Part-1\Tugas-7\tugas7.js:94:10)
    at listOnTimeout (internal/timers.js:557:17)
    at processTimers (internal/timers.js:500:7)

Any idea how might it happened?

zippyboy
  • 57
  • 4
  • 2
    `this.timer = setInterval(this.render,1000);` *looses* `this` inside `this.render`. Try `this.timer = setInterval(this.render.bind(this),1000);` – Yoshi Aug 24 '21 at 07:00
  • 1
    @Yoshi my personal preference is `setInterval(() => this.render(), 1000)` because it avoids the code looking like a `this` sandwich with method in the middle. – VLAZ Aug 24 '21 at 07:03
  • @Vlaz You're right, I would probably also use this. And thank you for finding the duplicate! My hope with [`.bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind) was that it might be a good starting point to follow when reading about the underlying *problem*. – Yoshi Aug 24 '21 at 07:05

1 Answers1

0

Use this.timer = setInterval(() => this.render(), 1000);

When you use this.timer = setInterval(this.render, 1000); the scope of this will be Window object, to define the scope to your object level, use arrow function as this.timer = setInterval(() => this.render(), 1000);

class Clock {
  constructor({ template }) { //template  = "h:m:s"
    this.template = template;
    this.timer;
  }

  render() {
    var temp = this.template;
    let date = new Date();

    let hours = date.getHours();
    if (hours < 10) hours = '0' + hours;

    let mins = date.getMinutes();
    if (mins < 10) mins = '0' + mins;

    let secs = date.getSeconds();
    if (secs < 10) secs = '0' + secs;

    let output = temp
      .replace('h', hours)
      .replace('m', mins)
      .replace('s', secs);

    console.log(output);
  }

  stop() {
    clearInterval(this.timer);
  }

  start() {
    this.render();
    this.timer = setInterval(() => this.render(), 1000);
  }
}

var clock = new Clock({ template: 'h:m:s' });
clock.start();
Nitheesh
  • 19,238
  • 3
  • 22
  • 49