1

I was watching a course and its instructor implemented the prototype members outside the constructor function and when you do such a thing, It causes multiple problems. I was wondering, can I declare these prototype members inside the constructor function, because in that case It works properly?

(I looked up in various websites and they had declared the prototype members outside the constructor function and by the way I know these kind of optimization is premature and useless but It's just an exercise)

prototype members outside the constructor function:

function Stopwatch(){
   let running,stop,start;
}


Stopwatch.prototype.start=function(){
    if(running) throw new Error("This watch is already started! ");
    start=console.time("time")/1000;
    running=true;
}

Stopwatch.prototype.stop=function(){
    if(!running) throw new Error("The watch hasn't started yet!");
    stop=console.timeEnd("time")/1000;
    running=false;
}


const timer=new Stopwatch();

prototype members inside the constructor function:

function Stopwatch(){
    let running,stop,start;
    
    
    Stopwatch.prototype.start=function(){
        if(running) throw new Error("This watch is already started! ");
        start=console.time("time")/1000;
        running=true;
    }
    
    Stopwatch.prototype.stop=function(){
        if(!running) throw new Error("The watch hasn't started yet!");
        stop=console.timeEnd("time")/1000;
        running=false;
    }
}
    
const timer=new Stopwatch();
gog
  • 10,367
  • 2
  • 24
  • 38
Lome G ner
  • 21
  • 4
  • Yes you can do it, with `this` keyword. Use `this` keyword instead of `Stopwatch`. But this is not best practice. – Mithat Ercan Dec 25 '22 at 11:22
  • It might be a good idea to find a more modern tutorial. This prototype stuff is obsolete and shouldn't be used in new programs. – gog Dec 25 '22 at 11:44
  • "*when you do such a thing, It causes multiple problems.*" - no, on the contrary, assigning them *inside* the `constructor` causes problems. But your problem is unrelated to that: it is [trying to use `let` variables instead of instance properties](https://stackoverflow.com/q/13418669/1048572?javascript-do-i-need-to-put-this-var-for-every-variable-in-an-object) for keeping the object state. – Bergi Dec 25 '22 at 11:57
  • 2
    @gog "This prototype stuff" is still how classes work, whether they are defined with `class` syntax or not, so it still needs to be taught. – Bergi Dec 25 '22 at 12:01
  • @Bergi: not in a freshman course. – gog Dec 25 '22 at 12:11

1 Answers1

2

I was wondering, can I declare these prototype members inside the constructor function, because in that case It works properly?

No.

Doing that would modify the prototype with new methods each time you instantiated an object. Since you'd be overwriting the existing ones, your variables would be shared between every instance (so every one would have methods that closed over the variables in the call to the constructor of the most recent instance).

Here's a demonstration:

// Do not do this!

function Animal() {
  let type;
  Animal.prototype.set = function(animalType) {
    type = animalType;
  }
  Animal.prototype.get = function() {
    return type;
  }
}

const dog = new Animal;
dog.set('dog');
console.log(`My dog is a ${dog.get()}`);

const cat = new Animal;
cat.set('cat');
console.log(`My cat is a ${cat.get()}`);
console.log(`My dog is a ${dog.get()}`);  // This dog is now a cat!

Don't use variables. Use object properties (this.running etc) instead.

function Animal() {}

Animal.prototype.set = function(animalType) {
  this.type = animalType;
}
Animal.prototype.get = function() {
  return this.type;
}


const dog = new Animal;
dog.set('dog');
console.log(`My dog is a ${dog.get()}`);

const cat = new Animal;
cat.set('cat');
console.log(`My cat is a ${cat.get()}`);
console.log(`My dog is a ${dog.get()}`);

Or, since it is 2022, use the class syntax instead. It has had widespread support in browsers for over half a decade.

class Animal {
  set(animalType) {
    this.type = animalType;
  }
  get() {
    return this.type;
  }
}

const dog = new Animal;
dog.set('dog');
console.log(`My dog is a ${dog.get()}`);

const cat = new Animal;
cat.set('cat');
console.log(`My cat is a ${cat.get()}`);
console.log(`My dog is a ${dog.get()}`);
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335