Bloques de inicialización estática de clases
La nueva sintaxis del bloque de inicialización estática de clases permite a los desarrolladores reunir el código que debe ejecutarse una vez para una definición de clase dada y colocarlo en un solo lugar. Considere el siguiente ejemplo, donde un generador de números pseudoaleatorios utiliza un bloque estático para inicializar un grupo de entropía una vez, cuando se evalúa la definición de class MyPRNG
.
class MyPRNG {
constructor(seed) {
if (seed === undefined) {
if (MyPRNG.entropyPool.length === 0) {
throw new Error('Grupo de entropía agotado');
}
seed = MyPRNG.entropyPool.pop();
}
this.seed = seed;
}
getRandom() { … }
static entropyPool = [];
static {
for (let i = 0; i < 512; i++) {
this.entropyPool.push(probeEntropySource());
}
}
}
Alcance
Cada bloque de inicialización estática es su propio alcance de var
y let
/const
. Al igual que en los inicializadores de campos estáticos, el valor de this
en los bloques estáticos es el propio constructor de la clase. De manera similar, super.property
dentro de un bloque estático se refiere a la propiedad estática de la clase superior.
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'
}
}
// Dado que los bloques estáticos son su propio alcance de `var`, ¡los `var` no realizan hoisting!
y;
// → 'y exterior'
Múltiples bloques
Una clase puede tener más de un bloque de inicialización estática. Estos bloques se evalúan en orden textual. Además, si hay campos estáticos, todos los elementos estáticos se evalúan en orden textual.
class C {
static field1 = console.log('campo 1');
static {
console.log('bloque estático 1');
}
static field2 = console.log('campo 2');
static {
console.log('bloque estático 2');
}
}
// → campo 1
// bloque estático 1
// campo 2
// bloque estático 2
Acceso a campos privados
Dado que un bloque de inicialización estática de clase siempre está anidado dentro de una clase, tiene acceso a los campos privados de esa clase.
let getDPrivateField;
class D {
#privateField;
constructor(v) {
this.#privateField = v;
}
static {
getDPrivateField = (d) => d.#privateField;
}
}
getDPrivateField(new D('privado'));
// → privado
Eso es todo. ¡Feliz orientación a objetos!