DEV Community

loading...

Classes as an Organizational Tool

Austin Harlow
Full Stack Software Engineer from Seattle. Always learning and trying new things.
・4 min read

As someone who is currently in the react section of my coding bootcamp, I have been trying to get a better understanding of Javascript classes recently.

Hopefully, by the end of this article you and I both have a better understanding of what Javascript classes are and how they work.

What is a Javascript Class?

A Javascript Class is really just a special type of function. Just like how you can have a function expression and a function declaration, classes also have class expressions and declarations.

Function Expression

let foo = (a, b) => console.log(a + b)

foo(2, 3)

// => 5

Function Declaration

foo(2, 3)

function foo(a, b) {
   console.log(a + b)
}

//=> 5

While both methods of writing a function will return the same result, the function expression we saw will be undefined if we call it the same way that we called our function declaration. Function declarations are hoisted, which means that they are evaluated and saved before we run the line calling our function. Although this is important for our functions, it works a bit differently for classes.

Class Declaration

As promised, declaration for classes is a bit different. A class declaration is not hoisted in the same fashion as a function declaration which means that you cannot create new instances of that class before you have created it.

Brief sidebar on Hoisting

For the purposes of this blog all we need to understand about hoisting is that it will cause our function declaration to be interpreted before we call the function directly. This means that we can call a function before we declare it and still have the function call be successful.

Class Expression

let foo = class bar {
   constructor(hello, world) {
      this.hello = hello,
      this.world = world
   }
}

const baz = new foo("Hello", "World")
console.log(baz.hello)
console.log(baz.world)

//=> "Hello"
//=> "World"

Class Declaration

class fooBar {
   constructor(hello, world) {
      this.hello = hello,
      this.world = world
   }
}

const baz = new fooBar("Hello", "World")
console.log(baz.hello)
console.log(baz.world)

//=> "Hello"
//=> "World"

In this case, both our expression and declaration have to be made before we try to create new instances of these classes. However, we are able to use the class expression to reference the bar class using foo.

Why do Javascript classes matter?

Javascript classes are great for containing code. They allow us to define a class, create a constructor for that class and then write methods that modify the class. For example, if you wanted to write a function that takes two sides of a right triangle and displays the hypotenuse, you can easily incorporate that with a class.

Triangle Class

class triangle {
   constructor(a, b) {
      this.a = a,
      this.b = b
   }
   findHypotenuse() {
      return Math.sqrt((this.a**2)+(this.b**2))
   }
   get c() {
      return this.findHypotenuse()
   }
}

const foo = new triangle(3, 4)
console.log(foo.c)

//=> 5

Using the findHypotenuse function that we wrote, we are able to get the hypotenuse for a right triangle and save that value as c. By describing the getter c function we are able to call .c on our triangle to return the length of the hypotenuse.

While this may seem like a lot of work to just find the hypotenuse, this class can also be used to create additional functions that we use to interact with right triangles. In that sense it allows us to better organize our code by keeping all of the functions for our triangles in one place.

Using 'extends' to share functions between classes

The extends keyword can be used to allow child classes to inherit the structure of their parent class. In keeping with our geometric example above, we can see this displayed as a a parent 'shape' class that might have a constructor function to save and display length and width.

class shape {
   constructor(length, width) {
      this.length = length,
      this.width = width
   }
}
class triangle extends shape {
   findHypotenuse() {
      return Math.sqrt((this.length**2)+(this.width**2))
   }
   get hypotenuse() {
      return this.findHypotenuse()
   }
}
class rectangle extends shape {
   findArea() {
      return this.length * this.width
   }
   get area() {
      return this.findArea()
   }
}

const foo = new triangle(3, 4)
console.log(foo.hypotenuse)
const bar = new rectangle(4, 5)
console.log(bar.area)

//=> 5
//=> 20

In this example I was able to write our two functions for our rectangle and triangle classes that inherited the constructor from the parent shape class. As the parent class has attributes that both of the children are using, we are saved from having to create an additional constructor for each of these child classes.

This also means that as we increase the complexity of our program and add more shapes we are saving increasingly more lines of code. We can also consider that our parent class can have functions that are also passed down to the children.

References

Discussion (0)