JavaScript Under the Hood #1: Classes

Understanding how classes work in JavaScript

If you're a programmer coming to JavaScript from other languages, you may have heard that JavaScript has "fake" classes. In this article, we'll explore how classes work under the hood in JavaScript and why they're different from classes in other languages.

Before we dive into classes, let's review some basics of object-oriented programming in JavaScript. Object-oriented programming is a popular paradigm for organizing code, especially in large code bases. It involves bundling data with its associated functionality to make the code more manageable and easier to maintain.

In JavaScript, we can achieve this bundling of data and functionality using objects. For example, we can create an object to store a user's name, last name, phone number, and city, and also include a method to change the user's city:

const user = {
  name: "John",
  lastName: "Doe",
  phone: "314-500-2934",
  city: "San Francisco",
  changeCity: function (newCity) { = newCity;

console.log(; // "Miami"

This approach is known as encapsulation, as it bundles data and its associated functionality into a single entity. However, this approach has some scalability issues. For example, every time we create a new user, we create a new copy of the changeCity method in memory. This is not ideal for large code bases and can lead to performance issues.

To solve this problem, we can extract the common functionality into a separate object, called the __proto__ in JavaScript. Here's an example:

const userFunctionStore = {
  changeCity: function (newCity) { = newCity;

function userCreator(name, lastName, city) {
  const newUser = Object.create(userFunctionStore); = name;
  newUser.lastName = lastName; = city;

  return newUser;

const user1 = userCreator("John", "Doe", "San Francisco");
console.log(; // "Washington"

In this approach, we store the changeCity method in the userFunctionStore object, which is shared by all users. This approach is more scalable and efficient.

However, this approach is still not ideal because it's verbose and requires more boilerplate code. To make it easier to use, JavaScript introduced the new keyword, which simplifies the creation of new objects. Here's an example:

function User(name, lastName, city) { = name;
  this.lastName = lastName; = city;

User.prototype.changeCity = function (newCity) { = newCity;

const user1 = new User("John", "Doe", "Orlando");
console.log(; // "Boston"

In this approach, we use the new keyword to create a new object and call the constructor function User to initialize its properties. We also add the changeCity method to the User.prototype object, which is shared by all instances of User.

Finally, in ES2015, JavaScript introduced the class keyword, which provides a more familiar syntax for defining classes in JavaScript. Here's an example:

class User {
  constructor(name, lastName, city) { = name;
    this.lastName = lastName; = city;

  changeCity(newCity) { = newCity;

const user1 = new User("John", "Doe", "Dallas");
user1.changeCity("Las Vegas");
console.log(; // Las Vegas

The ES2015 approach is just a syntactic sugar from the third approach, it works in the same way as adding the changeCity function into the prototype object, but now it's under the hood.

console.log(User.prototype.changeCity); // Function

Using classes instead of functions allow us to get a default constructor and our functions inside the class are automatically added to the prototype object. This can save us time, and improve the code readability and organization, but if the developers involved in the project don't know how classes work they can introduce unexpected bugs into the code.

If you want to continue your studies from here you can check the sources for more. I hope this article helps you in the understanding of classes and how they work under the hood in JavaScript.


We want to work with you! Check out our "What We Do" page.