Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

ES6 Class Mechanics: Syntactic Sugar Over Prototype-Based Constructors

Tech 1

JavaScript's class syntax, introduced in ECMAScript 2015, provides a cleaner interface for creating object blueprints while maintaining the language's underlying prototypal architecture. Prior to this enhancement, developers relied on constructor functions combined with prototype manipulation to achieve object-oriented patterns.

Consider the traditional ES5 approach for defining an entity type:

function Vehicle(make, year) {
    this.manufacturer = make;
    this.productionYear = year;
}

Vehicle.prototype.describe = function() {
    return `Manufactured by ${this.manufacturer} in ${this.productionYear}`;
};

const sedan = new Vehicle("Toyota", 2020);
console.log(sedan.describe());

The instantiation process involves several implicit steps: creating a new object, binding it as the execution context for the constructor, executing the constructor body to initialize properties, and returning the initialized object.

ES6 introduces the class keyword, which formalizes this pattern into a more structured syntax:

class Vehicle {
    constructor(make, year) {
        this.manufacturer = make;
        this.productionYear = year;
    }
    
    describe() {
        return `Manufactured by ${this.manufacturer} in ${this.productionYear}`;
    }
}

const sedan = new Vehicle("Toyota", 2020);

Despite the different appearance, class Vehicle creates a function where Vehicle.prototype holds the defined methods. Verifying this relationship shows that typeof Vehicle yields "function" and Vehicle === Vehicle.prototype.constructor evaluates to true.

Methods declared within the class body automatically attach to the prototype. You can extend this behavior by directly modifying the prototype object:

Vehicle.prototype.honk = function() {
    return "Beep!";
};

Or batch-add functionality using Object.assign():

Object.assign(Vehicle.prototype, {
    startEngine() {
        return "Engine running";
    },
    stopEngine() {
        return "Engine stopped";
    }
});

The constructor method handles instance initialization. If omitted, JavaScript supplies a default empty constructor. Explicitly, the constructor returns this by default, but you can override this to return a differetn object entirely:

class Rental {
    constructor() {
        return {
            type: "temporary",
            valid: false
        };
    }
}

const instance = new Rental();
console.log(instance.type); // "temporary"

Property placement determines ownership. Variables assigned to this inside the constructor become own properties of the instance, while methods defined in the class body reside on the prototype chain:

class Rectangle {
    constructor(width, height) {
        this.w = width;
        this.h = height;
    }
    
    area() {
        return this.w * this.h;
    }
}

const shape = new Rectangle(10, 20);
console.log(shape.hasOwnProperty("w"));    // true
console.log(shape.hasOwnProperty("area")); // false
console.log("area" in shape);              // true

All instances share identical prototype references, meaning modifications through one instance's __proto__ affect all siblings:

const rect1 = new Rectangle(5, 5);
const rect2 = new Rectangle(8, 8);

rect1.__proto__.perimeter = function() {
    return 2 * (this.w + this.h);
};

console.log(rect2.perimeter()); // Available on rect2 as well

Unlike function declarations, class declarations do not hoist. The identifier remains uninitialized until execution reaches the declaration:

// Valid in ES5
const obj = new Legacy();
function Legacy() {}

// Throws ReferenceError in ES6
const item = new Modern();
class Modern {}

For inheritance, ES6 provides the extends keyword and super() function, which invoke the parent class constructor and establish the prototype chain between parent and child prototypes.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.