Black Friday Sale Upgrade Your Home →

ORGANIZING YOUR CODE

In the beginning, this is a great thing! For example, if you just want to make a simple button on your webpage do something, you can set that up in a couple lines of code. However, as your program becomes more complex, it can become hard to maintain unless you take care to organize your code, and because JavaScript is such a flexible language, how you do that is entirely up to you. For many coders, making decisions about design patterns is crippling, so we’re here to help.

This lesson series is going to cover a few of the most common design patterns that occur in modern JavaScript code. We will discuss some pros and cons of each pattern and will give you a chance to practice using each pattern in a project.

The patterns we’ll be covering in this series are

  1. Plain Old JavaScript Objects and Object Constructors
  2. Factory Functions and the Module Pattern
  3. Classes
  4. Modules

Going through these will give us a chance to learn about a few other important concepts in JavaScript such as “closure”, “prototypes”, “IIFEs” and more! This series covers the most important parts of JavaScript after simply learning the basics of the language… are you ready?

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental.

  1. The book You Don’t Know JS (YDKJS) is free on GitHub, and explains how Javascript works “under the hood”. If you ever wondered why JavaScript works the way it does, this book is for you!

OBJECTS AND OBJECT CONSTRUCTORS

Introduction In our JavaScript fundamentals course, you should have learned the basics of using objects to store and retrieve data. Let’s start with a little refresher.

There are multiple ways to define objects but in most cases, it is best to use the object literal syntax as follows:

JSX
const myObject = {
property: 'Value!',
otherProperty: 77,
"obnoxious property": function() {
// do stuff!
}
}

There are also 2 ways to get information out of an object: dot notation and bracket notation.

JSX
// dot notation
myObject.property // 'Value!'
// bracket notation
myObject["obnoxious property"] // [Function]

Which method you use will depend on context. Dot notation is cleaner and is usually preferred, but there are plenty of circumstances when it is not possible to use it. For example, myObject."obnoxious property" won’t work because that property is a string with a space in it. Likewise, you cannot use variables in dot notation:

JSX
const variable = 'property'
myObject.variable // this gives us 'undefined' because it's looking for a property named 'variable' in our object
myObject[variable] // this is equivalent to myObject['property'] and returns 'Value!'

If you are feeling rusty on using objects, now might be a good time to go back and review the content in Fundamentals 5 from our JavaScript Basics course.

Learning Outcomes

By the end of this lesson, you should be able to do the following:

  1. Write an object constructor and instantiate the object.
  2. Describe what a prototype is and how it can be used.
  3. Explain prototypal inheritance.
  4. Understand the basic do’s and don’t’s of prototypical inheritance.
  5. Explain what Object.create does.
  6. Explain what the this keyword is

Objects as a Design Pattern

One of the simplest ways you can begin to organize your code is by simply grouping things into objects. Take these examples from a ‘tic tac toe’ game:

JSX
// example one
const playerOneName = "tim"
const playerTwoName = "jenn"
const playerOneMarker = "X"
const playerTwoMarker = "O"
// example two
const playerOne = {
name: "tim",
marker: "X"
}
const playerTwo = {
name: "jenn",
marker: "O"
}

At first glance, the first doesn’t seem so bad.. and it actually takes fewer lines to write than the example using objects, but the benefits of the second approach are huge! Let me demonstrate:

JSX
function printName(player) {
console.log(player.name)
}

This is something that you just could NOT do with the example one setup. Instead, every time you wanted to print a specific player’s name, you would have to remember the correct variable name and then manually console.log it:

JSX
console.log(playerOneName)
console.log(playerTwoName)

Again, this isn’t that bad… but what if you don’t know which player’s name you want to print

JSX
function gameOver(winningPlayer){
console.log("Congratulations!")
console.log(winningPlayer.name + " is the winner!")
}

Or, what if we aren’t making a 2 player game, but something more complicated such as an online shopping site with a large inventory? In that case, using objects to keep track of an item’s name, price, description and other things is the only way to go. Unfortunately, in that type of situation, manually typing out the contents of our objects is not feasible either. We need a cleaner way to create our objects, which brings us to…

Object Constructors

When you have a specific type of object that you need to duplicate like our player or inventory items, a better way to create them is using an object constructor, which is a function that looks like this:

JSX
function Player(name, marker) {
this.name = name
this.marker = marker
}

and which you use by calling the function with the keyword new.

JSX
const player = new Player('steve', 'X')
console.log(player.name) // 'steve'

Just like with objects created using the Object Literal method, you can add functions to the object:

JSX
function Player(name, marker) {
this.name = name
this.marker = marker
this.sayName = function() {
console.log(name)
}
}
const player1 = new Player('steve', 'X')
const player2 = new Player('also steve', 'O')
player1.sayName() // logs 'steve'
player2.sayName() // logs 'also steve'

Exercise

Write a constructor for making “Book” objects. We will revisit this in the project at the end of this lesson. Your book objects should have the book’s title, author, the number of pages, and whether or not you have read the book.

Put a function into the constructor that can report the book info like so:

JSX
theHobbit.info() // "The Hobbit by J.R.R. Tolkien, 295 pages, not read yet"

Note: It is almost always best to return things rather than putting console.log() directly into the function. In this case, return the info string and log it after the function has been called:

JSX
console.log(theHobbit.info());

The Prototype

Before we go much further, there’s something important you need to understand about JavaScript objects. All objects in JavaScript have a prototype. Stated simply, the prototype is another object that the original object inherits from, which is to say, the original object has access to all of its prototype’s methods and properties.

The concept of the prototype is an important one, so you’ve got some reading to do, which you’ll find in the Assignment section below. Make sure you really get it before moving on!

If you’ve understood the concept of the prototype, this next bit about constructors will not be confusing at all!

JSX
function Student(name, grade) {
this.name = name
this.grade = grade
}
Student.prototype.sayName = function() {
console.log(this.name)
}
Student.prototype.goToProm = function() {
console.log("Eh.. go to prom?")
}

If you’re using constructors to make your objects it is best to define functions on the prototype of that object. Doing so means that a single instance of each function will be shared between all of the Student objects. If we declare the function directly in the constructor, like we did when they were first introduced, that function would be duplicated every time a new Student is created. In this example, that wouldn’t really matter much, but in a project that is creating thousands of objects, it really can make a difference.

Recommended Method for Prototypal Inheritance

So far you have seen several ways of making an object inherit the prototype from another object. At this point in history, the recommended way of setting the prototype of an object is Object.create (here is the documentation for that method). Object.create very simply returns a new object with the specified prototype and any additional properties you want to add. For our purposes, you use it like so:

JSX
function Student() {
}
Student.prototype.sayName = function() {
console.log(this.name)
}
function EighthGrader(name) {
this.name = name
this.grade = 8
}
EighthGrader.prototype = Object.create(Student.prototype)
const carl = new EighthGrader("carl")
carl.sayName() // console.logs "carl"
carl.grade // 8

You can probably figure out what’s going on here. After creating the constructor for EighthGrader, we set its prototype to a new object that has a copy of Student.prototype.

A warning… this doesn’t work:

EighthGrader.prototype = Student.prototype

because it will literally set EighthGrader’s prototype to Student.prototype (i.e. not a copy), which could cause problems if you want to edit something in the future. Consider one more example:

JS
function Student() {
}
Student.prototype.sayName = function() {
console.log(this.name)
}
function EighthGrader(name) {
this.name = name
this.grade = 8
}
// don't do this!!!
EighthGrader.prototype = Student.prototype
function NinthGrader(name) {
this.name = name
this.grade = 9
}
// noooo! not again!
NinthGrader.prototype = Student.prototype
NinthGrader.prototype.sayName = function() {console.log("HAHAHAHAHAHA")}
const carl = new EighthGrader("carl")
carl.sayName() //uh oh! this logs "HAHAHAHAHAHA" because we edited the sayName function!

If we had used Object.create in this example, then we could safely edit the NinthGrader.prototype.sayName function without changing the function for EighthGrader as well.

Assignment

  1. Read up on the concept of the prototype from the articles below.

JavaScriptIsSexy’s article on the prototype is a straightforward introduction and demonstration of the concept. It also covers constructors again.. good time for a review! The important bits here, once you’ve covered the basics, are ‘Prototype-based inheritance’ and the ‘Prototype chain’. To go a bit deeper into both the chain and inheritance, spend some time with JavaScript.Info’s article on Prototypal Inheritance. As usual, doing the exercises at the end will help cement this knowledge in your mind. Don’t skip them! Important note: This article makes heavy use of proto which is not generally recommended. The concepts here are what we’re looking for at the moment. We will soon learn another method or two for setting the prototype.

  1. You might have noticed us using the this keyword in object constructors and prototype methods in the examples above.

Dmitri Pavlutin’s article on the this keyword is very comprehensive and covers how this changes in various situations. You should have a solid understanding of the concept after reading it. Pay special attention to the pitfalls mentioned in each section.

This stack overflow question explains the difference between defining methods via the prototype vs defining them in the constructor.

Test

This section contains questions for you to check your understanding of this lesson. If you’re having trouble answering the questions below on your own, review the material above to find the answer.

  1. Write an object constructor and instantiate the object.
  2. Describe what a prototype is and how it can be used.
  3. Explain prototypal inheritance.
  4. Understand the basic do’s and don’t’s of prototypical inheritance.
  5. Explain what Object.create does
  6. How does this behave in different situations?

if You are not Able to Perform the test Then you can Join my Discord for the Answers

Discord Server Link

  Previous      Next