Object-Oriented JavaScript

Outline

Are you tired of having related functions, but no way to group them? Do you repeat the same code over and over again? Isn't there a better way? Well, welcome Object Literals and Classes! Through this post, you will learn the basics of Object-Oriented Javascript and when you should use one over the other.

Object Literals

Object Literals are great for modeling one specific thing. They encapsulate related information into one singular object allowing you to easily group data. This object is very similar in concept to a Python dictionary. Let's walk through some situations and examples for using an Object Literal.

Basic example

Let's say you have a dog named Jeffery who is brown with blue eyes. Jeffery can bark and fetch. You could write all of Jeffery's properties and methods straight out...

// Properties
let name     = "Jeffery";
let type     = "dog";
let furColor = "brown";
let eyeColor = "blue";

// Methods
function bark() {
    console.log('bark');
}
function fetch(item) {
    return item;
}

But there are a few issues with this method. First, all of your code for Jeffery is in the global space meaning it is accessible everywhere. While this may sound nice, you will quickly run into naming and overlap issues as your project grows. A better way to write the code for Jeffery is using Object Literals.

Setup

const Jeffery = {
    // Properties
    name:"Jeffery",
    type:"dog",
    furColor:"brown",
    eyeColor:"blue",
    // Methods
    bark: function bark() {
        console.log('bark');
    },
    fetch: function fetch(item) {
        return item;
    }
}

Now, all of Jeffery's methods and properties are nicely encapsulated. Here is how we then access the data using the dot operator and the String version.

Usage

// Properties
console.log( Jeffery.name ); // using the dot operator
console.log( Jeffery["eyeColor"] ); // you can also use a String

// Methods
Jeffery.bark();
let stick = "stick";
console.log( Jeffery.fetch(stick) );

Classes

Classes are great for modeling one generic thing. They create a pattern for how future objects should be built and a model for storing the object's properties and methods. If we take our Jeffery example and added three new animals, we would end up with three very similar Object Literals. This would be a great spot to transform this into a class because now we are modeling a generic thing. An animal.

Basic example

Let's take Jeffery and make a generic animal class with the following:

When we initialize a class (i.e. make a new instance of the animal class), we use a constructor to set the initial properties. Also, functions inside of a class do not need the normal function keyword to start and instead are simply the name of the function.

Setup

class Animal {
    constructor(name, type, bodyColor, eyeColor, noise) {
        this.name      = name;
        this.type      = type
        this.bodyColor = bodyColor;
        this.eyeColor  = eyeColor;
        this.noise     = noise;
    }

    makeNoise() {
        console.log(this.noise);
    }
}

Great! Now we have a working animal class. Let's see how we would use it.

Usage

// Create an instance
const Jeffery = new Animal('Jeffery', 'dog', 'brown', 'blue', 'bark');

// Update a property
Jeffery.noise = 'loud bark!';

// Use a property
console.log(Jeffery.bodyColor);

// Call a method
Jeffery.makeNoise();

Following the above example, you are now ready to start using classes. But wait, you say! What if I want to set properties/methods later and not in the constructor? This is where Getters and Setters come into play.

Getters and Setters

Get: returns a computed value, but is not stored anywhere.
Set: allows you to store a variable not set in the constructor.

Here is an example of adding a getter and setter for an owner property. We will add this to the above animal class.

class Animal {
    constructor(name, type, bodyColor, eyeColor, noise){...}

    get owner() {
        return this._owner;
    }

    // naming convention for 'set' values: _name
    set owner(owner) {
        this._owner = owner;
        console.log(`setter called: ${this._owner}`)
    }

    makeNoise(){...};
}

Now we can use the owner property just like the name or eyeColor property.

Jeffery.owner = 'Isaac';    // Set
console.log(Jeffery.owner); // Get

When to use each

To recap:

Object Literals: great for modeling one specific thing.
Classes: great for modeling one generic thing.

With these two new tools under your belt, what will you go out and build?

Comments

Login to Add comments.