Join over 55,891 Subscribers Today! FREE UPDATES!
Get The Only Freelancer crash course you will ever need to read!
Thanks to expertly crafted libraries such as jQuery and MooTools, JavaScript has become a foundation of Front-End Development. However, it’s extremely important that we note the higher level concepts utilized in these wonderful libraries. Why is that? As web developers, we must equally balance learning the current programming trends with attempts to push the boundaries of those trends. Without this balance, no innovation will occur in web development. So let’s take a moment to appreciate the fundamentals of JavaScript Object Oriented Programming, which include classes, inheritance, and scope.
Before we learn how to implement classes into your code, let’s discuss what classes are and why you should bother learning/using them.
As stated in the Java documentation, “A class is the blueprint from which individual objects are created.” Consider an actual blueprint used in the process of making a house. The builders use the blueprint to evaluate what properties the house contains and what functions the house will execute. Classes are a convenient way to represent the properties of objects, be it a house, car, or person. Classes become especially useful when more than one of a given object exists.
As an example, let’s compare two real-life objects without the use of classes. This mirrors the procedural thought process as opposed to the object oriented thought process. We’ll describe a man named Rob and a baby girl named Emillee. We must assume we know nothing about the human body since we have no blueprint(class) to work from.
Rob:
Emilee:
That was a LOT of work to just describe a human’s 1) Eyes, 2) Shoulders, 3) Hands, 4) Height, and 5) Act of Breathing. Notice we had to make almost the exact same observations both times since we had no blueprint to work from. While describing 2 people wasn’t too bad, what if we wanted to describe 100, 1000, a million? There certainly has to be a more efficient way of describing objects that have similar properties: This is where classes shine.
Let’s rethink the previous example using an object oriented mindset. Since we are describing a man and a baby girl, we know they are both humans. So let’s first create a simple blueprint for humans.
Humans:
So we’ve stated that the properties of humans are that they have eyes, shoulders, hands, and a height. We’ve also stated that these properties may vary. Having defined the blueprint of a Human, and having declared that Rob and Emillee are human, we can apply what we already know about humans to Rob and Emillee.
Rob is a Human.
Emillee is a Human.
By explicitly stating Rob and Emillee are Human, we take the properties and functions associated with being Human and apply them directly to Rob and Emillee. This lets us avoid redefining all the body parts while also letting us effectively describe the key differences between the two objects.
Here are a few examples of classes and their objects(known as instances of the class) so you understand the relationship between the two.
Class Student
Class Employee
Class Computer
So now that we understand the idea behind classes, let’s apply what we know to JavaScript. Unlike languages including PHP and C++, JavaScript does not have the class data type. However, using JavaScripts flexibility, we can easily mimic a class using functions.
Referring to one of our previous examples, let’s use a class to represent students.
When creating a class, there are two things you must do: You must know what properties/functions(also known as methods) the class will have, and you need to initialize the properties with a value.
function Student(name, gender, age, grade, teacher)
{
this.name = name;
this.gender = gender;
this.age = age;
this.grade = grade;
this.teacher = teacher;
}
var bob = new Student("bob", "male", 15, 10, "Marlow");
alert(bob.age); //Outputs 15
var susan = new Student("susan", "female", 10, 5, "Gresham");
alert(susan.gender); //Outputs 'female'
From this example we can see that instances of the class are initiated using the new operator. Properties and methods of the class are accessed using the . (dot) operator. So to get the property age of the instance of the Student class named bob, we simply use bob.age. Similarly, we created an instance of the Student class and assigned that to susan. To get the gender of susan, we simply use susan.gender. The code readability benefits from classes are enormous: You can reason that bob.age is the age of bob without having any programming experience.
However, the previous example contains two detrimental (but easily fixable) flaws.
1) The class properties can be accessed by any statement
2) The arguments must be passed in a certain order
Note that in the previous example, we were able to get the value of bob.age by simply calling bob.age. Additionally, we could set bob.age to any value we feel like anywhere in the program.
var bob = new Student("bob", "male", 15, 10, "Marlow");
alert(bob.age); //Outputs 15
bob.age = 9;
alert(bob.age); //Outputs 9;
Seems harmless, right? Well, consider this example.
var bob = new Student("bob", "male", 15, 10, "Marlow");
alert(bob.age); //Outputs 15
bob.age = -50;
alert(bob.age); //Outputs -50;
We have age as a negative number: A logical inconsistency. We can prevent issues like this and preserve the integrity of our data by utilizing the concept of private variables. A private variable is a variable that can only be accessed within the class itself. While once again JavaScript does not have a reserve word for making a variable private, JavaScript gives us the tools to create the same effect.
function Student(name, gender, age, grade, teacher)
{
var studentName = name;
var studentGender = gender;
var studentGrade = grade;
var studentTeacher = teacher;
var studentAge = age;
this.getAge = function()
{
return studentAge;
};
this.setAge = function(val)
{
studentAge = Math.abs(val); //Keep age positive using absolute value
};
}
var bob = new Student("bob", "male", 15, 10, "Marlow");
alert(bob.studentAge); //undefined, since age is privately protected in the class definition
alert(bob.getAge()); //Outputs 15
bob.setAge(-20);
alert(bob.getAge()); //Outputs 20
By using variable declarations as opposed to attributing properties directly to the class, we have protected the integrity of our age data. Since JavaScript utilizes function scope, a variable declared within our class will not be made accessible outside of that class unless explicitly returned by a function within the class. The method this.getAge, which returns the student age to the calling environment, is known as an Accessor method. An Accessor method returns the value of a property so that the value can be used outside the class without affecting the value inside the class. Accessor methods are usually preceded with the word “get” by convention. The method this.setAge is known as a Mutation method. Its purpose is to alter the value of a property and preserve its integrity.
So we see the benefits of using Accessor and Mutation methods within a class to preserve the integrity of data. However, creating an Accessor method for each property creates extremely long-winded code.
function Student(name, gender, age, grade, teacher)
{
var studentName = name;
var studentGender = gender;
var studentGrade = grade;
var studentTeacher = teacher;
var studentAge = age;
this.getName = function()
{
return studentName;
};
this.getGender = function()
{
return studentGender;
};
this.getGrade = function()
{
return studentGrade;
};
this.getTeacher = function()
{
return studentTeacher;
};
this.getAge = function()
{
return studentAge;
};
this.setAge = function(val)
{
studentAge = Math.abs(val); //Keep age positive using absolute value
};
}
var bob = new Student("bob", "male", 15, 10, "Marlow");
alert(bob.studentGender); //undefined, since gender is privately protected in the class definition
alert(bob.getGender()); //Outputs 'male'
My C++ Professor always said “If you find yourself typing the same code over and over, you’re doing it wrong.” Indeed there is a more efficient way to create Accessor methods for each property. Additionally, this mechanism also eliminates the need to call function arguments in a specific order.
This demonstration is based off John Resig’s Pro JavaScript Techniques book (which I highly encourage you to read. The first 3 chapters alone are worth it).
function Student( properties )
{
var $this = this; //Store class scope into a variable named $this
//Iterate through the properties of the object
for ( var i in properties )
{
(function(i)
{
// Dynamically create an accessor method
$this[ "get" + i ] = function()
{
return properties[i];
};
})(i);
}
}
// Create a new user object instance and pass in an object of
// properties to seed it with
var student = new Student(
{
Name: "Bob",
Age: 15,
Gender: "male"
});
alert(student.name); //Undefined due to the property being private
alert(student.getName()); //Outputs "Bob"
alert(student.getAge()); //Outputs 15
alert(student.getGender()); //Outputs "male"
By implementing this technique, not only do we keep our properties private, we avoid the need to specify our arguments in order. The following class instantiations are all equivalent
var student = new Student(
{
Name: "Bob",
Age: 15,
Gender: "male"
});
var student = new Student(
{
Age: 15,
Name: "Bob",
Gender: "male"
});
var student = new Student(
{
Gender: "male",
Age: 15,
Name: "Bob"
});
Recall that throughout this article I’ve used the term “class” extremely loosely. As stated before, JavaScript has no class entity, but the pattern of classes can still be followed. The main difference between JavaScript and other object oriented languages lies in their inheritance models. C++ and Java exhibit Class-based or “Classical” inheritance. JavaScript, on the other hand, exhibits Prototypal Inheritance. In other object oriented languages, class is an actual data type that represents the blueprint for creating objects. In JavaScript, although we can use Functions to simulate an object blueprint, they are just in fact objects themselves. These objects are then used as models (aka prototypes) for other objects.(See Article JavaScript Prototypal Inheritance).
Applying the concept of prototypal inheritance allows us to create “subclasses”, or objects that inherit the properties of another object. This becomes particularly useful when we want to use the methods of another object with some slight modifications.
Consider a class Employee. Let’s say we have two types of employees: wage-based and commission-based. These employee types will have many similar properties. For example, regardless of whether an employee receives income through commission or receives income through wages, an employee will have a name. However, the way the income for a commission-based employee and a wage-based employee is completely different. The following example captures this idea.
function Worker()
{
this.getMethods = function(properties, scope)
{
var $this = scope; //Store class scope into a variable named $this
//Iterate through the properties of the object
for ( var i in properties )
{
(function(i)
{
// Dynamically create an accessor method
$this[ "get" + i ] = function()
{
return properties[i];
};
//Dynamically create a mutation method that parses for an integer and
//Ensures it is positive.
$this[ "set" + i ] = function(val)
{
if(isNaN(val))
{
properties[i] = val;
}
else
{
properties[i] = Math.abs(val);
}
};
})(i);
}
};
}
//The CommissionWorker "subclass" and WageWorker "subclass"
//inherit the properties and methods of Worker.
CommissionWorker.prototype = new Worker();
WageWorker.prototype = new Worker();
function CommissionWorker(properties)
{
this.getMethods(properties, this);
//Calculates income
this.getIncome = function()
{
return properties.Sales * properties.Commission;
}
}
//Expects the following properties: wage, hoursPerWeek, weeksPerYear
function WageWorker(properties)
{
this.getMethods(properties, this);
//Calculates income
this.getIncome = function()
{
return properties.Wage * properties.HoursPerWeek * properties.WeeksPerYear;
}
}
var worker = new WageWorker(
{
Name: "Bob",
Wage: 10,
HoursPerWeek: 40,
WeeksPerYear: 48
});
alert(worker.wage); //Undefined. wage is a private property.
worker.setWage(20);
alert(worker.getName()); //Outputs "Bob"
alert(worker.getIncome()); //Outputs 38,400 (20*40*48)
var worker2 = new CommissionWorker(
{
Name: "Sue",
Commission: .2,
Sales: 40000
});
alert(worker2.getName()); //Outputs "Sue"
alert(worker2.getIncome()); //Outputs 8000 (2% times 40,000)
The most important statements from the previous example are:
CommissionWorker.prototype = new Worker(); WageWorker.prototype = new Worker();
This states that for each instance of a new CommissionWorker or a new WageWorker object, the properties and methods of Worker will be passed down to those new objects. These methods and properties can be overwritten within the “subclass” definition if so desired.
JavaScript exhibits what is known as function scope. This means variables declared in a function are not initially accessible outside the function from which they originate. However, in blocks (such as coniditonal statements), variable declarations or alterations are made available to the calling environment.
var car = "Toyota";
if(car == "Toyota")
{
car = "Toyota - We never stop...and you won't either.";
}
alert(car); //Ouputs Toyota - We never stop...and you won't either.
car = "Toyota"; //Reset car back to original value.
function makeFord(car)
{
car = "Ford";
}
makeFord(car);
alert(car); //Outputs "Toyota" because car was altered in the function scope.
However, if you want a function to alter the value, you can pass in an object as an argument and alter a property of the object.
var car = new Object();
car.brand = "Toyota"
function makeFord(car)
{
car.brand = "Ford";
}
makeFord(car);
alert(car.brand); //Outputs "Ford"
This is known as passing a value to a function “by reference”. I generally recommend passing by reference only if you are setting up methods within a class and you know what properties the object will contain.
You are now armed with the object oriented basics as applied to JavaScript. Use these principles to simplify your code for projects in the future.
Get The Only Freelancer crash course you will ever need to read!
Joseph McCullough is the lead developer of Vert Studios, a web design company located in Tyler, Texas. Check out the Vert Studios Blog for articles on web development and design. Follow me on Twitter! @Joe_Query
Wednesday, June 8th, 2011 08:43
It is too funny to say, i have saved this page for three times. When i have came to visit this from google. Very detail tutorial for newbie.
Wednesday, January 26th, 2011 20:12
This has a lot of great tips! Thank you for the help.
Monday, October 25th, 2010 09:23
Some good stuff, but confusing for those new to js oo when it comes to the section:
CommissionWorker.prototype = new Worker();
WageWorker.prototype = new Worker();
Even if it’s not the time to delve into the details of how .prototype works – a brief explanation of how it is that this can come before the corresponding function statements would be nice. Does it have to come beforehand or is the order irrelevant?
Wednesday, October 13th, 2010 22:39
Thanks, this is really helpful. As a side note, what plugin do you use to get your code to appear as it does? It’s extremely clean!
Saturday, October 2nd, 2010 21:57
The dynamically Generated Accessor methods example is nice but it lacks one thing to make the class act consistently.
What if you create a new student as follows:
noAge = new Student(
{
Name: “Bob”,
Gender: “male”
}
);
This means the getAge method will not be generated.
A way to generate all the methods that are a part of the design is to add a defaults object.
function Student( properties )
{
var $this = this, //Store class scope into a variable named $this
defaults = {Name: ‘Nobody’, Age: 0, Gender: ‘undefined’};
//Iterate through the properties of the object
for ( var i in defaults )
{
(function(i)
{
// Dynamically create an accessor method
$this[ "get" + i ] = function()
{
return properties[i] != undefined ? properties[i] : defaults[i];
};
})(i);
}
}
Now the noAge student will have a getAge method.
Saturday, October 2nd, 2010 15:26
i don’t understand the syntax
(function(i)
{
// something
})(i)
what’s the meaning of “(i)” ?
Sunday, October 3rd, 2010 15:29
()(i); is a self executing function. This prevents you from adding a method that is only called on object construction.
function Student( properties )
{
var $this = this, //Store class scope into a variable named $this
defaults = {Name: ‘Nobody’, Age: 0, Gender: ‘undefined’};
this.build_accessor = function(i)
{
// Dynamically create an accessor method
$this[ "get" + i ] = function()
{
return properties[i] != undefined ? properties[i] : defaults[i];
};
};
//Iterate through the properties of the object
for ( var i in defaults )
{
this.build_accessor(i);
}
};
Creating and executing a function at the same time is one of the nice javascript features.
Friday, October 1st, 2010 17:18
If my prototypical public methods need to access private attribute then I need to create the get/set mutator for that attribute. By creating getters and setters then I open the way for outside code to change my private attributes.
Is there a way to enforce that only my prototypical public methods accessible from the outside world, but not my mutators?
Thursday, September 30th, 2010 22:21
Awesome tutorial, and thanks for the great useful comments with other JS tutorial links.
Wednesday, September 29th, 2010 15:12
This one of the really few detailed and “awesome” guides i saw in 1stwebdesigner, thanks!
Wednesday, September 29th, 2010 13:08
Great article! Nicely simplified and easy to understand… thanks!
If not, then it's time to learn how to:
You can trust 1stWebDesigner to help you become a better web designer!
- Jacob Cass | Just Creative
Just enter your name and email below and click Get Updates!
Jonern
Wednesday, September 29th, 2010 13:08
Great article! Nicely simplified and easy to understand… thanks!
Joseph McCullough
Wednesday, September 29th, 2010 16:37
Glad to hear! Do you have any JavaScript projects that you could simplify using these principles?
Aneslin
Thursday, September 30th, 2010 22:21
Awesome tutorial, and thanks for the great useful comments with other JS tutorial links.
Aldian
Friday, October 1st, 2010 17:18
If my prototypical public methods need to access private attribute then I need to create the get/set mutator for that attribute. By creating getters and setters then I open the way for outside code to change my private attributes.
Is there a way to enforce that only my prototypical public methods accessible from the outside world, but not my mutators?
Joseph McCullough
Monday, October 4th, 2010 10:28
Yup, there sure is! Take this as a starting point, feel free to tweak as you see fit. Also, you can email me at joseph@vertstudios.com if you have any more questions!
function Worker()
{
this.getAccessorMethods = function(properties, scope)
{
var $this = scope; //Store class scope into a variable named $this
//Iterate through the properties of the object
for ( var i in properties )
{
(function(i)
{
// Dynamically create an accessor method
$this[ "get" + i ] = function()
{
return properties[i];
};
})(i);
}
};
this.getMutatorMethods = function(properties)
{
var obj = {}; //Object that will store private methods
//Iterate through the properties of the object
for ( var i in properties )
{
(function(i)
{
//Dynamically create a mutation method that parses for an integer and
//Ensures it is positive.
obj[ "set" + i ] = function(val)
{
if(isNaN(val))
{
properties[i] = val;
}
else
{
properties[i] = Math.abs(val);
}
};
})(i);
}
return obj;
};
}
//The WageWorker “subclass” inherits the properties and methods of Worker.
WageWorker.prototype = new Worker();
//Expects the following properties: wage, hoursPerWeek, weeksPerYear
function WageWorker(properties)
{
//By assigning methods to the variable, we keep the mutator methods private to the class
var wageWorker = this.getMutatorMethods(properties);
//Make a property of the wageWorker object an object itself that holds class-specific properties
wageWorker.employment = {EmploymentStatus: “hired”, CriminalRecord: “spotless”};
this.getAccessorMethods(properties, this);
this.getAccessorMethods(wageWorker.employment, this);
//Functions a “boss” would have. Private to the class
wageWorker.theBoss = this.getMutatorMethods(wageWorker.employment);
//Calculates income
this.getIncome = function()
{
return properties.Wage * properties.HoursPerWeek * properties.WeeksPerYear;
}
//Private method invocations that will override default values
wageWorker.setWage(20);
wageWorker.setName(“Tim”);
//Fire the worker!
wageWorker.theBoss.setEmploymentStatus(“fired!!!”);
}
var worker = new WageWorker(
{
Name: “Bob”,
Wage: 10,
HoursPerWeek: 40,
WeeksPerYear: 48
});
alert(worker.getIncome()); //Outputs 38400 (20*40*48).
alert(worker.getName()); //Outputs “Tim”
alert(worker.getCriminalRecord()); //Outputs “Spotless”
alert(worker.getEmploymentStatus()); //Outputs “fired!!!”
worker.setEmploymentStatus(“Hired again…”); //ERROR: worker.setEmploymentStatus is not a function.
Dave
Thursday, September 30th, 2010 13:29
Thx Joseph, really didatic samples.
Julian
Thursday, September 30th, 2010 00:11
Excelent post!!, please give us more.
AKLP
Wednesday, September 29th, 2010 15:12
This one of the really few detailed and “awesome” guides i saw in 1stwebdesigner, thanks!
Joseph McCullough
Wednesday, September 29th, 2010 16:36
Thank you! I’d love to see how you apply it. Feel free to email me a link to your next JavaScript project so I can see how you use the Object Oriented Principles.
luglio7
Saturday, October 2nd, 2010 15:26
i don’t understand the syntax
(function(i)
{
// something
})(i)
what’s the meaning of “(i)” ?
Joseph McCullough
Monday, October 4th, 2010 09:09
Hey luglio,
That right there is a self executing function with i as a parameter for that function. The reason why we have to use the self executing function in this context is because closures only provide the last value of the variable within the parent function. Without the self executing function, only the last property would have its dynamic methods generated. Try it for yourself! Take out the self executing part and observe the results.
david
Sunday, October 3rd, 2010 15:29
()(i); is a self executing function. This prevents you from adding a method that is only called on object construction.
function Student( properties )
{
var $this = this, //Store class scope into a variable named $this
defaults = {Name: ‘Nobody’, Age: 0, Gender: ‘undefined’};
this.build_accessor = function(i)
{
// Dynamically create an accessor method
$this[ "get" + i ] = function()
{
return properties[i] != undefined ? properties[i] : defaults[i];
};
};
//Iterate through the properties of the object
for ( var i in defaults )
{
this.build_accessor(i);
}
};
Creating and executing a function at the same time is one of the nice javascript features.
david
Saturday, October 2nd, 2010 21:57
The dynamically Generated Accessor methods example is nice but it lacks one thing to make the class act consistently.
What if you create a new student as follows:
noAge = new Student(
{
Name: “Bob”,
Gender: “male”
}
);
This means the getAge method will not be generated.
A way to generate all the methods that are a part of the design is to add a defaults object.
function Student( properties )
{
var $this = this, //Store class scope into a variable named $this
defaults = {Name: ‘Nobody’, Age: 0, Gender: ‘undefined’};
//Iterate through the properties of the object
for ( var i in defaults )
{
(function(i)
{
// Dynamically create an accessor method
$this[ "get" + i ] = function()
{
return properties[i] != undefined ? properties[i] : defaults[i];
};
})(i);
}
}
Now the noAge student will have a getAge method.
Joseph McCullough
Monday, October 4th, 2010 09:11
David, that’s brilliant! I’ll get that incorporated into the article as soon as possible.
Julian
Monday, October 25th, 2010 09:23
Some good stuff, but confusing for those new to js oo when it comes to the section:
CommissionWorker.prototype = new Worker();
WageWorker.prototype = new Worker();
Even if it’s not the time to delve into the details of how .prototype works – a brief explanation of how it is that this can come before the corresponding function statements would be nice. Does it have to come beforehand or is the order irrelevant?
Brett Widmann
Wednesday, January 26th, 2011 20:12
This has a lot of great tips! Thank you for the help.
Node.js tutorials
Wednesday, June 8th, 2011 08:43
It is too funny to say, i have saved this page for three times. When i have came to visit this from google. Very detail tutorial for newbie.
Jacob Orange
Wednesday, October 13th, 2010 22:39
Thanks, this is really helpful. As a side note, what plugin do you use to get your code to appear as it does? It’s extremely clean!