Is JS an OOP Language?
Tags: react, javascript, beginners, oop
Published: 2020-11-06 21:06:08

**TLDR:** Yes. But as opposed to 'classical inheritance,' JS relies on _prototypal inheritance._

# Overview

This can be a very deep topic. The only reason that it's loosely relevant for this 'Pre-React' series is b/c you _might_ want to start with `class`-based components when beginning React.

Aside from that, since Object-Oriented Programming (OOP) is a deeply ingrained topic in software engineering in general, it may come up in some interviews. Some basic understanding of this topic, which is all that this article intends to provide, might be beneficial for that purpose also.

I'll focus on doing a couple of examples rather than doing too much theory. And... in the end, I'll kind of bash on OOP.

# WTH is OOP?

Object-Oriented Programming. The gist of this concept is that one creates either a class (classical inheritance - C#/Java) or a prototype (prototypal inheritance - JS). This is commonly referred to as a blueprint to describe the features and characteristics of what something is supposed to be.

For example, a 'person blueprint' might require, hair color, eye color, height, weight, etc. to adequately describe a person. Along with this, we might encompass functionality associated with a person - eating, sleeping, etc. 

So, with that, we have each and everything to 'model' a person. From there, we can pass use that 'blueprint' to model more specific people. 

For example, a 'driver' _is a_ 'person' but may include 'driving' functionality.

**OOP focuses on _inheritance._** This means that we have to classify/categorize things in terms of _is a_ relationship. A 'driver' _is a_ 'person.' A 'student driver' _is a_ 'driver', which is also a 'person.'

_Summarily, the purpose of OOP is to dynamically generate **instances** or **objects** of a specific type with 'built in' **properties** and **methods w/o having to start from scratch each and every time.**_

## Creating Instances 'On The Fly'

To consider why we might even care about OOP at all, let's just create some individual _objects_ - i.e. _instances_ - of a couple of people. We'll do 'students' and 'faculty.'

{%replit @CodeFinity/ObjectInstances %}

If you've kept up with this series, pretty much all of the code should seem pretty familiar.

`this`, in case you're wondering 🤔 is just making sure that whenever one of the _methods_ is called, it will be properly _bound to_ the correct _object literal,_ and that it will use the correct properties. Without `this` JS will error out as it will look for, for example, `name` on the _global object 🙅🏽‍♂️._

Moving on, the 🔑 observation that we make 👆🏽 is the code duplication 🙅🏽‍♂️. We need to DRY (Don't Repeat Yourself) it up. This is why we might use OOP, taking advantage of JS's _prototypal inheritance_ feature. 

After all, this would be very tedious and waste a lot of memory 🧠 if we have to make 5000 students, etc.

# Function Constructors

Although it's rare to see this in JS nowadays except in legacy code, it behooves us to grasp the nuances of _prototypal inheritance._

## `Person`

### Instance Properties

We'll create a _constructor function_ that will encapsulate the properties that all people should have.

```javascript
function Person({id, name, age} = {}) {
  this.id = id;
  this.name = name;
  this.age = age;
}
```

`function Person` - It's a convention to capitalize _function constructors._ This signifies that we should use the `new` keyword to create individual _instances_ using this particular _function constructor._ 

`({id, name, age} = {})` - We are expecting to receive a single 'configuration' _object literal,_ from which we will _destructure_ the 🔑s. `= {}` is just nice to have so that if we accidentally _invoke_ the _function_ without any _arguments,_ at least our program won't just crash out. It's meant to [simulate _named parameters_](https://exploringjs.com/impatient-js/ch_callables.html#simulating-named-parameters) from other languages.

`this` - When used in conjunction with the 'new' keyword 👇🏽,
`this` will properly instantiate the instance, ensuring that the 'individual properties' are properly bound to the 'new instance.'

### Shared Functionality

All `Person`s should be able to `greet()`.

```javascript
/ ⚠️ 'Fat arrow' syntax will NOT properly bind 'this' ❗
Person.prototype.greet = function greet() {
  return `👋🏽. My name is, ${this.name}.`;
};
```

`prototype` - this is the crux of our JS OOP's _prototypal inheritance_ model. It establishes a chain ⛓️ such that whenever we call a _method_ on an _instance,_ unless that _instance_ has its own 'special implementation' (more on this later), this 'shared prototype method' will be used instead.

Again, `this` ensures that we reference the `name` of the _instance_ that is currently using this _method._
  
### Extend `Person` to `Student` and `Faculty`

{%replit @CodeFinity/Function-Constructors %}

The crux of the inheritance - establishing that `Student`s and `Faculty`s _are_ `Person`s occurs in the following areas:

```javascript
// Inheritance
Person.call(this, { id, name, age });
```

👆🏽 Here, we are _invoking_ `call` (this is also another deep topic, along with `bind`, so we'll stick to the basics) directly on the 'parent' _constructor function._ Once again, `this` comes into play b/c we need to let `Person` know that `this` is supposed to 'bind to' a `Student` (or `Faculty`) when it's called.

The second _argument_ uses _object shorthand_ to create an _object literal argument_ that `Person` uses to do its part for `Student` or `Faculty`

**`Student` allows `Person` to _instantiate_ _some_ of its _properties,_ and it focuses on just the ones that are 'special' to it.**

```javascript
/**
  * Inheritance - 
  * Spread the 'Person' prototype as a separate reference in
  * the 'Student.prototype'.
  *
  * This means that 'Student' inherits from 'Person'
  * But, if we add more functionality to 'Student',
  * it will not affect 'Person.'
  */
Student.prototype = {...Person.prototype};
```

We also allow `Student` to inherit any/all _functionality_ encapsulated by `Person` (`greet`), in this case. Likewise, we see: `Faculty.prototype = Person.prototype;`

### Customize `rudeKid`

```javascript
rudeKid.greet = function() {
  return `I'm ${this.name}. Get bent! 🖕🏽`
}
```

Although `rudeKid` is a `Student`, which _inherits_ from a person, _rather than traversing the prototype chain ⛓️, JS sees that `rudeKid` has its own `greet` method and uses that one._ This is pretty 🆒. We can easily customize 'special functionality' for any given instance, while also _inheriting._

## `prototype`

If we search around in MDN documentation, we see many mentions of `prototype`. For example, [`Array.prototype.map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).

This means that whenever we create an _instance_ of an _array,_ and, for example, _invoke_ `map`, we are using some 'shared functionality' among all _arrays_ via `prototype.` This makes sense. We don't want to waste memory 🧠 by having all of our 'array methods' duplicated for each and every array 🙅🏽‍♂️!

{%replit @CodeFinity/DoNotDoThis %}

Even though we can 👆🏽, you **should not ever** overwrite the 'built-in' JS stuff. The example above does give some clue as to how some folks can create 'special JS libraries' that can 'expand upon' its built-in functionality. These would need to properly namespace though so that it _expands upon_ and doesn't _replace_ built-in JS functionality.

# `class`

💦 That's a lot of work 👆🏽. Fortunately, as part of ES2015/ES6, JS 'borrowed' some _syntax_ from 'classical OOP' languages such as C#/Java. 

**`class` is just _syntactic sugar 🧁._ Nothing, and I mean nothing about JS' _prototypal inheritance_ as illustrated with _function constructors 👆🏽_ changes.** 

I will emphasize it again. If you are coming from the `class` _keyword_ in other programming languages, note 🎵 that the behavior of `class` is significantly different. This is why I took time to show the 'old way' 👆🏽; hopefully it is clear that we are borrowing 'classical inheritance syntax,' but the 'under the hood' implementation is still **prototype-based.**

{%replit @CodeFinity/Class %}

Essentially, all the things work the same way, but the _syntax_ is a bit more delightful 🤓.

`super` takes the place of using `call(this`.

`extends` takes the place of `.prototype = Person` assignment.

## Anti-OOP 💧

⚠️ It's arguable that this is generally a poor design approach as I have to 'upfront' try to predict all of the different 'things' that I may need in an application, and could be severely restricted with constantly classifying what things _are (as opposed to what they 'do,' a la composition)._ 

I'll show _composition_ in the next post.