Blocos de inicialização estática da classe
A nova sintaxe de blocos de inicialização estática da classe permite que os desenvolvedores agrupem o código que deve ser executado uma vez para uma definição de classe específica e o coloquem em um único lugar. Considere o seguinte exemplo, onde um gerador de números pseudoaleatórios usa um bloco estático para inicializar um conjunto de entropia uma vez, quando a definição class MyPRNG
é avaliada.
class MyPRNG {
constructor(seed) {
if (seed === undefined) {
if (MyPRNG.entropyPool.length === 0) {
throw new Error('Conjunto de entropia esgotado');
}
seed = MyPRNG.entropyPool.pop();
}
this.seed = seed;
}
getRandom() { … }
static entropyPool = [];
static {
for (let i = 0; i < 512; i++) {
this.entropyPool.push(probeEntropySource());
}
}
}
Escopo
Cada bloco de inicialização estática é seu próprio escopo de var
e let
/const
. Assim como nos inicializadores de campos estáticos, o valor this
em blocos estáticos é o próprio construtor da classe. Da mesma forma, super.property
dentro de um bloco estático se refere à propriedade estática da superclasse.
var y = 'y exterior';
class A {
static fieldA = 'A.fieldA';
}
class B extends A {
static fieldB = 'B.fieldB';
static {
let x = super.fieldA;
// → 'A.fieldA'
var y = this.fieldB;
// → 'B.fieldB'
}
}
// Como os blocos estáticos são seus próprios escopos `var`, `var`s não são elevados!
y;
// → 'y exterior'
Múltiplos blocos
Uma classe pode ter mais de um bloco de inicialização estática. Esses blocos são avaliados em ordem textual. Além disso, se houver campos estáticos, todos os elementos estáticos são avaliados em ordem textual.
class C {
static field1 = console.log('campo 1');
static {
console.log('bloco estático 1');
}
static field2 = console.log('campo 2');
static {
console.log('bloco estático 2');
}
}
// → campo 1
// bloco estático 1
// campo 2
// bloco estático 2
Acesso a campos privados
Como um bloco de inicialização estática de classe está sempre aninhado dentro de uma classe, ele tem acesso aos campos privados dessa classe.
let getDPrivateField;
class D {
#privateField;
constructor(v) {
this.#privateField = v;
}
static {
getDPrivateField = (d) => d.#privateField;
}
}
getDPrivateField(new D('privado'));
// → privado
E é isso. Bom uso da orientação a objetos!