JavaScript: A Journey to the valley of ES6

Data Types, Event Loop, Try…Catch, Coding Style, Comment, Caching, Arrow Function, Block Binding, Spread Operator, Function Default Parameter

Muhammad Rabiul Alam
9 min readMay 6, 2021

--

Data Types

JavaScript has total nine types of data or you may say values in two major categories. The primitive types and the Objects and Functions. Primitive types are values which we can use only not modify them. On the other hand, we can modify Objects and Functions as we want, anyway, anytime.

Primitive Types

● Undefined​ (undefined), used for unintentionally missing values.
● Null​ (null), used for intentionally missing values.
● Booleans​ (true and false), used for logical operations.
● Numbers​ (-100, 3.14, and others), used for math calculations.
● Strings​ (“hello”, “something”, and others), used for text.
● Symbols​ (uncommon), used to hide implementation details.
● BigInts​ (uncommon and new), used for math on big numbers.

Objects and Functions

● Objects​ ({} and others), used to group related data and code.
● Functions​ (x => x * 2 and others), used to refer to code.

Anything else than those above types falls into the Objects Category.

Event Loop

JavaScript is an event driven, single threaded language. Event driven programming is a programming paradigm in which program flow is determined by events. Events are either user activity (e.g. a button click, etc) or browser activity (e.g. a web page finished loading, etc). When an event is detected, some actions to be done are executed. We may call those actions waiting for an event to happen the call back functions. JavaScript is a single threaded language, which means in JavaScript only a single line of code is executed at a time during the runtime, no possibility of parallel execution of multiple lines of code. To understand the event loop in JS, we must know what is an event and what single threaded means and we have already known that above in brief. So, lets get to the point now, what is the so called Event Loop at all? Lets analyse the picture below in short:

Fig.1: Event Loop Illustration

The Call Stack the function call stack that keeps track of all the functions called in runtime. Heap is large block of mostly unstructured memory to store the objects. Call-back Queue is a list of messages to processed used by JS runtime. Messages in the queue are created whenever an event occurs and wait to be processed in the event loop. When the JS runtime starts processing the messages it takes the oldest one from the queue and removes it from the queue. Then, the call-back function associated with the message is placed onto the call stack and processed completely before any other message to be processed. The call-stack is cleared after processing one message and then another message is dequeued from the call-back queue for processing and goes on this way till there’s a single message in the queue. This cycle is called the event loop and this how JavaScript manages its events.

Error handling with “try…catch…finally”

try…catch allows to try a block of code and catch the errors those happens in the runtime. If a known error is caught, an error message could be thrown and a message could be rethrown if the error is unknown. finally, a block of code could always be executed irrespective of the try…catch outcome for finalizing the process we started.

let json = '{ "age": 30 }'; // incomplete data 
try {
// try to execute the code
let user = JSON.parse(json);
if (!user.name) {
throw new SyntaxError("Incomplete data: no name");
}
name = 'rabi'; // unexpected error <-- forgot to put "let" before name variable, this error will be rethrown
alert( user.name );
}
catch (err) {
// handle errors
if (err instanceof SyntaxError) {
alert( "JSON Error: " + err.message );
}
else {
throw err; // rethrow (*)
}
}
finally {
// execute always
alert( 'finally' );
}

Coding Style

Take a complex problem and code it down to a clean and human readable program, and this should be the habit and ability of every good programmer.

Curly braces

For shorter and single line do not use any curly brace, use them only for multiple lines. A single space before and after the braces should be used.

Fig.2: Good Coding Style

Line Length

Ling horizontal lines should be broken down to shorter lines with 80 to 120 characters maximum.

// backtick quotes ` allow to split the string into multiple lines let str = `   
ECMA International's TC39 is a group of JavaScript developers,
implementers, academics, etc collaborating with the community
to maintain and evolve the definition of JavaScript.
`;
// for 'if' statements
if ( id === 123 &&
moonPhase === 'Waning Gibbous' &&
zodiacSign === 'Libra' ) {
letTheSorceryBegin();
}

Spaces & Indents

Use a single space after every keyword, before and after each operators. Use 2 or 4 space horizontal indents. Use empty line to split code into logical blocks and add extra lines where necessary. There should be a vertical indentation after at most nine lines.

function pow(x, n) {   
let result = 1;
// <--
for (let i = 0; i < n; i++) {
result *= x;
}
// <-- return result;
}

Semicolons

Semicolons should be written after each line of statement.

Nesting Level

Avoid multiple level of nesting.

Bad Practice

function pow(x, n) {   
if (n < 0) {
alert("Negative 'n' not supported");
} else {
let result = 1;
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
}

Good Practice

function pow(x, n) {   
if (n < 0) {
alert("Negative 'n' not supported");
return;
}

let result = 1;

for (let i = 0; i < n; i++) {
result *= x;
}

return result;
}

Function Placement

First write the code that use the functions, then code the functions.

// the code which uses the functions 
let elem = createElement();
setHandler(elem);
walkAround();
// --- helper functions ---
function createElement() {
...
}

Comments

Comments are used to describe how and why the code works. Comments can be single-line: starting with // and multiline: /* ... */. Explanatory comments are usually bad. Good comments provide a high-level overview of components, how they interact, what’s the control flow in various situations… In short — the bird’s eye view of the code.

/**  
* Returns x raised to the n-th power.
*
* @param {number} x The number to raise.
* @param {number} n The power, must be a natural number.
* @return {number} x raised to the n-th power.
*/
function pow(x, n) { ... }

Caching

Caching is the way of storing commonly used data in several places and then serving that data to requesters from the common data store, rather than generating new content each time it is requested.

Client Caching

Store commonly referenced data locally for a time with a given expiry date from the last time it was requested, allowing the cache to be dynamic. This reduces the data cost for the client and also frees up time on the server side.

Server Caching

Server caching helps limit the cost incurred by the server and its underlying systems. Many requests made by clients can either be responded to using the same data, or responded to using parts of the same requests made by others.

To the API, this request looks like this:

  1. The client request is received by the server.
  2. The server checks for a local copy of the file requested. Though, this check has a cost, it is still extremely lower than the cost of computing a massive database check or generating content.
  3. If the local resource exists, the server responds with its resource URI. Otherwise, the request is processed normally.

Hybrid Caching

Use both types of caching to reduce the data cost on both sides.

From the API perspective, the flow would follow as such:

  1. A client makes a request
  2. It first checks for a local copy. If the copy doesn’t exist, it contacts the server with a request for this content.
  3. On the server side, the server will then check for its own local copy,
  4. If a copy exists, it will serve it. Or, it will generate a new one if the copy does not exist.

Caching has some serious implications when it comes to privacy and security as cached content may be slow to change and the damage might already be done. Caching is a balancing game, and improper balancing can cost largely in terms of both performance and money. The balancing should be done what works best for the situation.

Block Bindings

In JS variable declaration with the var keyword is hoisted to the top of the function during the runtime. Which is confusing to the developers sometimes, as the variable is accessible from outside of the block it is initialized and may cause bugs. And also the makes the controlling a variable’s lifecycle complex. But, ES6 introduces the block level declaration similar to other C based languages to bring that same flexibility (and uniformity) to JavaScript. The ‘let’ and ‘const’ keywords are introduced for the variable with dynamic values to be declared with ‘let’ and the constants to be declared with ‘const’ keywords. And, reduces the place of confusion with the ‘var’ and hoisting.

Spread Operator

One of the powerful feature released with es6 is the spread operator denoted with three dots {…}. It makes the manipulation of Array, String and Object much much more easier and comfortable to its developers by allowing expansion in places where zero or more arguments (for function calls) or elements (for array literals) or key-value pairs (for object literals) are expected.

Syntax

For function calls:

// pass all elements of iterableObj as arguments to function myFuncmyFunc(...iterableObj);

For array literals or strings:

// combine two arrays by inserting all elements from iterableObj[...iterableObj, '4', 'five', 6];

For object literals (new in ECMAScript 2018):

// pass all key:value pairs from an objectlet objClone = { ...obj };

Arrow functions

Arrow functions allow us to write shorter function syntax and this is another great es6 feature I love most. If the function has only one statement that returns a value, the brackets and the return keyword could also be removed.

Before:

hello = function() {
return “Hello World!”;
}

With Arrow Function:

hello = () => {
return “Hello World!”;
}

Arrow Function With Parameters and a single statement:

hello = (val) => “Hello “ + val;

Even the parentheses around the parameter can also be removed if there is only one parameter.

Function Default Parameter

Functions with Default Parameter Values is also new to ES6. Default function parameters allow named parameters to be initialized with default values if no value or undefined is passed.

function getInfo (name, year = 2018, color = 'blue') {   
// function body here...
}

Without this kind of check and safeguard in place, any uninitiated parameters would default to a value of undefined, which is usually not desired.

References

--

--

Muhammad Rabiul Alam

I am a Front-End Developer. I love to work with JavaScript, ReactJS, NodeJS, React Native and other front-end and/or JavaScript based technologies.