Lesson 2 - The First Object-Oriented Application in JavaScript
In the previous lesson, Introduction To Object-Oriented Programming In JavaScript, we explained the whys and hows of OOP and took a quick peek at some actual OOP code in JavaScript. Today, we will be going deeper into detail of how OOP works and create our very first object-oriented application in JavaScript.
How OOP works
OOP's main purpose is to simulate reality as we perceive it. In other words, we no longer have to care how the program is seen by the computer, instead, we focus on our own perspective. They replaced the assembler with human readable mathematical notation and then that was replaced with OOP. Meaning that there is a certain level of abstraction above the program when OOP is put into use. This has significant advantages because it appears to be more natural and clear to us.
A unit in OOP is referred to as an object which may very well emulate an object in the real world (e.g. human or database objects).
Each object has its own properties and methods.
Properties
Object properties are data that it stores. For example, a
human's name
and age
, or a database's
password
. They are simply variables, with which we have worked
hundreds of times. Occasionally they are referred to as the object's internal
state. Properties are bound to objects, which is how they differ from local
variables (the kind of variable that we've been using up until now).
Methods
Methods are abilities that the object can perform, meaning
its functions. Humans, for example could have
goToWork()
, greet()
, or blink()
methods.
Whereas for databases, addEntry()
or search()
would be
more suitable. Methods can have parameters and may also return a value. Methods
are bound to the object, which is how they differ from functions, which are
global and a major problem of non-OOP code.
We know methods very well, for example we used the write()
method on the document
object. In fact, document
is an
object that represents a document in reality. You can see that we can simply
imagine that we are dealing with a document, ordering it to do something or
setting something to it. It contains methods that the document can perform
(writing, selecting elements, replacing ...) and has some properties, such as
title
, which contains its title.
In older languages, functions didn't belong to objects but were loosely
placed in modules (units). We could call them by typing split(text)
instead of text.split()
. The disadvantage to that was, of course,
that the split()
function didn't belong to anything. There was no
way to list what string could do and the code was messy. Additionally, we
couldn't have two methods with the same name. In OOP we can have both
user.remove()
and article.remove()
. It's very clear
and simple. In a structured program we'd have to write:
remove_user(user)
and remove_article(article)
. We'd
have to create thousands of silly, unnecessary methods. If you're thinking, hey,
isn't that what the PHP language does? You are absolutely
right. PHP is terrible when it comes to things like this, and for that same
reason, its design is considered old. It became fully object-oriented later, but
its foundations will probably never change.
Prototypes and Classes
In 2015, which is quite recently, JavaScript went through major changes. One of them is a support of a modern way of creating objects using classes. This approach is also significantly easier and therefore we'll use it to explain OOP. OOP is already an advanced concept itself and there's no reason to make it any more difficult.
Classes in JavaScript work as syntactic sugar. That means they allow programmers to write simpler and more readable code, but internally, the commands are rewritten to work with prototypes. These were the only reasonable way to work with objects in JavaScript in the past. Of course, in order to be able to edit older source codes and understand how OOP in JS works internally, we'll also explain prototypes in detail in the course. But now back to the classes.
Class
To create an object, we must first create a class. A class is a pattern, based on which we create objects. In other words, it is an extensible program-template used to define properties and abilities.
An object that is created using a class is called an
instance. Instances have the same interface as
the class used to create them, but mutually differ in their internal data
(properties). For example, imagine that we have a Human
class from
which we create carl
and jack
instances. Both
instances certainly have the same properties (e.g. name
and
age
) and methods (goToWork()
and greet()
)
as the main class, but the values within them are different. For example, the
first instance's name
property has the value of "Carl"
and the age
of 22
. Whereas the same properties in the
second one have "Jack"
and 45
as values.
Object-oriented programming itself does not actually know the term object, it only distinguishes classes and instances. If I mention an object in the articles, I mean an instance.
Communication between objects is performed via messages. A message looks
something like this: receiver->methodName(parameters)
. In our
case, it would be something along the lines of
carl.greet(neighbor)
, which would make the carl
instance greet the neighbor
instance.
First Object-Oriented Application
At the beginning of the JavaScript Basic Constructs course we created a Hello world script. It wrote "Hello ICT.social!" to the page. Let's do a similar program as an introduction to object-oriented programming. Let's program Hello object world!
Create a folder, you can name it hello_oop/
, and create a
js/
subfolder in it for the JavaScript files.
Greeter.js
As we explained, for each action there's going to be an object responsible from now on. This division of logic into objects is sometimes also referred to as responsibility assignment. A different object is responsible for each part of the application, and it's declared in a separated file.
To greet the user, we'll create a greeter
object for which, as
we already know, we need a Greeter
class. We name classes using
PascalCase, the first letter is uppercase to specify it's the pattern, not an
object. Of course, we don't use any accent characters in class names as well as
in the identifier names in general. Individual instances, the greeters we
create, will be then named using camelCase, i.e. the first letter will be
lowercase.
We'll create a Greeter.js
file in the js/
folder.
Its contents will be as follows:
'use strict'; class Greeter { }
Let's describe the code.
- Using
'use strict'
we say we want to use a more modern type of source code checking. In this way, JavaScript will alert us about much more bugs and weirdness in our code, which would be ignored in older versions. We'll use this command at the beginning of our files, but we'll not write it anywhere where third-party code is located. Such code could be of an older date and this check could prevent it from running. - The
class
block declares our class, that is, a pattern to create an object or objects of theGreeter
type.
Now we'll add a greeting method, similarly as we declared functions before. Our greeting method will have no input parameters or a return value.
'use strict'; class Greeter { greet() { document.write("Hello OOP!"); } }
We're done here for now.
app.js
Now we'll create an instance of the Greeter
class. It'll be the greeter object we'll work with. We store objects in
variables. Typically, instances has the same name as the class, only the first
letter is lowercase. Let's declare a greeter
variable and then
create a new instance of Greeter
class in it. And we'll let it
greet the user.
In the js/
folder, we'll create a new file named
app.js
and put the following code into it:
'use strict'; const greeter = new Greeter(); Greeter.greet();
Note that:
- We create a new instance using the
new
keyword, followed by the class name which we are creating the instance from. We'll explain why we write the parentheses after the class name later in the course. - If we want the greeter to greet, we just call the
greet()
method on its instance using the dot (.
) operator.
The const Keyword
We used the const
keyword to store the instance. In the JavaScript Basics Course we created variables
mainly with let
. Since we are already advanced, we'll try to
declare variables that do not change using the const
keyword. JavaScript then watches us so that their value never changes.
And we don't want to have anything other than this greeter stored in this
variable ever.
Attention. A common mistake is that people think that an
object stored in a variable declared using const
is immutable. If
the greeter had some properties, we could simply change them, we just can no
longer assign any other object to the greeter
variable.
index.html
We have everything ready so we'll just load our scripts. Therefore, we'll
create the index.html
file in the project's root folder with the
following contents:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Greeter</title> </head> <body> <script src="js/Greeter.js"></script> <script src="js/app.js"></script> </body> </html>
The code is trivial and basically just loads both our JavaScript files.
- Notice that we load classes first. If we tried to create an instance of a class that JavaScript has not yet loaded and therefore does not know it, the script would end up with an error. When we have multiple classes in our application that use each other, we have to load them in such an order that it never happens that JS doesn't know some class.
- Scripts are loaded at the end, before
</body>
, so that they are executed when the page is already loaded. This is a good practice in JavaScript that shouldn't surprise you. If you like to load scripts in the<header>
, you'd have to respond to the page load event in your code.
Let's end today's lesson with a look at our first working object-oriented application:
It's important that we realize that it's now the object that has the function. If anything goes wrong for you, download the sample project in the attachment below to find your bug.
Next time, in the lesson Object Properties and Constructors in JavaScript, we'll show what else objects in JavaScript can do.