TToprak1
TToprak1

Reputation: 368

Prototype and Closure

I am trying to solve some JavaScript questions about prototype (and maybe closure). I am very new to this concept.

I need to create a MyNumber prototype, then add increment function which will return a number that is incremented by 1. Here I will create multiple instances of the prototype and every instance will keep track of its own value separately.

Here is my logically broken code:

function MyNumber(num) {
  this.num = num;
}

MyNumber.prototype.increment = function() {
   return function() {
     ++this.num
   }
}

After this example, I need to create a Clock prototype, which will increment by one every second.

Upvotes: 0

Views: 41

Answers (2)

Nick Parsons
Nick Parsons

Reputation: 50989

While you're using function constructors, I would suggest you use ES6's classes. It will allow you to write more readable and maintainable code. Your MyNumber function can be made into a class by creating your own constructor() and increment() methods. The increment() method is in charge of incrementing the number and returning the new number.

Since you need a clock, you could also make an additional Clock class. This extends the MyNumber class, which allows Clock to access the properties and methods declared in the MyNumber class. Since a clock needs to have an internal counter we can extend MyNumber which provides this counting functionality for us.

The Clock class has a constructor which calls the MyNumber's constructor by doing a super() call. This initializes what this.num will be in our Clock class. The constructor also accepts additional arguments such as an action, which is a function that gets executed every time the clock "ticks" and a speed for how fast the clock should "tick".

The Clock class also implements a begin() method, which uses setInterval() to repeatedly execute the passed through arrow function. The arrow function is executed every x m/s (based on the this.speed property). Every time the arrow function is executed, it increments the clocks internal counter (using the .increment() provided by the extended MyNumber class). It also executes the action function passed through the constructor initially.

You can then create an instance of your Clock class and pass through the required arguments to the constructor like so:

class MyNumber {
  constructor(num) {
    this.num = num;
  }
  
  increment() {
    return ++this.num;
  }
}

class Clock extends MyNumber {
  constructor(beginTime, action, speed=1) { // default speed to `1`
    super(beginTime);
    this.act = action;
    this.speed = speed; // in seconds
  }
  
  begin() {
    this.act(this.num); // call once before looping
    setInterval(() => { // executes every `this.speed` seconds
      const new_time = this.increment(); // increment the time and get the new time
      this.act(new_time); // execute the action
    }, this.speed*1000); 
  }
}

const clock = new Clock(3, t => console.log(`Tick tock, the time is ${t}`));
clock.begin();

Upvotes: 1

Alexander Nied
Alexander Nied

Reputation: 13678

The main problem I see here is that rather than your increment method simply incrementing this.num, it returns a function that increments this.num. In the example below, I rewrote it to simply do the incrementing itself. Also in the example we make sure we create new instances using the new operator, so that the JS engine knows we're creating a new instance of an object:

function MyNumber(num) {
  this.num = num;
}

MyNumber.prototype.increment = function() {
  ++this.num;
}

let myNumA = new MyNumber(10);
let myNumB = new MyNumber(100);

console.log(myNumA.num); // 10
console.log(myNumB.num); // 100

myNumB.increment();

console.log(myNumA.num); // 10
console.log(myNumB.num); // 101

Upvotes: 1

Related Questions