cult3

Javascript Objects

Oct 15, 2012

Table of contents:

  1. Creating Objects
  2. Accessing Properties
  3. Methods
  4. Custom Constructors
  5. Objects and other stuff
  6. Object default Methods
  7. For In loop
  8. Prototypes
  9. Why do Prototypes work like this?
  10. Multiple Inheritance
  11. Wrap up

Javascript Objects are part of the fundamental building blocks of the language and will become invaluable once you start creating more complex Javascript applications. Objects allow us to group common properties and functions together into a single object to allow an application to work with that data all in one place.

We’ve already looked at the basics of Javascript, including strings, numbers and arrays that allow us to store and work with bits of data.

Next we looked at creating Javascript functions that allow us to create reusable chunks of code that abstract any repeated functionality into one location and allows use to build more complex applications.

Objects are the next important thing to learn in Javascript. You can think of an Object as an instance of a certain something. For example, you and I are instances of humans, we both have names, ages and other characteristics that make us unique, but we are both still humans.

Creating Objects

Objects allow us to store all the relevant information about something in one place.

To create an object we can use curly braces.

var philip = {};

Inside Objects, we can store properties that represent the object. For example, in the “Philip” object, I might want to store my age, website, twitter handle and interests.

var philip = {
  age: 24,
  website: "culttt.com",
  twitter: "philipbrown",
  interests: ["design", "development", "business"],
};

As you can see, each property is given a name and a value. The property (key) and value are separate by a colon, and each key value pair is separated by a comma. Also notice how we can use a combination of numbers, strings and arrays.

The method above for creating Javascript Objects is called Literal Notation, but there is another way to create Objects.

For example:

var philip = new Object();
philip.age = 24;
philip.website = "culttt.com";
philip.twitter = "philipbrown";

This second way is called Constructor Notation.

Accessing Properties

Now that we have made the Object and we have set the properties within in it, how do we access the data?

To access data from an object you can do it through Dot Notation or Bracket Notation.

// Do Notation
var twitter = philip.twitter;
// Bracket Notation
var website = philip["website"];

Methods

Methods are one of the fundamental aspects of Object Oriented Programming that you should be familiar with.

A method is basically just a Function that is part of an object. So as we’ve just seen, properties like “age”, “website” and “twitter handle” are variables that are all related to the object, methods are just functions that are related to the object.

So for example:

var philip = new Object();
philip.age = 24;
philip.addTwitter = function (twitter) {
  philip.twitter = "https://twitter.com/" + twitter;
};
// Add Twitter handle
philip.addTwitter("philipbrown");
alert(philip.twitter);

In the example above, we are using a method to save the user’s full twitter URL but only requiring them to enter their username.

Now if we wanted to update the Twitter URL, we could just run the addTwitter method again.

philip.addTwitter("culttt");

Methods are extremely important for using Objects within Javascript because they allow you to work with the properties inside them.

Our addTwitter function is great for setting the Twitter URL for the philip object, but what if we wanted to also use the method on another Object? Currently we would have to rewrite the same method and attach it to the new object, which isn’t very good because we are needlessly repeating ourselves (Don’t Repeat Yourself).

To make Methods work for any objects, we can use the keyword this. The this keyword represents the current object and so it acts like a placeholder.

var addTwitter = function (twitter) {
  this.twitter = "https://twitter.com/" + twitter;
};

As you can see in this example, we have separated the Method and replaced the hardcoded object reference with the keyword this.

Now we can reuse this method on any object.

var addTwitter = function (twitter) {
  this.twitter = "https://twitter.com/" + twitter;
};

// Create a philip object
var philip = new Object();
philip.addTwitter("philipbrown");

// Create a culttt object
var culttt = new Object();
culttt.addTwitter("culttt");

Custom Constructors

At the beginning of this post, I introduced you to the Constructor Notation way of creating new objects.

var book = new Object();
book.title = "Crush It!";

This works because Object() is recognised by Javascript and so it knows to just make a new empty constructor.

But as you have probably picked up so far, creating new objects and assigning the properties one by one is incredibly tedious. Programming is all about efficiency and simplicity, so to make the process of creating new Objects more efficient and simple, we can define our own constructors.

function Book(title, author) {
  this.title = title;
  this.author = author;
}

Notice how I defined Book with a capital letter. This is an important Javascript style that shows that this is an object. Also notice how again I use the this keyword.

Next we can create new objects using our constructor.

var book1 = new Book("Crush It!", "Gary Vaynerchuk");
var book2 = new Book("Fooled by Randomness", "Nassim Nicholas Taleb");

This allows us to create new objects in a much easier and simple way.

Defining our own constructors also allows us to set default values for each new object.

function Book(title, author) {
  this.title = title;
  this.author = author;
  this.format = "Paperback";
}

Now each new object will have the format property of “Paperback” without us having to explicitly set it on construction.

And of course, our custom constructors can also have Methods.

function Book(title, author) {
  this.title = title;
  this.author = author;
  this.format = "Paperback";
  this.setPrice = function (price) {
    this.price = price;
  };
}

Now each new object will have a Method that allows you to set the price of the book.

Objects and other stuff

Objects are really useful for storing and manipulating collections of data that all relate to one another. Objects can be combined with Arrays and Functions to extend this usefulness.

For example, you might want to create an array of business books for use in a library application.

// Create object constructor
function Book(title, author) {
    this.title = title;
    this.author = author;
}

// Add books to the business category
var business[0] = new Book("Crush It!", "Gary Vaynerchuk");
var business[1] = new Book("Fooled by Randomness", "Nassim Nicholas Taleb");
var business[2] = new Book("Unleashing the ideavirus", "Seth Godin");

Objects can also be passed into functions much the same way you can pass strings or numbers.

// Create object constructor
function Book(title, author) {
  this.title = title;
  this.author = author;
}
// A function to print the name
// and title of the book
var printNameTitle = function (Book) {
  console.log(Book.title + " was written by " + Book.author);
};
// Create a book
var book1 = new Book("The Lean Startup", "Eric Ries");
// Run the function
printNameTitle(book1);

Object default Methods

When we create an Object in Javascript, it comes ready with a couple of predefined Methods that can be extremely useful.

For instance, the hasOwnProperty method checks to see if the object has a particular property set.

var car = {
  electricWindows: true,
  powerSteering: true,
};
car.hasOwnProperty("electricWindows"); // returns true
car.hasOwnProperty("ejectorSeat"); // returns false

For In loop

As I mentioned above, programming is all about doing things in the most efficient and simple ways. Say we have an object that has 5 different properties and we need to print each of those properties to the screen. Calling each property is tedious especially if you need to do this on multiple objects, or if the objects has different property names.

To get around this problem, we can use the for in loop.

// Create a user object
var user = {
  name: "Philip Brown",
  location: "England",
  age: 24,
  twitter: "philipbrown",
};
// Print out each property
for (var property in user) {
  console.log(property);
}

Similarly, we can use Bracket Notation to get the values from the object.

// Print out each property
for (var key in user) {
  console.log(user[key]);
}

Prototypes

Prototypes are an important concept to understand in Javascript. It is probably easier to explain with an example.

Take for instance the follow code.

//Construct the object
function Laptop(type) {
  this.type = type;
}
// Create a new Apple Laptop
var apple = new Laptop("MacBook");
// Create a function to connect to the internet
apple.internet = function (connection) {
  if (connection === true) {
    console.log("You are now connected to the internet");
  }
};
// Connect to the internet
apple.internet(true);
// Create a new Sony laptop
var sony = new Laptop("Vaio");
// Try to connect to the internet
sony.internet(true);

If we try to run the code above, we will get an error on the last line. This is because the internet method is not defined on the Sony object.

To allow all of the Laptop objects to have the internet method, we can add it using the prototype.

Laptop.prototype.internet = function (connection) {
  if (connection === true) {
    console.log("You are now connected to the internet");
  }
};

Now if we run the code again, we should be able to connect to the Internet through both laptops.

The prototype is a special way of adding stuff like Methods to Objects. It is also important, because everything that is created will be able to inherit that new Method.

When creating new objects, it is often useful to be able to bootstrap those new objects with some defined properties. For example, if we were going to make a new object for every book on Amazon, we wouldn’t want to write out the same properties that are common across every book, rather, we would just want to set the things that are unique for each book.

If you are familiar with Object Oriented Programming in other languages, you will already be familiar with the concept of inheritance. Inheritance works in a different way in Javascript, but it is a very powerful concept to understand.

So first we need to create a prototype for all the books on Amazon. Our prototype holds all of the common attributes we want all of our books to hold.

var bookPrototype = {
  category: "Uncategorised",
  kindle: true,
  tags: [],
  available: true,
  isAvailable: function () {
    if (this.available === true) {
      console.log("This book is available for purchase");
    } else {
      console.log("I'm sorry we are out of stock");
    }
  },
};

So when it comes to adding a new book to the Amazon directory, we want to grab a copy of the prototype and create a new book.

So first we create our constructor function.

function Book(name, author) {
  this.name = name;
  this.author = author;
}

Next we need to grab a copy of the bookPrototype using the special prototype property.

Book.prototype = bookPrototype;

Next we can create a new book for Amazon.

var book1 = new Book("The 4 hour work week", "Tim Ferriss");

Now when we access the name and the author of the book we get the name and the author back as you would expect.

book1.name; // returns "The 4 hour work week"
book1.author; // returns "Tim Ferriss"

But now what happens when we see if there is a Kindle edition?

book1.kindle; // returns true

So as you can see, we have created a new object that is based upon the prototype. Now by default, all of our books will be available on the Kindle and will be available for purchase.

How do Prototypes work?

Prototypes in Javascript work by secretly linking objects together that allows inheritance to work.

So in our example above, when we set the Book.prototype property, we were actually creating a link to the bookPrototype that means all new Book objects will inherit from the assigned prototype.

If you imagine your Book object as a tree. When you created your Book object and set the Name and the Author of the book, those properties were set at the top of the tree because you explicitly assigned them. But when you look for the Kindle property, Javascript starts at the top of the tree and looks for something that references Kindle. At first, Javascript can’t find anything that references Kindle at the top of the tree because we did not assign it. Javascript continues down the tree until it finds the Kindle property. In this case it returns true.

Using Prototypes

Next we will create another book based upon the same prototype.

var book2 = new Book("The Innovator's Dilemma", "Clayton Christensen");

Now we have two books with different names and authors, but they both have inherited the standard base properties that we want all books to have.

Next we want to categorise “The Innovator’s Dilemma” as being a business book.

To do this, we can set the property like this.

book2.category = "Business";

Now when we access the category property on book2 we should be returned the string, “Business”.

book2.cateogry; // returns "Business"

But the category property was inherited from the prototype, does that mean “The 4 hour work week” will also be categorised as “Business” too?

book1.category; // returns "Uncategorised"

As you can see it still returns “Uncategorised”.

So why is that? Well, when you set book2’s category to “Business” you are effectively setting that property at the top of the tree. When Javascript looks for the category property it finds it at the top and so it returns it.

Now we can create new books from the standard prototype and we can update their properties with new data.

Modifying Prototypes

Amazon is having technical difficulties with their Kindle downloads and so they are currently unavailable. In order to prevent people from trying to download new books on their Kindle, we need to set the Kindle property in all of our books to false. Unfortunately we now have millions of books, do we have to go through each book and update them?

Fortunately, we can update the prototype to reflect the Kindle downtime.

Book.prototype.kindle = false;

Now when we try to access the Kindle editions on any of our books, we are returned false.

book1.kindle; // returns false
book2.kindle: // returns false

And so you can see, it is now extremely easy to update any of the properties across the objects that were inherited from the Prototype.

Why do Prototypes work like this?

When we use Prototypes in Javascript, we can say that we are chaining them together. The secret link that links the prototype to the Object is the chain.

Prototypes are fundamental to how Javascript works. For instance, when we create a new function, we are essentially creating a new Object of type Function.

Function is a predefined Javascript Object, and so it inherits properties like length and methods like call and apply.

So when we create a new object, we are really just building on top of the already defined Javascript architecture, and when you use a function or an object with a predefined method, it is available to you because of inheritance, just like what we have just shown with the Prototype example.

Multiple Inheritance

Inheritance through the Prototype is not limited to just one layer of inheritance. By creating Objects that inherit from another Object, we can write some powerful code.

For example, a CEO of a company is also a manager and an employee of the company. In Javascript we could represent each of these roles as an Object.

// Employee
function Employee(name, job) {
  this.name = name;
  this.job = job;
  this.employed = true;
}
// Manager
function Manager(name, department) {
  this.name = name;
  this.job = "Manager";
  this.department = department;
}
// CEO
function CEO(name) {
  this.name = name;
  this.department = "The Board";
}

Next we set the prototype chain between the objects.

Manager.prototype = new Employee();
CEO.prototype = new Manager();

Next we create a new CEO and print out some properties.

theCEO = new CEO("Jane");
console.log(theCEO.name); // Prints "Jane"
console.log(theCEO.department); // Prints "The Board"
console.log(theCEO.job); // Prints "Manager"
console.log(theCEO.employed); // Prints True

So as you can see, we can inherit properties through a number of different chained Objects.

Wrap up

Phew! That was a long post, congratulations for sticking with it and getting this far!

Objects are not only incredibly useful in Javascript, but their usage is an important concept to understand as you familiarise yourself with Object Oriented Programming. This concept carries over to other programming languages, so by understanding the fundamentals and the goals in one language, you will be able to recognise the same patterns in another.

Objects are extremely useful for working with data in Javascript. An Object allows you to group things of the same type together, inherit properties and methods, and extend them to other Objects to prevent code duplication and repetition.

Come back soon as we go deeper still into our exploration of Javascript!

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.