Ruben Saucedo
Ruben Saucedo

Reputation: 249

Class vs Instance Scope in JavaScript

I am evaluating a way of use the Singleton Pattern called Monostate in JavaScript.

I have some code like the following:

class Boss {
  get name() { return Boss._name }
  set name(value) {
    Boss._name = value;
  }

  get age() { return Boss._age }
  set age(value) {
    Boss._age = value
  }

  toString() {
    return `
      Boss' name is ${this.name}
      and he is ${this.age} years old.
    `
  }
}

Boss._age = undefined;
Boss._name = undefined;

But I am not deeply understanding the difference between the Class scope vs the Instance scope

I mean if I make the following:

let boss = new Boss();
boss.name = 'Bob';
boss.age = 55;

let boss2 = new Boss();
boss2.name = 'Tom';
boss2.age = 33;

console.log(boss.toString());
console.log(boss2.toString());

I will always get the data of the second instance with name Tom, but why?

Boss' name is Tom and he is 33 years old.

Upvotes: 3

Views: 436

Answers (3)

Tom O.
Tom O.

Reputation: 5941

Use this instead of the class name Boss to refer to the object instance from within the class definition:

class Boss {
  get name() {
    return this._name
  }
  set name(value) {
    this._name = value;
  }

  get age() {
    return this._age
  }
  set age(value) {
    this._age = value
  }

  toString() {
    return `
      Boss' name is ${this.name}
      and he is ${this.age} years old.
    `
  }
}

const b1 = new Boss();
b1.name = 'Tom';
b1.age = 55;

const b2 = new Boss();
b2.name = 'Bill';
b2.age = 33;

console.log(b1.toString());
console.log(b2.toString());

The Boss you are referring to in your code is actually the constructor when you really want the instance.

Upvotes: 0

3limin4t0r
3limin4t0r

Reputation: 21130

The reason this behaviour happens is due the fact that instances of Boss refer to the same Boss object to set and read their values. Instances of Boss set the _name and _age value on Boss. When reading from these instance attributes, the last value set is returned.

You can see this by the value of Boss._name that changes every time a an instance of Boss sets their name. After boss.name = 'Bob' the value of Boss._name will be 'Bob'. After setting boss2.name = 'Tom' the value of Boss._name will be 'Tom'.

I've added a snippet that hopefully displays the troubling behaviour better. In the scenario below boss1 and boss2 have their own storage while boss3 and boss4 share their storage (you use the Boss object as storage).

class Boss {
  constructor(storage) {
    this.storage = storage || {};
  }
  
  get name() {
    return this.storage.name;
  }
  
  set name(value) {
    this.storage.name = value;
  }
}

var boss1 = new Boss(),
    boss2 = new Boss(),
    sharedStorage = {},
    boss3 = new Boss(sharedStorage),
    boss4 = new Boss(sharedStorage);

boss1.name = "a";
boss2.name = "b";
boss3.name = "c";
boss4.name = "d";

console.log(boss1.name, boss2.name, boss3.name, boss4.name);

Upvotes: 2

Maheer Ali
Maheer Ali

Reputation: 36574

Boss doesn't refer to instance of class it will refer to the constructor function Boss which is only one in the whole code. In the methods you are adding property not to the instance but the constructor.

You need to use this to access the instance inside the method of an object.

class Boss {
  get name() { return this._name }
  set name(value) {
    this._name = value;
  }

  get age() { return this._age }
  set age(value) {
    this._age = value
  }
}


let boss = new Boss();
boss.name = 'Bob';
boss.age = 55;

let boss2 = new Boss();
boss2.name = 'Tom';
boss2.age = 33;


console.log(boss2.name);

console.log(boss.name);

Upvotes: 0

Related Questions