A Deep Dive into JavaScript Classes: Static, Public, Private, and Protected
In this blog series, I've discussed the core concepts and features of classes in JavaScript. In this final post, we'll explore an equally important topic: managing the accessibility of properties. According to MDN, The static keyword defines a static method or field for a class, or a static initialization block. Static properties cannot be directly accessed on instances of the class. Instead, they're accessed on the class itself. MDN Static Methods class MyClass { static sayHi() { console.log("Hi from the class."); } } MyClass.sayHi(); // Hi from the class. const myInstance = new MyClass(); myInstance.sayHi(); // Error: myInstance.sayHi is not a function Static Fields class MyClass { static myField = "This is a static field."; } console.log(MyClass.myField); // This is a static field. const myInstance = new MyClass(); console.log(myInstance.myField); // undefined When to Use Static methods are ideal for utility functions, such as creating or cloning instances. Static fields are useful for storing caches, fixed configurations, or other data that does not need to be duplicated across instances. Static methods and fields belong to a class, making them effective for encapsulation, convenience, and reusability. Examples: Utility Function: Static methods are often used for calculations or sorting. e.g. Math.random(); Factory Methods: In programming, a factory method is a static method that creates and returns instances of a class. Configurations or Constants: Static fields are used to store default values or shared settings. e.g. static defaultLanguage = "English"; Inheritance of Static Methods and Fields Static methods and fields are inherited when the extends keyword is used. This is possible because extends sets the child class's [[Prototype]], enabling it to reference the parent class. Note that built-in classes such as Array and Date do not follow this behavior. class ParentClass { static sayHi() { console.log("Hi from Parent."); } } class ChildClass extends ParentClass { sayBye() { console.log("Bye."); } } ChildClass.sayHi(); // Hi from Parent. Private Properties Class properties are public by default, meaning they are accessible from within the class and its instances (including inherited classes). To make a property private and only accessible within the class itself, we can prefix it with #, ensuring it is encapsulated. class MyClass { #privateProperty = "This is private."; getPrivateProperty() { return this.#privateProperty; } } const myInstance = new MyClass(); console.log(myInstance.getPrivateProperty()); // This is private. console.log(myInstance.#privateProperty); // Error Access from Child Classes Private methods and properties cannot be accessed directly in child classes because they are scoped to the parent class. class ParentClass { #sayHi() { console.log("Hi from Parent."); } } class ChildClass extends ParentClass { sayBye() { console.log("Bye."); } } const child = new ChildClass(); console.log(child.sayHi()); // Error Protected Fields Protected fields are typically prefixed with an underscore _ and are intended to be used only within the class or its subclasses. This is not enforced by the language level but is a common convention among developers. Classes are a powerful and dynamic feature, essential for understanding object-oriented programming. Mastering these concepts and applying them in code will make us better developers. Now it's time to put these concepts into practice and take our JavaScript skills to the next level.

In this blog series, I've discussed the core concepts and features of classes in JavaScript. In this final post, we'll explore an equally important topic: managing the accessibility of properties.
According to MDN,
The static keyword defines a static method or field for a class, or a static initialization block. Static properties cannot be directly accessed on instances of the class. Instead, they're accessed on the class itself.
MDN
Static Methods
class MyClass {
static sayHi() {
console.log("Hi from the class.");
}
}
MyClass.sayHi(); // Hi from the class.
const myInstance = new MyClass();
myInstance.sayHi(); // Error: myInstance.sayHi is not a function
Static Fields
class MyClass {
static myField = "This is a static field.";
}
console.log(MyClass.myField); // This is a static field.
const myInstance = new MyClass();
console.log(myInstance.myField); // undefined
When to Use
Static methods are ideal for utility functions, such as creating or cloning instances.
Static fields are useful for storing caches, fixed configurations, or other data that does not need to be duplicated across instances.
Static methods and fields belong to a class, making them effective for encapsulation, convenience, and reusability.
Examples:
Utility Function:
Static methods are often used for calculations or sorting.
e.g. Math.random();
Factory Methods:
In programming, a factory method is a static method that creates and returns instances of a class.
Configurations or Constants:
Static fields are used to store default values or shared settings.
e.g. static defaultLanguage = "English";
Inheritance of Static Methods and Fields
Static methods and fields are inherited when the extends
keyword is used. This is possible because extends
sets the child class's [[Prototype]], enabling it to reference the parent class.
Note that built-in classes such as Array and Date do not follow this behavior.
class ParentClass {
static sayHi() {
console.log("Hi from Parent.");
}
}
class ChildClass extends ParentClass {
sayBye() {
console.log("Bye.");
}
}
ChildClass.sayHi(); // Hi from Parent.
Private Properties
Class properties are public by default, meaning they are accessible from within the class and its instances (including inherited classes).
To make a property private and only accessible within the class itself, we can prefix it with #
, ensuring it is encapsulated.
class MyClass {
#privateProperty = "This is private.";
getPrivateProperty() {
return this.#privateProperty;
}
}
const myInstance = new MyClass();
console.log(myInstance.getPrivateProperty()); // This is private.
console.log(myInstance.#privateProperty); // Error
Access from Child Classes
Private methods and properties cannot be accessed directly in child classes because they are scoped to the parent class.
class ParentClass {
#sayHi() {
console.log("Hi from Parent.");
}
}
class ChildClass extends ParentClass {
sayBye() {
console.log("Bye.");
}
}
const child = new ChildClass();
console.log(child.sayHi()); // Error
Protected Fields
Protected fields are typically prefixed with an underscore _
and are intended to be used only within the class or its subclasses.
This is not enforced by the language level but is a common convention among developers.
Classes are a powerful and dynamic feature, essential for understanding object-oriented programming. Mastering these concepts and applying them in code will make us better developers. Now it's time to put these concepts into practice and take our JavaScript skills to the next level.