ES6 Classes vs. Prototypes: Just Syntactic Sugar?

One of the biggest innovations and most debated features in the ES6 (ECMAScript 2015) standard was the introduction of the class keyword into the JavaScript language. Many thought that the language had completely changed and become a true, Java-like class-based program, but in reality, this is merely "syntactic sugar" over the existing prototype-based mechanics.

What Does Syntactic Sugar Mean?

Syntactic sugar refers to programming language features created to make the code easier to read and write, while the underlying mechanism remains unchanged. The introduction of classes provides a much cleaner, more readable structure that is more familiar to developers coming from other languages (especially from the Java, C#, or PHP world).

Let's see how a prototype-based structure looks as a modern ES6 class:

class Developer {
    // The constructor runs upon object instantiation (new keyword)
    constructor(name, language) {
        this.name = name;
        this.language = language;
    }
    
    // In the background, this method is placed on the Developer.prototype object!
    introduce() {
        return `Hi, my name is ${this.name} and I code in ${this.language}.`;
    }
}

const developer1 = new Developer("Gabor", "TypeScript");
console.log(developer1.introduce());

Private Methods and Fields in Classes

For a long time, JavaScript developers used underscores (e.g., _balance) to denote "private" variables, but this was just a convention; they were not actually protected in the code. However, modern JavaScript (ES2022+) now supports true private class members. To do this, a # (hash) character must be placed before the variable or method name.

class BankBranch {
    #balance = 0; // True private field
    
    constructor(owner, initialAmount) {
        this.owner = owner;
        this.#balance = initialAmount;
    }
    
    // Public method that accesses the private data
    getBalance() {
        return this.#balance; 
    }
    
    #secretInternalMethod() {
        console.log("This cannot be called from the outside!");
    }
}

const account = new BankBranch("John Smith", 50000);
console.log(account.getBalance()); // 50000
// console.log(account.#balance); // Error! Private field '#balance' must be declared in an enclosing class

Summary

The introduction of ES6 classes was a massive step toward the readability of JavaScript code. Although prototypes still operate in the background, the class, extends, and super keywords, along with the new private (#) fields, allow for the construction of robust, modern object-oriented (OOP) architectures.

Frequently Asked Questions (FAQ)

Should I still use traditional prototypes?

In modern development, especially in the world of React, Angular, or Node.js, the use of classes (or functional programming) is preferred. Building traditional function() based prototypes is nowadays mostly used only when maintaining existing, legacy code.


You Might Also Like: