Welcome!
Everything is fine.
OOP in JS¶
Today, we'll focus on how to do Object-Oriented Programming (OOP) in JavaScript.
Next time: forms, this
and a bit on debugging.
Plan¶
- Announcements
- Bank Accounts
- OOP in JS
- Objects as Database
- APIs
- Your Questions
- Breakout
- Next time: Pitfalls of
this
Announcements¶
- Grading status
- video on debugging.
- Sliding Tiles
OOP in JS¶
- First, we'll see a practical example, to help make things concrete.
- Then we'll talk about some abstract principles
Example of OOP in JS using new class
syntax¶
Let's see an example using the new class
syntax for OOP in JS, namely
bank accounts. Each bank account has
- state: the current balance for that account, and
- behavior (methods): the way that clients can change the balance,
namely
deposit
andwithdrawal
class Account {
balance = 0;
constructor (init) {
this.balance = init;
}
deposit (amount) {
this.balance += amount;
}
withdrawal (amount) {
if( this.balance >= amount ) {
this.balance -= amount;
} else {
throw new Error("Insufficient funds");
}
}
}
var harry = new Account(1000);
var ron = new Account(2);
var hermione = new Account(200);
Here is a demo using
the new class
syntax; demo opens in a new tab.
If you open the JS console, you can look at the three variables harry
,
ron
and hermione
. You can try using some methods:
// Harry gives Ron 10 galleons
harry.withdrawal(10);
ron.deposit(10);
// create an account for Cho Chang
cho = new Account(200);
cho.withdrawal(50); // money for a new broom
A getBalance() Method¶
How could we write a method to return the current balance? Do this as a paper-and-pencil exercise.
class Account {
balance = 0;
constructor (init) {
this.balance = init;
}
deposit (amount) {
this.balance += amount;
}
...
getBalance () {
return this.balance;
}
...
}
OOP in JS¶
What we saw above has constructors, instance variables and methods. Let's briefly recap each.
Constructors¶
The constructor is the Account
function:
- Create a constructor function (really, it's an initializer)
- By convention, name it with a capital letter, to remind us to use
new
- Use the
new
keyword when invoking the constructor - The value of
this
is an new, empty, object - The constructor can store stuff in
this
when it executes - The constructor has no return value
- Commonly, it's used to initialize the instance variables
We can think of this function as a factory, but in practice we name
it with the things it makes. So, we don't call it makeAccount
; we
called it Account
because we'll use it like this:
var hermione = new Account(200);
Instance Variables¶
In our bank account example, the instance variable is the balance
property. Instance variables
- are also called
- attributes
- data members
- fields
- are properties of the object (
this
) - can be modified like any object property
As an aside:
- ideally, should not be used outside the object, but
- JavaScript doesn't have that abstraction barrier, though
- if every object were a closure, it would
Methods¶
In our bank account example, the two methods were deposit
and
withdrawal
- also called
- member functions
- instance methods
- inherited by all objects created using the given constructor
- the function is shared by all instances (saving memory)
- can use
this
to refer to the object and its properties
Using Objects as a Database¶
There are many kinds of database. A very common and useful type is a key-value database.
For an in-memory database of that kind, we could use JavaScript objects. Like this:
var house = {};
house['cho'] = 'ravenclaw';
house['draco'] = 'slytherin';
house['cedric'] = 'hufflepuff';
console.log(house['cho']);
Or this:
var heads = {};
heads['gryffindor'] = 'McGonnagall';
heads['slytherin'] = 'Snape';
APIs¶
Abstraction barriers give the implementation freedom and flexibility. Here's a picture of the idea (picture by Ross Anderson):

In this chapter we want a key-value database and we decided to use objects, but what if we wanted to change our minds? What if we wanted to switch to Oracle NoSQL or LMDB or ... But if we hide the database behind an abstraction barrier, we can isolate that implementation decision and allow ourselves to change it.
Our API will consist of two methods:
put(key,val)
stores a key, value pairget(key)
returns the stored value
Here's one way, using the new class
syntax:
class KeyValueDB {
db = null;
constructor () {
this.db = {};
}
get(key) {
return this.db[key];
}
put(key,val) {
this.db[key] = val;
}
}
Finally, let's see an example of it in use:
// make a new database of heads-of-house
var heads = new KeyValueDB();
// store two values
heads.put('gryffindor', 'McGonnagall');
heads.put('slytherin','Snape');
Questions¶
We'll look at your questions
Coffeerun¶
I'll run it and do:
- look at
debug.ds1
- fill out the form and submit
- look at
debug.ds1
again - try printing via
debug.truck1.printOrders_buggy
debug.truck1.printOrders_closure
debug.truck1.printOrders_bind
debug.truck1.printOrders_arrow
Exercise 1¶
To get started, copy the ~cs204/pub/downloads/bank
folder to your cs204
folder:
cd ~/public_html/cs204/
cp -r ~cs204/pub/downloads/bank bank
- Make sure it works as above
- Add an instance variable to the object for different types of accounts: checking vs savings
Here's my solution:
function Account(type,init) {
this.type = type;
this.balance = init;
}
Exercise 2¶
Write code to add a method that will add x
percent interest to a savings
accounts but not to checking accounts. Name it addInterest
.
Here's my solution:
class Account {
constructor (init) {
this.balance = init;
}
deposit (amount) {
this.balance += amount;
}
...
addInterest (rate) {
if( this.type == "savings" ) {
this.balance += rate * this.balance;
}
}
}
Did you rename the "x" parameter? Why or why not?
Breakout¶
- work on homework
- ask 1:1 questions