How JavaScript Tries to Imitate Classes and Is There a Better Way?
Tags: javascript, classes, prototypes, oop
Published: 2024-06-09 04:15:28

---

title: How JavaScript Tries to Imitate Classes and Is There a Better Way?
published: true
description: A deep dive into how JavaScript mimics class-based structures and the underlying mechanics of prototypes.
tags: [JavaScript, Classes, Prototypes, OOP]
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ljz6eq7ag4egqmbph8dg.jpg

---

## How JavaScript Tries to Imitate Classes and Is There a Better Way?

JavaScript, undoubtedly, can be a very confusing language, especially for those coming from traditional class-based languages like Java or C#. When JavaScript was first created by Brendan Eich, there was an intention to make it look somewhat like Java. This has led to some interesting design choices, particularly around how JavaScript handles object-oriented programming (OOP).

Today, I would like to take a quick look under the hood and see what is going on with JavaScript's approach to classes and prototypes.

## The Evolution of Classes in JavaScript

Before the introduction of the `class` keyword in ES6 (ECMAScript 2015), JavaScript developers used constructor functions to create objects and simulate class-like behavior. Here’s a simple example:

```javascript
// Constructor function
function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.greet = function() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

const john = new Person('John', 30);
john.greet(); // Output: Hello, my name is John and I am 30 years old.
```

In this example, `Person` is a constructor function, and we add methods to its prototype. This allows all instances of `Person` to share the same method, saving memory.

## The Introduction of the `class` Keyword

With ES6, JavaScript introduced the `class` keyword, which provides a cleaner and more familiar syntax for creating objects and handling inheritance. However, under the hood, classes in JavaScript are still based on prototypes.

```javascript
// Class syntax
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    greet() {
        console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
    }
}

const jane = new Person('Jane', 25);
jane.greet(); // Output: Hello, my name is Jane and I am 25 years old.
```

Despite the syntactic sugar, the `class` keyword in JavaScript does not introduce a new object-oriented model. It simply provides a more convenient way to work with prototypes.

## Understanding Prototypes

In JavaScript, every object has a hidden internal property called `[[Prototype]]` that points to another object. This is known as the prototype chain. When you try to access a property on an object, JavaScript will look up the prototype chain until it finds the property or reaches the end of the chain.

```javascript
const animal = {
    eats: true
};

const rabbit = {
    jumps: true,
    __proto__: animal
};

console.log(rabbit.eats); // true
console.log(rabbit.jumps); // true
```

In this example, `rabbit` inherits the `eats` property from `animal` through the prototype chain.

## Classes vs. Prototypes: What’s the Difference?

While classes provide a more structured and organized approach, prototypes offer more flexibility and control. Here’s a comparison:

### Classes

- **Syntax**: Cleaner and more intuitive, especially for developers from class-based languages.
- **Readability**: Easier to read and understand.
- **Inheritance**: Uses the `extends` keyword for inheritance.

### Prototypes

- **Flexibility**: More control over the inheritance chain.
- **Memory Efficiency**: Methods are shared across instances.
- **Compatibility**: Supported in all JavaScript environments, including older ones.

## Real-Life Code Samples

### Using Classes

```javascript
class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        console.log(`${this.name} makes a noise.`);
    }
}

class Dog extends Animal {
    speak() {
        console.log(`${this.name} barks.`);
    }
}

const dog = new Dog('Rex');
dog.speak(); // Output: Rex barks.
```

### Using Prototypes

```javascript
function Animal(name) {
    this.name = name;
}

Animal.prototype.speak = function() {
    console.log(`${this.name} makes a noise.`);
};

function Dog(name) {
    Animal.call(this, name);
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.speak = function() {
    console.log(`${this.name} barks.`);
};

const dog = new Dog('Rex');
dog.speak(); // Output: Rex barks.
```

## Conclusion

JavaScript's approach to OOP through prototypes and the `class` keyword provides developers with powerful tools to create and manage objects. While classes offer a more familiar and organized syntax, understanding prototypes is crucial for mastering JavaScript. Both methods have their own advantages, and a good JavaScript developer should be comfortable using both, depending on the requirements of the project.

By understanding the underlying mechanics of prototypes, you can write more efficient and maintainable code, leveraging the full potential of JavaScript's object-oriented capabilities.