Какой метод мне следует использовать для подсчета экземпляров подклассов в JavaScript?

Я хотел бы реализовать счетчик, который будет генерировать уникальный идентификатор для каждого экземпляра классов (и подклассов).

На данный момент я использую это:

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" 

Я отредактировал (теперь удаленный) комментарий, который вы добавили к моему ответу, прямо в свой вопрос. Если этот комментарий был неправильным, отредактируйте его или отредактируйте свой вопрос, чтобы на самом деле указать, какой результат вы ожидаете. Ответы, которые у вас есть сейчас, основаны на разных предположениях.

zero298 30.07.2018 22:25

Почему именно текущее поведение является проблемой? Я бы посоветовал (ab) не использовать UID экземпляра для различения подклассов.

Bergi 30.07.2018 22:39
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
115
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Поместите уникальный идентификатор за пределы конструктора и разрешите его охват всем классам, которые будут его увеличивать.

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», счетчик ломается.

René Chenard 30.07.2018 22:25
Ответ принят как подходящий

Проблема в том, что свойство 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 возвращает логическое значение, а && является логическим оператором. Я не понимаю, как это возвращает натуральное число?

René Chenard 30.07.2018 22:51

Да ладно ... Я нашел здесь свой ответ: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

René Chenard 30.07.2018 23:33

Думаю, я бы просто инициализировал счетчик как для родительского, так и для подкласса. Я как бы на заборе, но я думаю, что это понятнее и упрощает код в конструкторе. Это также позволяет подклассу контролировать начальную точку (хотя я не думаю, что это очень полезно):

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"

Это решение работает, но я стараюсь, чтобы мой код был максимально СУХИМ ...

René Chenard 30.07.2018 23:29

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