Classes and Objects in JavaScript

We use classes and objects all the time in just about every dynamic language we use but do we really understand what these data types are? JavaScript is a tricky language to teach this in because “object” could mean object literals (example: {}) or it could mean a full on JavaScript class that includes a constructor function that returns a JavaScript object or class. I’m fascinated/obsessed with Object Oriented JS so today I want to talk about JavaScript classes in the second sense of the word.

What frustrates me most about teaching JS classes is that the objects they create are often confused with POJOs (Plain Old JavaScript Object).

JS has classes?

Yes! People new to advanced JS or Node often don’t realize that this functional language has the concept of classes baked right in except in a different way. Unlike languages with classic inheritance where classes and objects are pretty straightforward, JavaScript classes disguise themselves as named functions and no one ever explores their ability to create classes from these functions.

What is a class and Object Oriented Programming

The best explanation for OOJS (or OO Programming in general) I know of comes from a Rolling Stone interview Steve Jobs did in the 90’s. To paraphrase it goes something like this: I’m a program and I use “libraries” all the time to get things done. These libraries are classes and they act like black boxes where input goes in and output comes out but the program itself doesn’t know or need to know what happens in between. So now I need my laundry done. Not knowing how to do it myself I get a Laundry class to do it for me. I hire someone (an instance of the laundry class) to do it for me. The person shows up to my door and I hand them a bag of dirty laundry and a short time later they return clean clothes back to me. Me, as the program, just gave them dirty laundry as input and the class went out to the laundromat and cleaned my clothes. I have no idea where the laundromat is, how many quarters each machine takes, or how to separate my darks from whites. But luckily my Laundry object knows all about that. It has attributes (the quarters, knowledge of how to get to the laundromat) and methods (separating clothes, using the machines) built in. I can have multiple instances of my Laundry objects (each being a separate person) and give them each a bag of dirty laundry and they’d return different clothes back to me each time based on what input (the bag of clothes) I gave them.

There’s also the classical explanation of classes and objects. A class is a blueprint for creating an instance of a thing with unique attributes. For example, a car is always a popular example. If I created a car class I could pass it input like a brand, horse power, wheel size, etc, and create different car objects based on what I gave as input to the class.

Enough theory, let’s write some code.

How it works

In JavaScript all you need is a constructor function to get going. So let’s create a car class.

1
2
3
4
function Car(brand, horsePower) {
  this.brand = brand || 'Honda';
  this.horsePower = horsePower || 100;
}

This function is a function. But it can also be a class. We’ve bound some properties to any instance of the class created by using this and assigning the arguments to properties on this. This allows the class to keep state. Any instance of the car will remember it’s brand and horse power. It’s already a factory for creating new unique car instances.

But we’re not done because just our class holds states. We want methods to use the object’s state to really make this class useful. So let’s take this farther. Let’s give the car class something useful to do like shift gears and accelerate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Constructor
function Car(brand, horsePower) {
  this.brand = brand || 'Honda';
  this.horsePower = horsePower || 100;
  this.gear = 1;
}

// Car method
Car.prototype.switchGear = function(gear) {
  this.gear = gear;
 }

 // Acellerate
 Car.prototype.accellerate = function(speed) {
  this.speed = this.speed += speedo
 }

 // Let's use the Car class
 var volkswagen = new Car('Volkswagen', 400);

 // Now we can do "useful" (but more exemplary stuff) using this instance of the Car object
 volkswagen.switchGear(3) // Switch to third gear so we can go faster
 volkswagen.accellerate(60); // Up the sleed to 60

This was just an example. It illustrates the idea of classes being blueprints for objects.

Inheritance

This is where JavaScript differs from languages like Ruby and PHP. These languages use classical inheritance to extend their functionality. With JavaScript we have what’s called prototypal inheritance. This is the kind of inheritance where anything added to the prototype chain gets passed down to all objects of the same class at run time. In classical inheritance, attributes and behavior are inherited when the program begins and cannot be altered during runtime. So if I wanted to override or add additional functionality to my car class ass the program was running all we would have to do is add something to the object’s prototype object and then all objects of that class, no matter when they were instantiated will have those properties or methods available to them.

How we can use it

The best example I can think of is to create a wrapper for Node’s native HTTP module you can use to create an API library for a server side API. Back when I was running my last company I did exactly that. I created a class that could be instantiated by initializing it with your API credentials and then using it’s methods to communicate with our RESTful API. I won’t show the full example here but you can see the code for it on GitHub here. Notice how I export it as a module. Although I won’t go through the details of how the library was coded (it’s pretty simply but there’s quite a bit of code for a simple blog post about classes) I’ll show you how it’s used.

1
2
3
4
5
6
7
8
9
// Require dependencies
var Q       = require(q-client),
    QClient = new Q(public key here, private key here);

QClient.getSubsidy(state, zip, {demographic_data_object}, function(err, response) {
  if (err) return new Error(err);

  console.log(response);
});

When people think of JavaScript they think of callback hell, get caught up in avoiding JavaScript’s async nature, but they fail to remember that this functional language has useful object oriented features that get overlooked. Take advantage of the OO principles of state, use those methods, and one day I’ll talk about those awesome prototypes that give JavaScript it’s super-powers.

If you’re still curious about object oriented JS and prototypes, check out my older post on the subject that got picked up by Webucator and turned into a video.

Web Development

« Why I use the MIT License Functions should not fail silently »

Comments