JS 101: Classes in Plain JavaScript
Tags: javascript, webdev, programming, tutorial
Published: 2020-11-30 10:47:36

[In my last article](https://dev.to/krisguzman_dev/js-101-implementing-the-new-keyword-5h1j), I talked about how to implement the `new` keyword from scratch. Now we are going to take it a step further and re-implement a basic version of the somewhat controversial class syntax introduced in JavaScript. Why is it controversial, you might ask?

```
class Rectangle {
  constructor(width, height) {
    this.width = width
    this.height = height
  }
  size() {
    console.log(`${this.width} x ${this.height}`)
  }
}
class Square extends Rectangle {
  constructor(scale, width, height) {
    super(width, height)
    this.scale = scale
  }
  size() {
  	console.log(`${this.width}px wide and ${this.height}px tall`)
  }
}
```
Looks pretty straightforward, right? I agree. However, there is one thing wrong with all of this...

### The Problem with JS Classes
The problem with classes is that... well... JavaScript doesn't have classes! It's a language based on  [prototypal inheritance](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain) , not classical inheritance.

It's like trying to put a dress on a bear. Sure it will look less scary, but it doesn't change what's under the dress. 

Don't be the guy or gal who uses classes thinking it works exactly like classes in Java or Python. Impress your hiring interviewer by understanding what's underneath! JavaScript classes I mean, not the bear with the dress.

### Steps to implement classes in JavaScript
Let's implement our example above in plain old JavaScript without the syntax sugar. Here's what we will have to do:
1. Create our `Rectangle` constructor function with `width`, `height`, and `size` attached to `this`
2. Create a second constructor function called `Square`, which will call our `Rectangle` function to initialize parameters (this is the `super(...params)` line). It will also have a new member called `scale`
3. Make sure our `Square` "class" inherits the prototype of `Rectangle` as well by copying the prototype of `Rectangle`
4. Copying the prototype of `Rectangle` means `Square.prototype.constructor` will be `Rectangle.prototype.constructor` rather than the Square constructor we defined, so we must redefine the property.

Does all that make absolutely zero sense? No problem, let's go step by step with code.

### Step 1
*Create our `Rectangle` constructor function with `petName` and `bark` attached to `this`*

Easy enough:
```
function Rectangle() {
 this.width = width
 this.height = height
 this.size = function() {
  console.log(`${this.width} x ${this.height}`)
 }
}
```
Nothing new here, just a standard constructor function as we would do pre-class syntax days.

### Step 2 
*Create a second constructor function called `Square`, which will call our `Rectangle` function to initialize parameters (this is the `super(...params)` line). *

```
function Square(scale, width, height) {
 Rectangle.call(this, width, height)
 this.scale = scale
}
```
This is where the confusion often begins. Why did we call `Rectangle.call(this, width, height)`? This basically says "call our Rectangle constructor function, but use the `this` parameter we pass in rather than the one in Rectangle. Also, pass in any other parameters expected by Rectangle." This is essentially the same is running `super(width, height)`.

Our other member, `scale`, is exclusive to our Square class, so we assign it after we run the parent constructor function.
### Step 3
*Make sure our `Square` "class" inherits the prototype of `Rectangle` as well by copying the prototype of `Rectangle`*

```
Square.prototype = Object.create(Rectangle.prototype)

```
What the hell is this? Great question!

In plain english, this basically says "I want the prototype of Square to be a copy of the prototype of Rectangle".

Okay, so you may be wondering now, **why**  do we want to do this? Take the following example:

```
Rectangle.prototype.getArea = function() {
  return this.width * this.height
}
```

If we define the `getArea` method on the prototype of `Rectangle`, but forget to do step #3, our `Square` won't have access to this method. Why would we define methods on prototypes? You'll have to follow me and wait for the next article to explain that one!

### Step 4
*Copying the prototype of `Rectangle` means `Square.prototype.constructor` will be `Rectangle.prototype.constructor` rather than the Square constructor we defined, so we must redefine the property.*

Our last step is an odd one, but basically if ran:
```
Square.prototype.constructor.name === Rectangle.prototype.constructor.name
```
we would see that they are equal, which isn't what we want. We want our `Square` to point to the `Square` constructor function, but because we literally copied the whole `Rectangle` prototype, we lost that connection.

So let's fix that:
```
Object.defineProperty(Square.prototype, 'constructor', {
 value: Rectangle,
 enumerable: false, // prevents this property from showing up for-in loop statements
})
```

### Step 5: Profit
Phew! That wasn't super straightforward. Here is our final implementation:

```
function Rectangle() {
 this.width = width
 this.height = height
 this.size = function() {
  console.log(`${this.width} x ${this.height}`)
 }
}

function Square(scale, width, height) {
 Rectangle.call(this, width, height)
 this.scale = scale
}

Square.prototype = Object.create(Rectangle.prototype)

Object.defineProperty(Square.prototype, 'constructor', {
 value: Rectangle,
 enumerable: false, 
})
```
You might be thinking, "okay... nope I'm just going to use the class syntax", which is exactly why it was introduced in the first place!

The point of this article isn't to say "hey, classes aren't real so don't use them". The point is to understand what is really happening behind the scenes so you can make the educated decision between using class syntax or functions. 

### Coming Up Next on December 2nd...

We saw how classes are implemented in plain JavaScript, but what are the pros and cons of using the class syntax? Are there performance implications? 

Follow me to find out! Or you can just google it I guess...