Классы ES6 - Обновление статических свойств
Я пытаюсь найти альтернативные способы установить статическое (или класс) свойство класса ES6, а затем изменить его после создания новых экземпляров класса.
Например, допустим, у меня есть класс с именем Geo
, и мне нужно статическое свойство, называемое all
, которое даст мне массив всех экземпляров класса Geo
.
Эта версия работает:
class Geo {
constructor(name){
this.name = name;
Geo.all.push(this);
}
}
Geo.all = [];
ruby = new Geo("Ruby");
rocks = new Geo("Rocks");
console.log(Geo.all.length); // => 2
Я бы предпочел не устанавливать свойство ВНЕ определения класса, хотя. Я пробовал несколько вещей, но не могу создать статическое свойство внутри класса, которое я могу обновить из конструктора.
Я должен также упомянуть, что мне нужно сделать это в браузере (Chrome) без использования Babel или чего-либо подобного.
Вот примеры некоторых вещей, которые я пробовал:
class Geo {
constructor(name){
this.name = name;
Geo.all.push(this);
}
static get all() {
return [];
}
}
ruby = new Geo("Ruby");
rocks = new Geo("Rocks");
console.log(Geo.all.length); // => 0
И другой
class Geo {
constructor(name){
this.name = name;
Geo.all.push(this);
}
static all = [];
}
ruby = new Geo("Ruby");
rocks = new Geo("Rocks");
console.log(Geo.all.length); // => error unexpected "="
Ответы
Ответ 1
В ES6 нет такого понятия, как static all = []
. Экземпляр класса и статические поля в настоящее время являются предложениями этапа 3, которые могут быть использованы через транспортер, например, Babel. Уже существует реализация в TypeScript, которая может каким-то образом быть несовместимой с этими предложениями, но static all = []
действителен в TS и ES.Next.
Geo.all = [];
является действительным и предпочтительным способом сделать это в ES6. Альтернативой является пара геттер/сеттер - или только геттер для свойства только для чтения:
class Geo {
static get all() {
if (!this._all)
this._all = [];
return this._all;
}
constructor() { ... }
}
Отслеживание экземпляров в статическом свойстве обычно нельзя считать хорошим шаблоном и приведет к неконтролируемому потреблению памяти и утечкам (как было отмечено в комментариях).
Ответ 2
Это работает для меня для статических свойств.
class NeoGeo {
constructor() {
}
static get topScore () {
if (NeoGeo._topScore===undefined) {
NeoGeo._topScore = 0; // set default here
}
return NeoGeo._topScore;
}
static set topScore (value) {
NeoGeo._topScore = value;
}
}
И твой пример:
class NeoGeo {
constructor() {
NeoGeo.addInstance(this);
console.log("instance count:" + NeoGeo.all.length);
}
static get all () {
if (NeoGeo._all===undefined) {
NeoGeo._all = [];
}
return NeoGeo._all;
}
static set all (value) {
NeoGeo._all = value;
}
static addInstance(instance) {
// add only if not already added
if (NeoGeo.all.indexOf(instance)==-1) {
NeoGeo.all.push(instance);
}
}
}
Примечание. В получателе можно также проверить наличие свойства с помощью ключевого слова in
или hasOwnProperty
слова hasOwnProperty
.
static get topScore () {
if (!("_topScore" in NeoGeo)) {
NeoGeo._topScore = 0; // set default here
}
return NeoGeo._topScore;
}
И используя hasOwnProperty
:
static get topScore () {
if (NeoGeo.hasOwnProperty("_topScore")==false) {
NeoGeo._topScore = 0; // set default here
}
return NeoGeo._topScore;
}
Ответ 3
У меня недавно была похожая проблема создания статических классов.
Я сначала попробовал это с постоянными переменными класса, но отладчик Chrome выдал ошибку. Поэтому я определил переменные класса "статические", а также методы получения.
Работал в Chrome.
class TestClass {
//static properties.
static _prop1 = [ 'A', 'B', 'C'];
static _prop2 = true;
static _prop3 = 'some String';
//constructor. Commented out because the class only has static elements.
//constructor () {}
//Getters.
static get prop1 () {
return this._prop1;
}
static get prop2 () {
return this._prop2;
}
static get prop3 () {
return this._prop3;
}
}