Я хотел бы реализовать счетчик, который будет генерировать уникальный идентификатор для каждого экземпляра классов (и подклассов).
На данный момент я использую это:
class Item {
constructor(type) {
this.constructor.counter = (this.constructor.counter || 0) + 1;
this.type = type || "item";
this._id = this.type + "_" + this.constructor.counter;
console.info(this.id);
}
get id() {
return this._id;
}
}
class SubItem extends Item {
constructor() {
super("sub_item");
}
}
var test1 = new Item(); // <- "item_1"
var test2 = new Item(); // <- "item_2"
var test3 = new Item(); // <- "item_3"
var test4 = new Item(); // <- "item_4"
var test5 = new SubItem(); // <- "sub_item_5"
var test6 = new SubItem(); // <- "sub_item_6"
var test7 = new Item(); // <- "item_5"
var test8 = new Item(); // <- "item_6"Ты видишь проблему? Если я сделаю это, сначала создав экземпляр SubItem, каждый будет работать правильно ... Но когда я сначала создаю экземпляр «материнского класса», счетчик сломается. Есть ли способ решить эту проблему?
Я ищу следующее поведение:
var test1 = new Item(); // <- "item_1"
var test2 = new Item(); // <- "item_2"
var test3 = new Item(); // <- "item_3"
var test4 = new Item(); // <- "item_4"
var test5 = new SubItem(); // <- "sub_item_1"
var test6 = new SubItem(); // <- "sub_item_2"
var test7 = new Item(); // <- "item_5"
var test8 = new Item(); // <- "item_6"
Почему именно текущее поведение является проблемой? Я бы посоветовал (ab) не использовать UID экземпляра для различения подклассов.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Поместите уникальный идентификатор за пределы конструктора и разрешите его охват всем классам, которые будут его увеличивать.
let INSTANCE_COUNT = 0;
class Item {
constructor(type) {
this.type = type || "item";
this._id = `${this.type}_${INSTANCE_COUNT++}`;
console.info(this.id);
}
get id() {
return this._id;
}
}
class SubItem extends Item {
constructor() {
super("sub_item");
}
}
var test1 = new Item(); // <- "item_0"
var test2 = new Item(); // <- "item_1"
var test3 = new Item(); // <- "item_2"
var test4 = new Item(); // <- "item_3"
var test5 = new SubItem(); // <- "sub_item_4"
var test6 = new SubItem(); // <- "sub_item_5"
var test7 = new Item(); // <- "item_6"
var test8 = new Item(); // <- "item_7"Я ищу поведение, когда «sub_item» начинает отсчет с 1 вместо того, чтобы следовать за счетчиком «материнского класса». Если я сначала создаю экземпляр «sub_item», все в порядке ... Когда я сначала создаю экземпляр класса «item», счетчик ломается.
Проблема в том, что свойство counter на SubItem - это слежка, свойство counter в классе Item. Итак, когда выполняется следующая строка:
this.constructor.counter = (this.constructor.counter || 0) + 1;
Когда создается первый SubItem, this.constructor.counter, который является доступ, является counter на Item через прототипное наследование. Но тогда назначение this.constructor.counter присваивает counter свойство прямо на SubItem. (так что дальнейшие экземпляры SubItem будут ссылаться на counter непосредственно на SubItem, а не на родительский класс).
Вы можете проверить, является ли свойство counterпрямо на конструкторе, через hasOwnProperty:
class Item {
constructor(type) {
this.constructor.counter = ((this.constructor.hasOwnProperty('counter') && this.constructor.counter) || 0) + 1;
this.type = type || "item";
this._id = this.type + "_" + this.constructor.counter;
console.info(this.id);
}
get id() {
return this._id;
}
}
class SubItem extends Item {
constructor() {
super("sub_item");
}
}
var test1 = new Item(); // <- "item_1"
var test2 = new Item(); // <- "item_2"
var test3 = new Item(); // <- "item_3"
var test4 = new Item(); // <- "item_4"
var test5 = new SubItem(); // <- "sub_item_5"
var test6 = new SubItem(); // <- "sub_item_6"
var test7 = new Item(); // <- "item_5"
var test8 = new Item(); // <- "item_6"Это именно то, что я искал! Однако я не совсем понимаю, как работает ваше решение. Метод hasOwnProperty возвращает логическое значение, а && является логическим оператором. Я не понимаю, как это возвращает натуральное число?
Да ладно ... Я нашел здесь свой ответ: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Думаю, я бы просто инициализировал счетчик как для родительского, так и для подкласса. Я как бы на заборе, но я думаю, что это понятнее и упрощает код в конструкторе. Это также позволяет подклассу контролировать начальную точку (хотя я не думаю, что это очень полезно):
class Item {
constructor(type) {
this.constructor.counter++;
this.type = type || "item";
this._id = this.type + "_" + this.constructor.counter;
console.info(this.id);
}
get id() {
return this._id;
}
}
Item.counter = 0 // initialize
class SubItem extends Item {
constructor() {
super("sub_item");
}
}
SubItem.counter = 0 // initialize
var test1 = new Item(); // <- "item_1"
var test2 = new Item(); // <- "item_2"
var test3 = new Item(); // <- "item_3"
var test4 = new Item(); // <- "item_4"
var test5 = new SubItem(); // <- "sub_item_5"
var test6 = new SubItem(); // <- "sub_item_6"
var test7 = new Item(); // <- "item_5"
var test8 = new Item(); // <- "item_6"Это решение работает, но я стараюсь, чтобы мой код был максимально СУХИМ ...
Я отредактировал (теперь удаленный) комментарий, который вы добавили к моему ответу, прямо в свой вопрос. Если этот комментарий был неправильным, отредактируйте его или отредактируйте свой вопрос, чтобы на самом деле указать, какой результат вы ожидаете. Ответы, которые у вас есть сейчас, основаны на разных предположениях.