Understanding JavaScript Classes
Introduction: Why Classes in JavaScript?
When you first start programming, you often write code that executes line by line. As your projects grow, you might find yourself managing many related variables and functions. For example, if you are building an application with many users, you might have many names and greeting functions scattered around. This can become messy very quickly.
Object-Oriented Programming, or OOP, solves this problem by grouping data and behavior together. In JavaScript, we use a class as a blueprint. Imagine a blueprint for a house; the blueprint is not the house itself, but it tells you how to build one. Similarly, a class tells JavaScript how to create objects that contain specific information and can perform specific actions. This approach makes your code much more organized and professional.
Defining a Class with the class Keyword
To create this blueprint, we use the class keyword followed by a name. By convention, class names start with a capital letter. Inside the class, we use a special method called the constructor. This is a unique function that runs automatically whenever you create a new version of your class.
In this example, the Greeter class has a constructor that takes a name as an argument. The keyword this refers to the specific object being created. By writing this.name = name, we are telling JavaScript to take the name we provided and save it inside that specific object. This allows every object created from this blueprint to remember its own unique data.
Adding Methods to a Class
A class is not just for storing data; it is also for defining behavior. We can add functions to our class, which are called methods when they live inside a class. These methods can access the data we stored in the constructor by using the this keyword again.
The hello method belongs to the Greeter class. When it runs, it looks at this.name to see which name belongs to the current object. It then returns a friendly string. Notice that we do not use the function keyword when defining methods inside a class; we simply write the name of the method followed by parentheses.
Creating Instances with new
Once we have our blueprint, we need to build an actual object from it. We call this instantiating the class, and we do it using the new keyword. Each time we use new, JavaScript creates a unique instance that has its own properties.
Output:
In this code, g1 and g2 are two different objects. Even though they both come from the same Greeter class, they are independent. When we call g1.hello(), it knows to use "Ada" because that is the name we passed to the constructor for that specific instance. This is the power of classes: one blueprint can create many unique objects.
The Prototype Model: How Methods Are Shared
You might wonder if every object we create has its own copy of the hello method. If we had thousands of objects, thousands of copies of the same function would waste a lot of computer memory. JavaScript handles this efficiently using something called the prototype.
Methods defined in a class actually live on the prototype of that class, not on the individual objects themselves. When you call g1.hello(), JavaScript first looks at g1. If it does not find the method there, it looks up at the prototype. Since both g1 and g2 share the same prototype, they share the exact same function in memory. This makes JavaScript very fast and efficient.
Output:
Type Checking with instanceof
As you build complex programs, you may need to check if an object was created from a specific class. JavaScript provides the instanceof operator for this purpose. It checks the "prototype chain" to see if the object belongs to a class or its parents.
Output:
The first line returns true because g1 was created using the Greeter class. The second line also returns true because almost everything in JavaScript is a type of Object. The instanceof operator "walks up the chain," checking every level of the object's ancestry until it finds a match or reaches the end.
Recognizing the ES5 Constructor Pattern
Before the modern class keyword was introduced in 2015, developers used regular functions to act as constructors. You will still see this older style in many legacy codebases and older tutorials. It is important to recognize it so you are not confused when you encounter it in the wild.
Output:
In this older pattern, the data is set inside a function, and the methods are manually attached to the prototype property of that function. While this uses the same underlying prototype-sharing model for methods, modern classes are not exactly the same. Modern classes are mostly syntactic sugar over prototypes, but they also have stricter rules and some different semantics—for instance, classes cannot be called without new, and they automatically run in strict mode. For this course, and for your own projects, you should always prefer the modern class syntax as it is much cleaner and more robust.
Summary and Practice Ahead
In this lesson, we learned how to use the class keyword to create blueprints for our objects. We used the constructor to set up initial data and added methods to define how our objects should behave. We also touched on the prototype, which is JavaScript's clever way of sharing methods between objects to save memory. Finally, we saw how the instanceof operator helps us identify the type of an object.
In the upcoming practice exercises, you will get to write your own classes and create instances yourself. This hands-on practice will help make these concepts feel natural to you. Good luck!
