0%
Reading Settings
Font Size
18px
Line Height
1.5
Letter Spacing
0.01em
Font Family
Table of contents

Modern JavaScript OOP Features
Software Engineer
Software Engineer
Frontend
Frontend

When I first started learning JavaScript, its object-oriented features felt like an afterthought. The language had objects and prototypal inheritance, but it was missing key features like true private fields and methods. That’s why many developers turned to TypeScript or other tools to write more structured OOP-style code.
But in recent years, JavaScript has come a long way. Thanks to the latest ECMAScript updates, it now supports a much more powerful and expressive approach to OOP, with built-in features like classes, inheritance, static fields, private fields, getters and setters, and more. Let’s take a look at how these modern features work in practice.
1. Class syntax
JavaScript’s class syntax provides a modern and intuitive way to define objects and behavior.
// language: javascript class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a sound.`); } }
Browser support: Global 96.06%
Ref:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
- https://caniuse.com/es6-class
2. Class fields
Class fields allow you to define instance properties directly in the class body, outside the constructor. There are two types of class fields:
- Instance Fields: These are defined directly on each instance of the class. They can be initialized with a default value or left undefined.
- Static Fields: These are defined with the static keyword and belong to the class itself, not its instances.
// language: javascript class Person { country = "Viet Nam"; // Instance field — each object gets its own "country" static count = 0; // Static field — shared across all instances } const john = new Person(); console.log(Person.count); // 0 -> Accessing static field on the class console.log(Person.country); // undefined console.log(john.country); // Viet Nam -> Accessing instance field on the object console.log(john.count); // undefined
Browser support: Global 94.12%
Ref:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Public_class_fields
- https://caniuse.com/mdn-javascript_classes_public_class_fields
3. Private fields and methods with #
One of the biggest upgrades in modern JavaScript OOP is the introduction of truly private fields and methods, using the # syntax. Before this, developers had to rely on naming conventions (like _private), closures, or Symbols to simulate privacy — none of which offered real protection from outside access.
NOTE: Code run in the Chrome console can access private properties outside the class. This is a DevTools-only relaxation of the JavaScript syntax restriction.
NOTE: Code run in the Chrome console can access private properties outside the class. This is a DevTools-only relaxation of the JavaScript syntax restriction.
// language: javascript class BankAccount { #balance = 0; constructor(owner) { this.owner = owner; } deposit(amount) { if (this.#isPositive(amount)) { this.#balance += amount; } } getBalance() { return this.#balance; } #isPositive(value) { return typeof value === "number" && value > 0; } } const account = new BankAccount("Nam"); account.deposit(100); console.log(account.getBalance()); // 100 console.log(account.#balance); // ❌ Error console.log(account.#isPositive(5)); // ❌ Error
Browser support: Global 93.97%
Ref:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties
- https://caniuse.com/mdn-javascript_classes_private_class_fields
4. Getters and setters
JavaScript classes allow you to define get and set methods for properties. This is useful for encapsulation, validation, or computed properties.
// language: javascript class Product { #price = 0; get price() { return `$${this.#price.toFixed(2)}`; } set price(value) { if (value < 0) throw new Error("Price can't be negative"); this.#price = value; } } const item = new Product(); item.price = 25.5; console.log(item.price); // $25.50
You interact with getters and setters like regular properties, but behind the scenes, you have full control over access and logic.
Ref:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set
5. Inheritance with extends
Inheritance is a core concept in OOP, and modern JavaScript supports it natively using the extends and super keywords. It allows one class (a subclass) to inherit properties and methods from another class (the superclass), enabling code reuse and polymorphism.
// language: javascript class Vehicle { constructor(type) { this.type = type; } } class Car extends Vehicle { constructor(brand) { super("car"); // Call parent constructor this.brand = brand; } describe() { console.log(`${this.brand} is a type of ${this.type}`); } } const car = new Car("Toyota"); car.describe(); // Toyota is a type of car
Browser support: Global 95.04%
Ref:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
- https://caniuse.com/mdn-javascript_classes_extends
6. Static class blocks
Static initialization blocks are declared within a class. It contains statements to be evaluated during class initialization, before any instance is created. This feature is useful when you need to initialize static fields with computed values, validate class-level configuration, or group related static logic together.
// language: javascript class AppConfig { static version; static environment; static { this.version = "1.0.0"; this.environment = process.env.NODE_ENV || "development"; if (this.environment === "production") { console.log("Production mode enabled"); } } constructor() { console.log("App initialized!"); } } // Suppose process.env.NODE_ENV is null console.log(AppConfig.version) // 1.0.0 console.log(AppConfig.environment) // development new AppConfig() // App initialized!
You can declare multiple static blocks, and they will run in order of appearance. Inside a static block, this refers to the class itself, just like in static methods.
Browser support: Global 92.31%
Ref:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_static_initialization_blocks
- https://caniuse.com/mdn-javascript_classes_static_initialization_blocks
7. Babel plugins
To ensure your code runs smoothly everywhere, you can use Babel, a JavaScript transpiler that converts modern syntax into backward-compatible code. To support the latest class syntax, make sure to include the following Babel plugins:
// language: bash @babel/plugin-transform-class-properties @babel/plugin-transform-private-methods @babel/plugin-transform-private-property-in-object @babel/plugin-transform-class-static-block
7. Conclusion
If you haven’t used JavaScript’s OOP features in a while, now is a great time to revisit them. While it still lacks a few things like abstract classes or interfaces, the current feature set is good enough for writing well-structured, maintainable code. And with the language evolving quickly, I believe that we’ll see more improvements soon.
Please note that the “Browser support” number in this blog is recorded as of June 2025. For the most up-to-date information, please refer to the link provided.
Please note that the “Browser support” number in this blog is recorded as of June 2025. For the most up-to-date information, please refer to the link provided.
Related blogs


How to add a custom Inline Code to Trix editor
Lately, I’ve been improving the writing experience in my Rails app, and something kept bugging me: I wanted a way to add inline code formatting in the Trix editor, just like those snippets you see on blogs and documentation sites.Turns out, Trix does...
Frontend
Frontend


I just made a serious mistake with Rails destroy_all
Rails Active Record is convenient and human-readable for interacting with SQL models. But not understanding the generated SQL behind these elegant methods can cause serious data loss that might go unnoticed until it's too late.1. Setting the SceneThi...
Software Engineer
Software Engineer
