Bake A Javascript Library using Vanilla JS (Part 3)
Before you go ahead, this is a mini-series where we start from ground zero to a shippable Javascript Date Library 📅
View the previous article to be on the track! 😄
Let’s Go! 🚀
Previously —
We utilized ES Modules and utilizedimport
& export
syntax to and apply tree-shaking methods to pass functions and also utilizingpackage.json
to make our node application understand all the processes above!
Next, we learn to utilize Prototypal Inheritance & use techniques like chaining & immutability to make our library more robust! 🚀
Content
- Constructor + Prototypal Inheritence
- Chaining
- Immutability
Constructor + Prototypal Inheritance
If someone is coming from OOP(s) (Object Oriented Programming) concept, one would understand how Classes work. You create an instance of the class and utilize the inner methods.
“class” keyword was added to JavaScript since ES6 (ECMAScript 2015)
JavaScript is not an object-oriented language, it was not designed to be one. Theclass
keyword is instead a syntactical sugar & internally it utilizes Prototypal Inheritance
The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects.
So let’s convert our existing import & export
structure to a Prototypal approach!
In our time.js
we shall introduce a constructor function named Time
/*time.js*/function Time(date) {
this.date = new Date(date)
}...rest of the code...
As you can see this is a constructor
function which accepts any date
parameter, which later utilizes this
, which refers to the current instantiation.
What’s happening above? -
- We create a
constructor
function. - It accepts a parameter named
date
. - The date is passed to create a new JS Date object.
- which is stored in
this.date
, wherethis
refers to the current instance.
Phew, that's a lot of change, or is it? 😅 Next! We need to use Prototypal Inheritance and modify our existing methods so that our Time
constructor has those methods attached.
/* time.js */
...rest of the code...Time.prototype.getDay = function () {
let days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; return days[this.date.getDay()];
}Time.prototype.getMonth = function() {
let months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; return months[this.date.getMonth()];
}Time.prototype.addDays = function (n) {
this.date.setDate(this.date.getDate() + n);
}export default Time
What’s happening above? -
- Methods like
getDay(), getMonth()
&addDays()
are added to the prototype chain ofTime
constructor. - Finally, we export this at the end of the file using
export.
- Default is used to export only one value from a file which can be a class, function, or object, which in our case is
Time.
- I would write a detailed article on Prototypal Inheritance.
- It’s a very important JS topic, as the JS we know today is built entirely on this. 🚨
Finally, we need to modify our index.js to accommodate the new prototypal changes.
/*index.js*/import Time from "./time.js"let Christmas = new Time('December 25, 2021');let day = Christmas.getDay(Christmas);
let month = Christmas.getMonth(Christmas);
console.log(day, month);Christmas.addDays(7);
console.log(Christmas);
What’s happening above? -
- We use
import
and import theTime
constructor in our file. - We use
Time
constructor to create a newTime
instance. 🚧 - We refer to prototypes by using instance.prototype syntax.
If everything is done right, on refreshing the browser you should see this!
Chaining ⛓
Pat yourself in the back! You just created a very sleek, not-yet-ready, but working prototype (no pun intended) 😅. Let’s add some flavor to it!
What does it mean by Chaining?
Method Chaining is a programming strategy that simplifies and embellishes your code. It is a mechanism of calling a method on another method of the same object.
Our library doesn’t support this as of now, how does it work though?
For a method to be chainable, it needs to return its context for the next method to utilize it.
So this works only in the existing methods that DO NOT return anything already.
So let’s make add 2 new methods called addMonths
& addYears to our time.js
file.
/*time.js*/
...rest of the code...Time.prototype.addMonths = function(n) {
this.date.setMonth(this.date.getMonth() + n);
return this
}Time.prototype.addYears = function(n) {
this.date.setFullYear(this.date.getFullYear() + n);
return this
}...rest of the code...
What’s happening above? -
- These methods modify our existing
this.date
variable. - But we also return
this
, this keyword holds the entire instance context (variable, prototypes)
Let’s put it to action 🚀, modify our index.js
/*index.js*/...rest of the code....Christmas.addDays(1).addMonths(1).addYears(1)
console.log(Christmas)...rest of the code...
What’s happening above? -
- We are chaining three methods
addDays()
,addMonths()
&addYears()
- Suppose the current date object is instantiated with
December 25, 2021
. - We are adding 1 Day, 1 Month, and 1 Year to it.
- What would be the output? Let’s check it out below 🔍.
As you can see —
- 1 day makes it December 26, 2021.
- 1 month makes it January 26. 2022.
- 1 year makes it January 26, 2023. ⏲
Chaining is very easy, seriously!
Immutability
Okay, take a breath soldier, you made it through the battlefields of Javascript! Finally, let’s understand the topic of Immutability.
Let’s understand it via this analogy-
A princess kisses a frog hoping it will turn into a handsome prince. The concept of immutability says that a frog will always be a frog. The immutability concept is mainly originated from functional and object-oriented programming. Whenever we want to make changes to some data (for example to an object or an array) we should get a new object back with the updated data instead of directly modifying the original one.
Until now, the way our Javascript Date Library has been designed, we are modifying the instance every time we call one of our methods, which are in turn being called through a proto chain.
For a robust library, we do expect sometimes that we don't directly modify the instance, but rather create a new instance, have it stored in another variable and take things forward ahead. This keeps the logic clean and proceeds towards achieving true Immutability.
Let’s start!
Let’s modify our time.js
and modify our chained methods -
/*time.js*/
...rest of the code...Time.prototype.addDays = function (n) {
let newDate = new Date(this.date)
newDate.setDate(this.date.getDate() + n);
return new Time(newDate)
}Time.prototype.addMonths = function(n) {
let newDate = new Date(this.date)
newDate.setMonth(newDate.getMonth() + n);
return new Time(newDate)
}Time.prototype.addYears = function(n) {
let newDate = new Date(this.date)
newDate.setFullYear(newDate.getFullYear() + n);
return new Time(newDate)
}...rest of the code...
What’s happening above? -
- We are creating a new JS Date Object every time one of the chained methods is called.
- Then the
newDate
object is used to perform the underlying action the method is supposed to do (addDay, addMonth…etc) - return the newly modified
newDate
Date object.
/*index.js*/...rest of the code...
console.log("before", Christmas)let modified = Christmas.addDays(1).addMonths(1);
console.log("after", modified, Christmas)...rest of the code....
What’s happening above? -
- We are storing the modified instance of
Christmas
in a variable namedmodified
. - To confirm we are logging twice, once with before and another comparing post-modification.
Without Immutability, it would look something like this…..
This concludes Part 3, if you have any doubts or improvements for this article please do comment, and if you liked it share a few applause 😄.
In Part 4, we shall explore adding Hooks! Ahoy 🚢 and explore more advanced topics which will bring us closer to the end goal of a Shippable Javascript Date Library!
****************************************************************
This post was inspired by — https://gomakethings.com/ , please do check out this wonderful blog based on pure Javascript.
I’m Saurav Tiru, Front End Engineer at building UI at Radius.
I would be posting articles related to Front End Engineering, Photography, and Video Editing every week!