Класс против области действия экземпляра в 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);