Класс против области действия экземпляра в JavaScript

Я оцениваю способ использования шаблона Singleton под названием Monostate в JavaScript.

У меня есть код, подобный следующему:

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;

Но я не очень хорошо понимаю разницу между областью действия класса и областью действия экземпляра

Я имею в виду, если я сделаю следующее:

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());

Я всегда буду получать данные второго экземпляра с именем Tom, но почему?

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

3 ответа

Причиной такого поведения является тот факт, что случаи Boss относятся к тому же Boss Объект для установки и чтения их значений. Экземпляры Boss установить _name а также _age значение на Boss, При чтении из этих атрибутов экземпляра возвращается последний набор значений.

Вы можете увидеть это по значению Boss._name который меняется каждый раз, когда экземпляр Boss устанавливает их имя. После boss.name = 'Bob' значение Boss._name будет 'Bob', После настройки boss2.name = 'Tom' значение Boss._name будет 'Tom',

Я добавил фрагмент, который, надеюсь, лучше отображает тревожное поведение. В сценарии ниже boss1 а также boss2 имеют свое собственное хранилище, а boss3 а также boss4 поделиться своим хранилищем (вы используете Boss объект как хранилище).

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);

Использование thisвместо имени классаBossчтобы ссылаться на экземпляр объекта из определения класса:

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());

Boss Вы ссылаетесь в своем коде на самом деле конструктор, когда вы действительно хотите экземпляр.

Boss не ссылается на экземпляр класса, он будет ссылаться на функцию конструктора Boss который только один во всем коде. В методах вы добавляете свойство не к экземпляру, а к конструктору.

Вам нужно использовать this чтобы получить доступ к экземпляру внутри метода объекта.

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);

Другие вопросы по тегам