Static Initialization Blocks in JavaScript Classes
Static initialization blocks in JavaScript provide a dedicated mechanism to execute complex configuration logic for static properties directly within a class declaration. This article explains what static initialization blocks are, how their syntax works, and precisely when the JavaScript engine executes them during runtime.
What is a Static Initialization Block?
A static initialization block is a block of code marked with the
static keyword inside a class body. It allows you to run
statements, execute logic, and set up static properties when a class is
loaded, rather than waiting for an instance to be constructed.
Prior to static blocks, initializing static properties with logic
like loops, conditional branching, or try...catch blocks
required writing code outside the class declaration. Static blocks keep
all static configuration encapsulated inside the class definition
itself.
class DatabaseConnection {
static defaultPort;
static connectionString;
static {
try {
const envPort = process.env.DB_PORT;
this.defaultPort = envPort ? parseInt(envPort, 10) : 5432;
this.connectionString = `localhost:${this.defaultPort}`;
} catch (error) {
this.defaultPort = 5432;
this.connectionString = 'localhost:5432';
}
}
}When Do Static Initialization Blocks Execute?
Static initialization blocks execute immediately when the class is evaluated by the JavaScript engine—meaning at class definition time.
Key execution rules include:
- Before Instantiation: They run before any instance
of the class is created using
newand before any static methods or properties are accessed externally. - Order of Declaration: If a class contains multiple static fields and static blocks, they execute sequentially in the exact order they appear in the source code.
- Inheritance Order: In class hierarchies with
extends, the superclass static blocks execute before the subclass static blocks. - Single Execution: They execute only once per class definition evaluation, not per instance creation.
class Example {
static first = (() => { console.log('1. Static field initialized'); return 1; })();
static {
console.log('2. First static block executed');
}
static second = (() => { console.log('3. Second static field initialized'); return 2; })();
static {
console.log('4. Second static block executed');
}
}
// Output upon script load:
// 1. Static field initialized
// 2. First static block executed
// 3. Second static field initialized
// 4. Second static block executedPrivileged Access to Private Fields
A unique capability of static initialization blocks is their
privileged access to private properties (#field) and
private methods. A static block can access private instance fields and
export access functions, enabling controlled private state sharing
across different scopes without exposing the fields globally.
let getPrivateField;
class SecureContainer {
#secret;
constructor(secret) {
this.#secret = secret;
}
static {
// Expose access to the private field via a closure
getPrivateField = (instance) => instance.#secret;
}
}
const item = new SecureContainer('confidential-data');
console.log(getPrivateField(item)); // "confidential-data"Summary
Static initialization blocks (static { ... }) streamline
class-level setup by providing a clean, scoped environment for complex
static variable initialization and private field bridging. They run
synchronously and exactly once at the moment the class declaration is
evaluated.