JavaScript vs ES6 vs TypeScript
Prerequisites: JavaScript, OOP
Convention: // is used in front of statement to show the result. /* */ is used to show a block of result inside it. /// is used in front of the statement to explain the statement. console.log() is used to output the result
OVERVIEW: In a nutshell, ES6 is a newer version of JavaScript, oh – wait, not so new, released in 2015 and after that ES7, ES8 and ES9 are also released, however, we call ES6 a modern JavaScript because it introduced some major changes and enhancement in a formal JavaScript.
Typescript is in fact ES6 and later versions + some additional features that we shall see later. We can say Typescript is a superset of the latest JavaScript. Typescript is transpiled into plain JavaScript which is the native language of browsers.
In this article, we shall discuss key differences between formal JavaScript and ES6 and then key features of Typescript vs ES6.
JAVASCRIPT VS ES6
Variable Declaration: In JavaScript, variable can be re-declared that is prone to error. For example following code snippet is perfectly fine in any scope:
var a = 25;
var a = 45; ///variable re-declared without error
Whereas in ES6, instead of using 'var', two other reserve words are introduced for a variable declaration that are 'let' and 'const'. 'const' is used for variables having a fixed value that will not change at any stage of the program. If you try to change the value of a variable declared with 'const', it would generate an error. You can reassign a value to a variable declared with 'let'. You cannot re-declare variable declared with either 'const' or 'let'. Doing so would generate an error as in the following code snippet:
let x = 25;
let x = 45; //Uncaught SyntaxError: Identifier 'a' has already been declared
Block-level Scope: In JavaScript, there is global scope and local scope, however, there is no block level scope. Therefore, following code snippet is perfectly fine in JavaScript:
var veg = ['Turnip', 'Cauliflower', 'Cabbage']
for (var i = 0; i < veg.length; i++) {
console.log(veg[i]);
}
console.log(i); //3
Variable 'i' shall be available outside 'for block' in above code. Whereas in ES6, block level scope is also introduced. If we write above code snippet as given below, it would generate an error:
let veg = ['Turnip', 'Cauliflower', 'Cabbage']
for (let i = 0; i < veg.length; i++) {
console.log(veg[i]);
/*
Turnip
Cauliflower
Cabbage
*/
}
console.log(i); //Uncaught ReferenceError: i is not defined
Remind you if the local variable is instantiated but not declared, it would make the variable scope global. In this case, it is used, not instantiated; hence, generates an error.
Concatenation: In JavaScript, we can concatenate two strings by using + symbol as in the following example.
var fname = "Adeel";
var lname = "Rauf";
var myName = "My name is " + fname + " " + lname;
console.log(myName); //My name is Adeel Rauf
There is no easy way to insert a double quote in a string enclosed in double quotes. We were advised to enclose the string in a single quote if we need to use a double quote somewhere inside the string because JavaScript accepts strings either way enclosed in single or double quotes. However, if we need to write a name inside double quote in above example, it wouldn't leave life easier as shown in the following example:
var myName = "My name is " + "\"" + fname +" " + lname + "\"";
console.log(myName); //My name is "Adee Rauf"
In ES6, concatenation is nothing but a breeze. You need to wrap the string in the backtick mark instead of single or double quotes. You can not only use single or double quote inside string but also use the variable directly anywhere required start with $ wrapped in curly braces as in the following example:
const city = "Sialkot";
let msg = `"I belong to ${city} city and my name is "${fname} ${lname}"`;
console.log(msg); //I belong to Sialkot city and my name is "Adeel Rauf"
You can also concatenate a string or perform an arithmetic operation on numbers inside curly braces.
const msg2 = `I belong to ${city + ' a cool'} city and my name is "${fname} ${lname}"`;
console.log(msg2); //I belong to Sialkot a cool city and my name is "Adeel Rauf"
String wrapped in backticks is known as Template literal and it allows you multi-line string as well.
Object Literal: Object Literal is an object wrapped in curly braces in which properties are declared in key-value pairs. In formal JavaScript, we can declare an object and get the value of the property as follows:
var car = {
??make: "Suzuki",
??Model: "Alto",
??Year: 2019
}
var mycar = car;
console.log(mycar.make); //Suzuki
In ES6, you can play directly with values as given below:
let lapi = {
??company: `lenovo`,
??model: `Thinkpad`,
??price: 2500
}
let {company, model} = lapi;
console.log(company); //lenovo
In formal JavaScript, we can write a function that return object literal as follows:
function objltr(book, lan, author) {
??return {
????book: book,
????lan: lan,
????author: author
??}
}
var myobj = objltr("Bal-e-Jibreel", "Urdu", "Iqbal");
console.log(myobj.book);
If property and function parameters are the same as in the above example, we can write the above code in ES6 way as follows:
function objltr(book, lan, author) {
??return {
????lan,
????book,
????author
??}
}
let {lan, author, book} = objltr("Bal-e-Jibreel", "Urdu", "Iqbal");
console.log(book); //Bal-e-Jibreel
Hence, no need to assign the property a parameter of a function as a key when the property name is the same as a function parameter. Also, you might have noticed that order of properties in function and, the order and number of variables in curly braces don't matter.
Functions: In JavaScript, old ways of writing a function are as follows:
function myFunc() {
console.log("This is one way of writing function in old JavaScript");
}
var func = function() {
console.log("This is another way of writing function in old JavaScript");
}
We call them formally as follows:
myFunc(); ///This format is not hoisted
func(); ///This is variable scope and is hoisted
In ES6, we can write function as follows:
const newFunc1 = () => { ///'function' reserve word is dropped and parentheses is used for parameters
console.log(`This is ES6 way of writing function`);
}
newFunc1(); //This is ES6 way of writing function
This syntax is termed as a fat arrow or simply an arrow function. If there is only one statement in the function body as in the above example, we can further simplify it by removing curly braces as follows:
const newFunc2 = () => console.log(`This is ES6 way of writing function without curly braces`);
newFunc2(); //This is ES6 way of writing function without curly braces
Now, what about if a function has parameters? If there is only one parameter, we can even remove parentheses as in the following example:
const newFunc3 = param1 => console.log(param1);
newFunc3(`param value`); //This is ES6 way of writing function with a param
However, if there are more than one parameters and function body contain more than one code statements, both parentheses and curly braces shall be used in arrow function as follows:
const newFunc4 = (param1, param2, param3) => {
console.log(`I'm ${param1} from ${param2}`);
console.log(`I'm working as a ${param3});
}
newFunc4(`Adeel`, `Sialkot`,`Frontend Developer`);
/*
I'm Adeel from Sialkot
I'm working as a Frontend Developer
*/
Therefore, keep in mind, parentheses can be quitted when there is only one parameter. In case of no parameter or more than one parameter, parentheses must be used. Similarly, curly braces can be quitted only in case of a single statement in the function body.
There is another major difference between old JavaScript and ES6, this is about scope of keyword 'this' in an object. In old JavaScript, consider the following case:
var myvar = {
??myname: 'Adeel Rauf',
??mycity: 'Sialkot',
??message: function() {
????var that = this;
????console.log("My name is " + this.myname);
????var profession = function() {
??????console.log('I am frontend developer from ' + that.mycity);
????}
????profession();
??}
}
myvar.message(); //I am frontend developer from Sialkot
Explanation: Object properties can be accessed inside a function by using 'this' keyword. However, if the nested function is used, you need to put the keyword 'this' equal to some other keyword in the parent function as we used 'that' in the above example. Then 'that' shall refer to object properties. If we use the arrow functions, those are smart enough to understand 'this' keyword would refer to object, hence properties can be accessed directly in nested function by using 'this' keyword.
领英推è
Above example can be written in ES6 as follows:
const myvar2 = {
??myname: 'Adeel Rauf',
??mycity: 'Sialkot',
??message: function() {
????console.log("My name is " + this.myname);
????const profession = () => {
??????console.log(`I am frontend developer from ${this.mycity}`);
????}
????profession();
??}
)}
myvar2.message(); //I am frontend developer from Sialkot
Default Parameters: In old JavaScript, we assign default parameters as follows:
var address = function(city, area, streetNo){
var x = city || 'Sialkot';
var y = area || 'Kotli';
var z = streetNo || 7;
console.log('My address is ' + x + ' ' + y + ' ' + 'street no ' + z);
}
address(); //My address is: Sialkot Kotli street no 7
In ES6, default value of parameters can be given while parameters declaration as given in the following example:
const address2 = function(city = `Sialkot`, area = `Kotli`, streetNo = 7){
console.log(`My address is: ${city} ${area} street no ${streetNo}`);
}
address2(); //My address is: Sialkot Kotli street no 7
Let's have a quick look at some features of ES5 applicable on arrays by using ES6 syntax of arrow functions by considering the following array:
const prime = [2, 3, 5, 7, 11, 13, 17, 23, 29];
forEach(): This method loops through arrays as given in the following example:
const p = prime.forEach(n => {console.log(n)});
/*
2
3
5
7
11
13
17
19
23
*/
If we like to find index of each item, we can write as follows:
prime.forEach((n, index) => console.log(`index of prime number ${n} is ${index}`));
/*
index of prime number 2 is 0
index of prime number 3 is 1
index of prime number 5 is 2
index of prime number 7 is 3
index of prime number 11 is 4
index of prime number 13 is 5
index of prime number 17 is 6
index of prime number 19 is 7
index of prime number 23 is 8
*/
If we try to find value of const p, we shall get undefined, because forEach() method do not return any value.
console.log(p); //undefined
map(): This method is used when we need to modify values of an existing array as in the following example:
const prime1 = prime.map(n => n + 1);
console.log(prime1); //[3, 4, 6, 8, 12, 14, 18, 24, 30]
You can use forEach() and map() interchangeably, however, map() allocate space in memory and save return value in the form of array. On the other hand, forEach do not return any value.
filter(): This method is used to return specific value/values as array type from array as given in the following example:
const even = prime1.filter(n => n !== 3);
console.log(even); //[4, 6, 8, 12, 14, 18, 24, 30]
reduce(): This method executes the function on each value of array from left to right and reduces it to a single value. Two parameters are required for this method, the first parameter stores the result and the second parameter represents each element of an array. The following example adds all elements of an array:
const primeSum = prime.reduce((n, m) => n + m);
console.log(primeSum); //110
find(): This method is new in ES6. It executes function on each value of array from left to right and return the first element that satisfy the criteria given in the function, otherwise returns undefined. Example is given below:
const myprime = prime.find(n => n > 20);
console.log(myprime); //23
OOP: You might be surprised by this statement that the concept of OOP isn't new in ES6. It was existing in old JavaScript, however, the process was a bit complicated, prone to errors, and also was different in structure than well-known languages like Java, php and C#. In old JavaScript, we can create 'object constructor function' or simply 'contructor function' that serve as class by which we can create objects as given in the following example:
function Season(winter, summer){
this.winter = winter;
this.summer = summer;
}
var peakMonths = new Season("Dec", "Jun");
console.log(peakMonths); //Season {winter: "Dec", summer: "Jun"}
You can add properties and methods in specific object as follows:
peakMonths.spring = "March";
However, you cannot add properties and methods in the constructor function this way. Object constructor function inherit properties and methods from 'prototype' and those shall be available to all objects created from that constructor function as given in the following example:
Season.prototype.rainy = "August";
Season.prototype.cricket = function() {
console.log("Cricket isn't linked with season but time");
}
console.log(peakMonths.rainy); //August
peakMonths.cricket(); //Cricket isn't linked with season but time
Now, what if you want to have another object with all properties of Season and some additional properties? You can do it as follows:
function AllSeason(winter, spring, summer, autumn) {
Season.call(this, winter, summer);
this.spring = spring;
this.autumn = autumn;
}
This is how properties of one object can be inherited by another object. In the above example, properties declared outside body of constructor function can not be accessed by extended constructor function unless prototype of parent constructor function is assigned as given in the following example:
AllSeason.prototype = Object.create(Season.prototype);
var peakDays = new AllSeason("22 December", "15 March", "21 June", "15 September");
peakDays.cricket(); //Cricket isn't linked with season but time
This is how inheritance work in ES5. If it seems complicated, let us talk about ES6. OOP is pretty straightforward in ES6 just like common programming languages like php, C# or Java. We create a class and create objects from class as given in the following example:
class Children {
constructor(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
behav() {
return `${this.name} is naughty`;
}
}
const mychild = new Children('Talha', 2, 'boy');
console.log(mychild); //Children {name: "Talha", age: 2, gender: "boy"}
If we want to create another object that posses all properties of parent class and some additional properties, we can do that as follows:
class ChildInfo extends Children {
constructor(name, age, gender, weight, height) {
super(name, age, gender);
this.weight = weight;
this.height = height;
}
behav(hairColor)?{
????return?`Weight?of?${this.name}?is?${this.weight}?and?hair?color?is?${hairColor}`;
}
}
const newborn = new ChildInfo('Sarah', 0, 'girl', '3kg', '18"');
console.log(newborn); //ChildInfo {name: "Sarah", age: 0, gender: "girl", weight: "3kg", height: "18""}
console.log(newborn.behav('black')); //Weight of Sarah is 3kg and hair color is black
console.log(mychild.behav()); //Talha is naughty
The last two lines above look like an example of overloading at first glance, however, this is an example of overriding in javascript. Function in the child class with the same name as of parent function overrides parent function.
ES6 vs TYPESCRIPT
Logically speaking, TypeScript can be assumed as a syntactic sugar on top of JavaScript. The reason why TypeScript transpile into JavaScript just like ES6 transpile to formal JavaScript. This is why, any code written in JavaScript works fine in TypeScript. However, there are some additional features available in TypeScript that help us to safely conclude TypeScript is a superset of JavaScript. If we compare both languages, we find:
- TypeScript minimizes the chances of runtime errors by highlighting errors at compilation time during the time of development, whereas JavaScript finds errors only at runtime.
- TypeScript supports strongly-typed or static typing optionally, whereas this option is not available in JavaScript.
- TypeScript support Interfaces whereas JavaScript doesn't. An Interface is a strongly-typed prescribed syntax that an object or class must follow. Interface in TypeScript doesn't transpile into JavaScript.
- TypeScript takes a longer time to run in browsers because it transpile first to JavaScript.
- TypeScript supports Enum data type whereas JavaScript doesn't.
That's all for now, if you have any questions or suggestions or corrections, please let me know.
Adeel Rauf