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) {
this.city = newCity;
},
};
user.changeCity("Miami");
console.log(user.city); // "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) {
this.city = newCity;
},
};
function userCreator(name, lastName, city) {
const newUser = Object.create(userFunctionStore);
newUser.name = name;
newUser.lastName = lastName;
newUser.city = city;
return newUser;
}
const user1 = userCreator("John", "Doe", "San Francisco");
user1.changeCity("Washington");
console.log(user1.city); // "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) {
this.name = name;
this.lastName = lastName;
this.city = city;
}
User.prototype.changeCity = function (newCity) {
this.city = newCity;
};
const user1 = new User("John", "Doe", "Orlando");
user1.changeCity("Boston");
console.log(user1.city); // "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) {
this.name = name;
this.lastName = lastName;
this.city = city;
}
changeCity(newCity) {
this.city = newCity;
}
}
const user1 = new User("John", "Doe", "Dallas");
user1.changeCity("Las Vegas");
console.log(user1.city); // 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.
Sources:
- https://frontendmasters.com/courses/object-oriented-js/
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
We want to work with you. Check out our "What We Do" section!