Pular para o conteúdo principal

Blocos de inicialização estática da classe

· Leitura de 2 minutos
Shu-yu Guo ([@_shu](https://twitter.com/_shu))

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!

Suporte aos blocos de inicialização estática de classe