Book Image

Learning JavaScript Data Structures and Algorithms - Second Edition

By : Loiane Groner
Book Image

Learning JavaScript Data Structures and Algorithms - Second Edition

By: Loiane Groner

Overview of this book

This book begins by covering basics of the JavaScript language and introducing ECMAScript 7, before gradually moving on to the current implementations of ECMAScript 6. You will gain an in-depth knowledge of how hash tables and set data structure functions, as well as how trees and hash maps can be used to search files in a HD or represent a database. This book is an accessible route deeper into JavaScript. Graphs being one of the most complex data structures you’ll encounter, we’ll also give you a better understanding of why and how graphs are largely used in GPS navigation systems in social networks. Toward the end of the book, you’ll discover how all the theories presented by this book can be applied in real-world solutions while working on your own computer networks and Facebook searches.
Table of Contents (18 chapters)
Learning JavaScript Data Structures and Algorithms - Second Edition
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface

ECMAScript 6 functionalities


In this topic, we will demonstrate how to use some of the new functionalities of ES6, which may be useful in the everyday JavaScript coding and which will also be useful to simplify the examples presented in the next chapters of this book. Among the functionalities, we will cover the following ones:

  • let and const

  • Template literals

  • Destructuring

  • Spread operator

  • Arrow functions using =>

  • Classes

Declaring variables with let instead of var

Until ES5, we could declare variables in any place of our code, even if we overwrote the variables declaration, as in the following code:

var framework = 'Angular'; 
var framework = 'React'; 
console.log(framework); 

The output of the preceding code is React as the last variable declared, named framework, was assigned this value. In the previous code, we had two variables with the same name; this is very dangerous and might drive the code to an incorrect output.

Other languages, such as C, Java, and C#, do no allow this behavior. With ES6, a new keyword was introduced, called let. Let is the new var keyword, meaning we can simply substitute the keyword var for let. In the following code, we have an example:

let language = 'JavaScript!'; //{1} 
let language = 'Ruby!'; // {2} - throws error 
console.log(language); 

Line {2} will throw an error because a variable named language is already declared in the same scope (line {1}). We will discuss the let and variables scope in the next topic.

Tip

The preceding code can be tested and executed at the URL https://goo.gl/he0udZ .

Variables scope with let

To understand how variables declared with let keyword work, let's use the following example (you can run the example using the URL  https://goo.gl/NbsVvg ):

let movie = 'Lord of the Rings'; //{1} 
//var movie = 'Batman v Superman'; //throws error, variable movie already declared 
 
function starWarsFan(){ 
  let movie = 'Star Wars'; //{2} 
  return movie; 
} 
 
function marvelFan(){ 
  movie = 'The Avengers'; //{3} 
  return movie; 
} 
 
function blizzardFan(){ 
  let isFan = true; 
  let phrase = 'Warcraft'; //{4} 
  console.log('Before if: ' + phrase); 
  if (isFan){ 
    let phrase = 'initial text'; //{5} 
    phrase = 'For the Horde!';   //{6} 
    console.log('Inside if: ' + phrase); 
  } 
  phrase = 'For the Alliance!';    //{7} 
  console.log('After if: ' + phrase); 
} 
 
console.log(movie); //{8} 
console.log(starWarsFan()); //{9} 
console.log(marvelFan()); //{10} 
console.log(movie);       //{11} 
blizzardFan(); //{12} 

This will be the output from the previous code:

Lord of the Rings 
Star Wars 
The Avengers 
The Avengers 
Before if: Warcraft 
Inside if: For the Horde! 
After if: For the Alliance!

Now, we will discuss the reason we got this output.

  • On line {1}, we declared a variable movie with the value Lord of the Rings, and we output its value on line {8}. This variable has global scope, as you learned in the Variable scope section of this chapter.

  • On line {9}, we executed the starWarsFan function. Inside this function, we also declared a variable named movie on line {2}. The output from this function is Star Wars because the variable from line {2} has local scope, meaning it is only valid inside this function.

  • On line {10}, we executed the marvelFan function. Inside this function, we changed the value of the movie variable (line {3}). This variable made a reference to the global variable declared on line {1}. This is why we got the output The Avengers on line {10} and also on line {11}, where we output the global variable.

  • Finally, we executed the blizzardFan function on line {12}. Inside this function, we declared a variable named phrase (line {4}) with the scope of the function. Then, on line {5}, again, we will declare a variable named phrase, but this time, this variable will have only a scope inside the if statement.

  • On line {6}, we changed the value of phrase. As we are still inside the if statement, only the variable declared on line {5} would have its value changed.

  • Then, on line {7}, we again changed the value of phrase, but as we are not inside the block of the if statement, the value of the variable declared on line {4} is changed.

Again, this scope behavior is the same as in other programming languages, such as Java or C. However, this was only introduced in JavaScript through ES6.

Constants

ES6 also introduced the keyword const. Its behavior is the same thing as the keyword let; the only difference is that a variable defined as const has a read-only value, meaning a constant value.

For example, consider the following code:

const PI = 3.141593; 
PI = 3.0; //throws error 
console.log(PI); 

When we try to assign a new value to PI or even try to redeclare it as var PI or let PI, the code will throw an error saying that PI is read only.

Tip

The preceding code can be executed at https://goo.gl/4xuWrC .

Template literals

Template literals are really nice because we can create strings without the need to concatenate the values.

For example, consider the following examples written with ES5:

var book = { 
  name: 'Learning JavaScript DataStructures and Algorithms' 
}; 
console.log('You are reading ' + book.name + '.,\n    and this is a new line\n    and so is this.');

We can improve the syntax of the previous console.log output with the following code:

console.log(`You are reading ${book.name}., 
and this is a new line 
and so is this.`);

Template literals are enclosed by backticks (`). To interpolate a variable value, we will simply set the variable value inside a dollar sign and curly braces (${}), as we did with book.name.

Template literals can also be used for multiline strings. There is no need to use \n anymore. Simply hit Enter on the keyboard to take the string to a new line, as was done with and this is a new line in the previous example.

This functionality will be very useful in our examples to simplify the output!

Tip

The preceding examples can be executed at https://goo.gl/PTqnwO .

Arrow functions

Arrow functions are a great way of simplifying the syntax of functions in ES6. Consider the following example:

var circleArea = function circleArea(r) { 
  var PI = 3.14; 
  var area = PI * r * r; 
  return area; 
}; 
console.log(circleArea(2)); 

We can simplify the syntax of the preceding code to the following code:

let circleArea = (r) => { //{1} 
  const PI = 3.14; 
  let area = PI * r * r; 
  return area; 
} 
console.log(circleArea(2)); 

The main difference is on line {1} of the example, on which we can omit the keyword function using =>.

If the function has a single statement, we can use a simpler version as well, by omitting the keyword return. Take a look at the following:

let circleArea2 = (r) => 3.14 * r * r; 
console.log(circleArea2(2)); 

Tip

The preceding examples can be executed athttps://goo.gl/CigniJ .

Default parameter values for functions

With ES6, it is also possible to define default parameter values for functions. The following is an example:

function sum (x = 1, y = 2, z = 3) { 
  return x + y + z 
}; 
console.log(sum(4,2)); //outputs 9 

As we are not passing z as a parameter, it will have value 3 by default. So, 4 + 2 + 3 == 9.

Before ES6, we would have to write the preceding function as the following code:

function sum (x, y, z) { 
  if (x === undefined) 
  x = 1; 
  if (y === undefined) 
  y = 2; 
  if (z === undefined) 
  z = 3; 
  return x + y + z; 
}; 

With ES6, we can save a few lines of code using the default parameter values functionality.

Tip

The preceding example can be executed at https://goo.gl/2MiJ59 .

Declaring the spread and rest operators

In ES5, we can turn arrays into parameters using the apply() function. ES6 has the spread operator (...) for this purpose. For example, consider the function sum we declared in the previous topic. We can execute the following code to pass the x, y, and z parameters:

var params = [3, 4, 5]; 
console.log(sum(...params)); 

The preceding code is the same as the code written in ES5, as follows:

var params = [3, 4, 5]; 
console.log(sum.apply(undefined, params)); 

The spread operator (...) can also be used as a rest parameter in functions to replace arguments. Consider the following example:

function restParamaterFunction (x, y, ...a) { 
  return (x + y) * a.length; 
} 
console.log(restParamaterFunction(1, 2, "hello", true, 7)); //outputs 9; 

The preceding code is the same as the following:

function restParamaterFunction (x, y) { 
  var a = Array.prototype.slice.call(arguments, 2); 
  return (x + y) * a.length; 
}; 

Tip

The spread operator example can be executed at https://goo.gl/8equk5 , and the rest parameter example can be executed at https://goo.gl/LaJZqU .

Enhanced object properties

ES6 introduces a concept called array destructuring, which is a way of initializing variables at once. For example, consider the following:

var [x, y] = ['a', 'b']; 

Executing the preceding code is the same as doing the following:

var x = 'a'; 
var y = 'b'; 

Array destructuring can also be performed to swap values at once without the need to create temp variables, as follows:

[x, y] = [y, x]; 

The preceding code is the same as the following one:

var temp = x; 
x = y; 
y = temp; 

This will be very useful when you learn sorting algorithms as this swap values is very common.

There is also another functionality, called property shorthand, which is another way of performing the destructuring of objects. For example, consider the following example:

var [x, y] = ['a', 'b']; 
var obj = { x, y }; 
console.log(obj); // { x: "a", y: "b" } 

The preceding code is the same as doing the following:

var x = 'a'; 
var y = 'b'; 
var obj2 = { x: x, y: y }; 
console.log(obj2); // { x: "a", y: "b" } 

The last functionality we will discuss in this topic is called the method property. This allows developers to declare functions inside objects as if they were properties. The following is an example:

var hello = { 
  name : 'abcdef', 
  printHello(){ 
  console.log('Hello'); 
  } 
} 
console.log(hello.printHello()); 

The preceding code can also be written as follows:

var hello = { 
  name: 'abcdef', 
  printHello: function printHello() { 
  console.log('Hello'); 
  } 
}; 

The three examples presented can be executed at:

Object-oriented programming with classes

ES6 also introduced a cleaner way of declaring classes. You learned that we can declare a class named Book in the Object oriented programming section this way:

function Book(title, pages, isbn){ //{1} 
  this.title = title; 
  this.pages = pages; 
  this.isbn = isbn; 
} 
Book.prototype.printTitle = function(){ 
  console.log(this.title); 
}; 

With ES6, we can simplify the syntax and use the following code:

class Book { //{2} 
  constructor (title, pages, isbn) { 
  this.title = title; 
  this.pages = pages; 
  this.isbn = isbn; 
  } 
  printIsbn(){ 
    console.log(this.isbn); 
  } 
} 

We can simply use the keyword class and declare a class with a constructor function and other functions as well—for example, the printIsbn function. The code for the class Book declared on line {1} has the same effect and output as the code declared on line {2}:

let book = new Book('title', 'pag',  'isbn'); 
console.log(book.title); //outputs the book title 
book.title = 'new title'; //update the value of the book title 
console.log(book.title); //outputs the book title 

Tip

The preceding example can be executed at  https://goo.gl/UhK1n4 .

Inheritance

As we have a new way of declaring classes, there is also a simplified syntax to use inheritance between classes. Let's take a look at an example:

class ITBook extends Book { //{1} 
  constructor (title, pages, isbn, technology) { 
    super(title, pages, isbn); //{2} 
    this.technology = technology; 
  } 
  printTechnology(){ 
    console.log(this.technology); 
  } 
} 
 
let jsBook = new ITBook('Learning JS Algorithms', '200', '1234567890', 'JavaScript'); 
console.log(jsBook.title); 
console.log(jsBook.printTechnology()); 

We can extend another class and inherit its behavior using the keyword extends (line {1}). Inside the constructor, we can also refer to the constructor superclass using the keyword super (line {2}).

Although the syntax of this new way of declaring classes in JavaScript is very similar to other programming languages such as Java and C/C++, it is good to remember that JavaScript object-oriented programming is done through a prototype.

Tip

The preceding example can be executed at  https://goo.gl/hgQvo9 .

Working with getters and setters

With the new class syntax, it is also possible to create getter and setter functions for the class attributes. Although class attributes are not private as in other object-oriented languages (the encapsulation concept), it is good to follow a naming pattern.

The following is an example of a class declaring a get and set function along with its use:

class Person { 
  constructor (name) { 
    this._name = name; //{1} 
  } 
  get name() { //{2} 
    return this._name; 
  } 
  set name(value) { //{3} 
    this._name = value; 
  } 
} 
 
let lotrChar = new Person('Frodo'); 
console.log(lotrChar.name); //{4} 
lotrChar.name = 'Gandalf';    //{5} 
console.log(lotrChar.name); 
lotrChar._name = 'Sam'; //{6} 
console.log(lotrChar.name); 

To declare a get and set function, we simply need to use the keyword get or set in front of the function name (lines {2} and {3}), which is the name we want to expose and to be used. We can declare the class attributes with the same name, or we can use underscore in front of the attribute name (line {1}) to make it seem as though the attribute is private.

Then, to take a look at the get or set functions, we can simply refer to their names as it was a simple attribute (lines {4} and {5}).

Tip

It is also good to remember that the _name attribute is not really private, and we can still make a reference to it. However, we will talk about this later on in this book. This example can be executed at https://goo.gl/SMRYsv.

Other functionalities

ES6 also has some other functionalities; among them, we can list iterators, typed arrays, Set, Map, WeakSet, WeakMap, modules, tail calls, and Symbol. We will cover some of these other functionalities in other chapters of this book.

Note

For more information about all the functionalities of ES6 and its specification, refer to http://www.ecma-international.org/ecma-262/6.0/ .