Class static blocks
in JavaScript allow you to perform additional static initializations during the evaluation of class definitions. However, class static blocks are currently still included in a stage 2 proposal, which is not intended as a replacement for static fields
but is meant to provide new use cases that could not be accomplished using static fields
. Therefore, class static blocks
make object-oriented programming (OOP) JavaScript much more interesting and powerful.
Programming languages such as Java and C# that use classical inheritance
already have implementations like this. In Java, they are static initializers
, while in C#, they are static constructors
.
Unlike these languages, OOP in JavaScript uses prototypal inheritance
. Typically, features like this should not be present. However, with the advent of classes in Ecmascript 2015 (es6), there have been implementations of features that are akin to those seen in classical inheritance
. Some, such as static methods
and extends
, have been implemented already. And now, there are even more experimental features, such as static fields
, private fields
, and class static blocks
.
Despite all of these great evolutions in OOP JavaScript, it is important to note that, under the hood, JavaScript still uses prototypal inheritance. Consequently, a lot of these are mere syntatic sugar
.
Syntatic sugar refers to a new, visually appealing syntax (often a shortcut) to perform an old operation. – Wikipedia
Let’s consider the syntax and semantics of class static blocks
in JavaScript in the next section.
class static blocks
Below is the proposed syntax:
class NewClass { static { // do something } }
No return statements:
class NewClass { static { return // syntax error } }
A class definition should have only one static block {}
.
class NewClass { static {} static {} // throws and error. }
A static block {}
creates a new variable environment nested within the scope of the class.
var age = 23 class NewClass { static { var age; // can still use age inside the static block //because it creates as new lexical scope var name = "Lawrence Eagles" } } console.log(name) // reference error. // cannot access name inside the static block's lexical scope.
From the code above, we can see that although var age
was declared in the same scope as the class, we still create a new age
variable inside the class static block
. This is because the class static block {}
has its own variable environment.
However, we could not access the var name
variable initialized inside the class static block {}
outside its local scope.
A static block {}
should not have decorators. You are to decorate the class itself, as shown below:
@decorator // ok class NewClass { @decorator // error. not allowed static { } }
When evaluated, the this
variable of the static block {}
points to the constructor function
of the class.
You can get more on its semantics here.
As previously mentioned, static blocks
are not replacements for static fields
or static private fields
.
They are however, meant to enable more use cases, as seen below:
Evaluating a statement
during class initialization
:
class NewClass { static square = {L: 8, B: 6}; static y; static z; // wrong code would throw an error try { // do something here }catch (error) { // handle error here } }
The code above would throw an error. We cannot evaluate that try…catch
statement during the class initialization. The try…catch
statement
must be moved outside the class declaration.
However, if we need to evaluate a statement (e.g., try..catch
) inside a class initialization, we can use a static block
as shown below:
class NewClass { static square = {L: 8, B: 6}; static y; static z; static { try { // do something here }catch (error) { // handle error here } } }
When we need to set two fields from a single value, as seen below:
class NewClass { static square = {L: 8, B: 6}; static y; static z; NewClass.y = square.L // throws an error NewClass.z = square.B // throws an error }
We can, however, set the values using static blocks
as shown below:
class NewClass { static square = {L: 8, B: 6}; static y; static z; static { NewClass.y = square.L // correct NewClass.z = square.B // correct } }
When information sharing is required between a class with an instance private field
and another class or function declared in the same scope, as shown below:
let getName; export class NewClass { #name constructor(devName) { this.#name = { data: devName }; } static { // getName has privileged access to the private state (#name) getName = (obj) => obj.#name; } } export function getNameData(obj) { return getName(obj).data; }
From the above, we can see that static blocks
allow you to evaluate statements in the context of the current class declaration with privileged access to (instance
or static
) private state.
Although the getName
function is evaluated in the class static block {}
, it still gets privileged access to the name private state
of the class.
You can learn more about the possible uses of class static block {}
here.
The development of JavaScript has continuously evolved, especially in OOP JavaScript. Although JavaScript maintains its prototypal inheritance
implementation, many new and proposed features are akin to those seen in classical inheritance
.
Class static block {}
is no different. This development is good for the language, as it now appeals to a broader scope of developers who find the prototypal inheritance
a deterrent to adopting JavaScript.
Lastly, class static block {}
is a powerful addition to OOP JavaScript but it is still a stage 2 proposal feature.
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowToast notifications are messages that appear on the screen to provide feedback to users. When users interact with the user […]
Deno’s features and built-in TypeScript support make it appealing for developers seeking a secure and streamlined development experience.
It can be difficult to choose between types and interfaces in TypeScript, but in this post, you’ll learn which to use in specific use cases.
This tutorial demonstrates how to build, integrate, and customize a bottom navigation bar in a Flutter app.