logo
logo

Object Oriented Programming Cheatsheet

Introduction to Object Oriented Programming

The basic features of object-oriented programming

Object-oriented programming is a programming paradigm that uses objects to represent real-world things. An object is a data structure that contains data and methods that can be used to manipulate that data. In OOP, objects are organized into classes, which define the properties and methods that objects of that class will have. JavaScript is a little different from other classic programming languages in that it is fully object-oriented, but it uses prototype-based programming rather than class-based programming.

Creating objects with constructor functions

To create objects, we can use constructor functions. A constructor function is a special type of function that is used to create objects. Here's an example:

function Ship() {
  this.floats = true;
  this.material = 'steel';
}

const myShip = new Ship();
console.log(myShip.floats); // Output: true
console.log(myShip.material); // Output: steel
In this example, we created a constructor function called
Ship
that has two properties,
floats
and
material
. We then instantiated a new object of the
Ship
class called
myShip
. We can access the properties of
myShip
using dot notation.

Encapsulation of data and methods in objects

Data and methods objects are encapsulated, meaning they can only be accessed within the context of the object itself. For example, we can't access the
floats
property of the
myShip
object like this:
console.log(floats); // Output: ReferenceError: floats is not defined

To access the properties of an object, we must use dot notation or bracket notation:

console.log(myShip.floats); // Output: true
console.log(myShip['material']); // Output: steel

Inheritance and prototype-based programming

Inheritance works a little differently than in other classic programming languages. JavaScript uses prototype-based programming, which means that each object has a private property called the prototype, which can have a prototype of its own. When we access a property or method on an object, JavaScript walks up the prototype chain to find it.

Here's an example:

const myObject = {
  a: 1
};

const myOtherObject = Object.create(myObject);
myOtherObject.b = 2;

console.log(myOtherObject.a); // Output: 1
console.log(myOtherObject.b); // Output: 2
In this example, we created an object called
myObject
with a property
a
. We then created another object called
myOtherObject
using
Object.create()
, which takes
myObject
as its argument. We added a property
b
to
myOtherObject
. When we access the property
a
on
myOtherObject
, JavaScript walks up the prototype chain to find it on
myObject
.

The prototype chain and how it works

The prototype chain is a fundamental concept in JavaScript that provides a mechanism for inheritance.

Each object has a private property called the
prototype
, which can have a
prototype
of its own. Essentially, the prototype chain works by walking up the chain until it finds the method or property it's looking for, and it checks if it exists in the instance itself, then in the prototype of the instance, and so on until it reaches the end of the chain, which is the object prototype.

This is how JavaScript does inheritance differently than some of the other traditional class-based object-oriented languages, where you define a class and then create an instance of that class.

Here's an example to illustrate the concept of the prototype chain:

const myObject = { a: 1 };
console.log(myObject.a); // 1
console.log(myObject.toString()); // [object Object]
In this example, we have an object called
myObject
, which has a property called
a
. We can access this property using dot notation. The second console.log statement demonstrates how the prototype chain works. The
toString()
method is called on
myObject
, but this method is not defined on the instance of the object. JavaScript then looks up the prototype chain to see if the method is defined on the prototype of the object. In this case, it is defined on the
Object.prototype
, so it returns the default
toString()
method.

Checking for own properties with
hasOwnProperty()

hasOwnProperty 
is a method of the
Object
constructor that returns a boolean value indicating whether the object has the specified property as its own property (as opposed to inheriting it from the prototype chain).
Here's an example to illustrate the
hasOwnProperty()
method:
const myObject = { a: 1 };
console.log(myObject.hasOwnProperty('a')); // true
console.log(myObject.hasOwnProperty('toString')); // false
In this example, we call the
hasOwnProperty()
method on
myObject
to check if it has the properties
a
and
toString
. The method returns
true
for
a
because it is an own property of the object. However, it returns
false
for
toString
because it is not an own property of the object, but rather it is inherited from the prototype chain.

Creating an Object Constructor

To create an object constructor, we use a function. Here's an example:

function Animal(name, age, breed) {
  const obj = {};
  obj.name = name;
  obj.age = age;
  obj.breed = breed;
  return obj;
}
This function takes in three arguments:
name
,
age
, and
breed
. We then create an object
obj
and set its properties to the values passed in as arguments. Finally, we return the object.

Instantiating New Objects with Properties

To instantiate a new object with properties, we can use the
new
keyword in conjunction with our constructor function. Here's an example:
const dogOne = new Animal('Spike', 3, 'Labrador');
This creates a new object
dogOne
with properties
name
,
age
, and
breed
set to 'Spike', 3, and 'Labrador', respectively.

Adding Methods to the Prototype Object

To add methods to our object constructor, we can use the
prototype
property. Here's an example:
Animal.prototype.sayBreed = function() {
  console.log(`My breed is ${this.breed}`);
};
This adds a method
sayBreed
to the
Animal
prototype, which we can then use on any object created by the
Animal
constructor.

Constructor Functions & Inheritance

When creating Constructor Functions, it is often necessary to create more specialized objects that inherit from a more generic parent object. This is where Constructor Functions that invoke another Constructor Function come in. This pattern allows us to create a more specialized Constructor Function that inherits from a more generic parent Constructor Function.

To create a Constructor Function that invokes another Constructor Function, we use the
call()
method. The
call()
method allows us to call a function that is defined elsewhere in the current context. In the context of a Constructor Function,
this
refers to the new object being created. We can pass
this
as the first argument to the
call()
method, which will allow the new object to inherit properties and methods from the parent object.

Here's an example of creating a more specialized Constructor Function that invokes another Constructor Function:

function Animal(name, age) {
  this.name = name;
  this.age = age;
}

Animal.prototype.makeNoise = function() {
  console.log('Generic animal noise');
}

function Dog(name, age, breed) {
  Animal.call(this, name, age);
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log('Bark bark woof');
}

const myDog = new Dog('Rufus', 3, 'Labrador');
myDog.makeNoise(); // Generic animal noise
myDog.bark(); // Bark bark woof
In this example, we have a parent Constructor Function
Animal
, which takes in
name
and
age
as arguments and creates a new object with those properties. It also has a
makeNoise
method, which is inherited by any child Constructor Functions.
We then have a more specialized Constructor Function
Dog
, which takes in
name
,
age
, and
breed
as arguments. We use the
call()
method to call the
Animal
Constructor Function, passing
this
as the first argument to inherit the
name
and
age
properties. We then set the
breed
property on the new object.
We then use
Object.create()
to create a new object that inherits from
Animal.prototype
, which allows the new
Dog
object to inherit the
makeNoise
method. We set the
constructor
property of the
Dog.prototype
object to
Dog
so that it points to the
Dog
Constructor Function.
Finally, we add a new
bark
method to the
Dog.prototype
object, which is a specialized method for
Dog
objects.
When we create a new
Dog
object using the
new
keyword, we can see that it inherits the properties and methods from the parent
Animal
object, as well as the specialized
bark
method.

Javascript Classes

Declaring a class

In JavaScript, a class is a type of function, but instead of using the
function
keyword, we use the
class
keyword to declare a class.
class Person {
  // class methods
}

Constructor method

The
constructor
method is a special method used for creating and initializing an object created with a class. It has to be called
constructor
and it can accept parameters.
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

Class Declaration vs. Class Expression

We can declare a class using two ways:

Class Declaration

We can use the class declaration to declare a class. It is a class statement that defines a new class with a given name using "class" keyword.

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

Class Expression

We can also use a class expression to define a class. It is similar to function expression syntax.

const Person = class {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
};

Methods in classes

Methods are functions that are defined on a class. They can be used to add behavior to an object created from a class. Here's an example of adding a
greetings
method to a
Person
class:
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  greetings() {
    console.log("Classes are cool.");
  }
}

Inheritance and super keyword

Classes can also inherit properties and methods from another class using the
extends
keyword. The
super
keyword is used to call the parent's constructor and to call the parent's methods.
class Employee extends Person {
  constructor(name, age, position) {
    super(name, age);
    this.position = position;
  }
}
In the above example, the
Employee
class extends the
Person
class and it has a
position
property. The
super
keyword is used to call the
Person
class's constructor, passing the
name
and
age
parameters to it.

What are static methods?

Static methods are methods that belong to a class itself, rather than an instance of the class. This means that they are called on the class itself, rather than on an object created from the class.

Defining a static method

To define a static method, we use the
static
keyword. We then define the method as we would any other method.
class Customer {
  static sayHi() {
    console.log('Hi with a smiley face');
  }
}

Calling a static method

To call a static method, we use the class name, followed by the method name.

Customer.sayHi();

Inheriting static methods

Static methods are inherited just like any other property of a class. For example:

class Person {
  static sayHey() {
    console.log('Hey');
  }
}

class Customer extends Person {}

Customer.sayHey(); // Output: 'Hey'

Use cases for static methods

Static methods are useful when we want to define a method that belongs to a class itself, rather than to an instance of the class. For example, we might use a static method when we want to perform some kind of comparison or logic on multiple instances of a class. We might also use a static method when we want to group together related functionality in a class.