Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Advanced JavaScript
Advanced JavaScript

Advanced JavaScript: Speed up web development with the powerful features and benefits of JavaScript

Arrow left icon
Profile Icon Zachary Shute
Arrow right icon
$19.99 per month
Full star icon Full star icon Full star icon Half star icon Empty star icon 3.5 (4 Ratings)
Paperback Jan 2019 330 pages 1st Edition
eBook
$17.99 $26.99
Paperback
$38.99
Subscription
Free Trial
Renews at $19.99p/m
Arrow left icon
Profile Icon Zachary Shute
Arrow right icon
$19.99 per month
Full star icon Full star icon Full star icon Half star icon Empty star icon 3.5 (4 Ratings)
Paperback Jan 2019 330 pages 1st Edition
eBook
$17.99 $26.99
Paperback
$38.99
Subscription
Free Trial
Renews at $19.99p/m
eBook
$17.99 $26.99
Paperback
$38.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with a Packt Subscription?

Free for first 7 days. $19.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing
Table of content icon View table of contents Preview book icon Preview Book

Advanced JavaScript

Chapter 1. Introducing ECMAScript 6

Learning Objectives

By the end of this chapter, you will be able to:

  • Define the different scopes in JavaScript and characterize variable declaration

  • Simplify JavaScript object definitions

  • Destructure objects and arrays, and build classes and modules

  • Transpile JavaScript for compatibility

  • Compose iterators and generators

In this chapter, you'll be learning how to use the new syntax and concepts of ECMAScript.

Introduction


JavaScript, often abbreviated as JS, is a programming language designed to allow the programmer to build interactive web applications. JavaScript is one of the backbones of web development, along with HTML and CSS. Nearly every major website, including Google, Facebook, and Netflix, make heavy use of JavaScript. JS was first created for the Netscape web browser in 1995. The first prototype of JavaScript was written by Brendan Eich in just a mere 10 days. Since its creation, JavaScript has become one of the most common programming languages in use today.

In this book, we will deepen your understanding of the core of JavaScript and its advanced functionality. We will cover the new features that have been introduced in the ECMAScript standard, JavaScript's asynchronous programming nature, DOM and HTML event interaction with JavaScript, JavaScript's functional programming paradigms, testing JavaScript code, and the JavaScript development environment. With the knowledge gained from this book, you will be ready to begin using JavaScript in a professional setting to build powerful web applications.

Beginning with ECMAScript


ECMAScript is a scripting language specification standardized by ECMA International. It was created to standardize JavaScript in an attempt to allow for independent and compatible implementations. ECMAScript 6, or ES6, was originally released in 2015 and has gone through several minor updates since then.

Note

You may refer to the following link for more information about ECMA specification:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Language_Resources.

Understanding Scope


In computer science, scope is the region of a computer program where the binding or association of a name to an entity, such as a variable or function, is valid. JavaScript has the following two distinct types of scope:

  • Function scope

  • Block scope

Until ES6, function scope was the only form of scope in JavaScript; all variable and function declarations followed function scope rules. Block scope was introduced in ES6 and is used only by the variables declared with the new variable declaration keywords let and const. These keywords are discussed in detail in the Declaring Variables section.

Function Scope

Function scope in JavaScript is created inside functions. When a function is declared, a new scope block is created inside the body of that function. Variables that are declared inside the new function scope cannot be accessed from the parent scope; however, the function scope has access to variables in the parent scope.

To create a variable with function scope, we must declare the variable with the var keyword. For example:

var example = 5;

The following snippet provides an example of function scope:

var example = 5;
function test() {
  var testVariable = 10;
  console.log( example ); // Expect output: 5
  console.log( testVariable ); // Expect output: 10
}
test();
console.log( testVariable ); // Expect reference error

Snippet 1.1: Function Scope

Parent scope is simply the scope of the section of code that the function was defined in. This is usually the global scope; however, in some cases, it may be useful to define a function inside a function. In that case, the nested function's parent scope would be the function in which it is defined. In the preceding snippet, the function scope is the scope that was created inside the function test. The parent scope is the global scope, that is, where the function is defined.

Note

Parent scope is the block of code, which the function is defined in. It is not the block of code in which the function is called.

Function Scope Hoisting

When a variable is created with function scope, it's declaration automatically gets hoisted to the top of the scope. Hoisting means that the interpreter moves the instantiation of an entity to the top of the scope it was declared in, regardless of where in the scope block it is defined. Functions and variables declared using var are hoisted in JavaScript; that is, a function or a variable can be used before it has been declared. The following code demonstrates this, as follows:

example = 5; // Assign value
console.log( example ); // Expect output: 5
var example; // Declare variable

Snippet 1.2: Function Scope Hoisting

Note

Since a hoisted variable that's been declared with var can be used before it is declared, we have to be careful to not use that variable before it has been assigned a value. If a variable is accessed before it has been assigned a value, it will return the value as undefined, which can cause problems, especially if variables are used in the global scope.

Block Scope

A new block scope in JavaScript is created with curly braces ({}). A pair of curly braces can be placed anywhere in the code to define a new scope block. If statements, loops, functions, and any other curly brace pairs will have their own block scope. This includes floating curly brace pairs not associated with a keyword (if, for, etc). The code in the following snippet is an example of the block scope rules:

// Top level scope
function scopeExample() {
  // Scope block 1
  for ( let i = 0; i < 10; i++ ){ /* Scope block 2 */ }
  if ( true ) { /* Scope block 3 */ } else {  /* Scope block 4 */ }
  // Braces without keywords create scope blocks
  { /* Scope block 5 */ } 
  // Scope block 1
}
// Top level scope

Snippet 1.3: Block Scope

Variables declared with the keywords let and const have block scope. When a variable is declared with block scope, it does NOT have the same variable hoisting as variables that are created in function scope. Block scoped variables are not hoisted to the top of the scope and therefore cannot be accessed until they are declared. This means that variables that are created with block scope are subject to the Temporal Dead Zone (TDZ). The TDZ is the period between when a scope is entered and when a variable is declared. It ends when the variable is declared rather than assigned. The following example demonstrates the TDZ:

// console.log( example ); // Would throw ReferenceError
let example;
console.log( example ); // Expected output: undefined
example = 5;
console.log( example ); // Expected output: 5

Snippet 1.4: Temporal Dead Zone

Note

If a variable is accessed inside the Temporal Dead Zone, then a runtime error will be thrown. This is important because it allows our code to be built more robustly with fewer semantic errors arising from variable declaration.

To get a better understanding of scope blocks, refer to the following table:

Figure 1.1: Function Scope versus Block Scope

In summary, scope provides us with a way to separate variables and restrict access between blocks of code. Variable identifier names can be reused between blocks of scope. All new scope blocks that are created can access the parent scope, or the scope in which they were created or defined. JavaScript has two types of scope. A new function scope is created for each function defined. Variables can be added to function scope with the var keyword, and these variables are hoisted to the top of the scope. Block scope is a new ES6 feature. A new block scope is created for each set of curly braces. Variables are added to block scope with the let and const keywords. The variables that are added are not hoisted and are subject to the TDZ.

Exercise 1: Implementing Block Scope

To implement block scope principles with variables, perform the following steps:

  1. Create a function called fn1 as shown (function fn1()).

  2. Log the string as scope 1.

  3. Create a variable called scope with the value of 5.

  4. Log the value of the variable called scope.

  5. Create a new block scope inside of the function with curly braces ({}).

  6. Inside the new scope block, log the string called scope 2.

  7. Create a new variable called scope, inside the scope block and assign the value different scope.

  8. Log the value variable scope inside our block scope (scope 2).

  9. Outside of the block scope defined in step 5 (scope 2), create a new block scope (use curly braces).

  10. Log the string called scope 3.

  11. Create a variable inside the scope block (scope 3) with the same name as the variables (call it scope) and assign it the value a third scope.

  12. Log the new variable's value.

  13. Call fn1 and observe its output

Code

index.js:
function fn1(){
 console.log('Scope 1');
 let scope = 5;
 console.log(scope);
 {
   console.log('Scope 2');
   let scope = 'different scope';
   console.log(scope);
 }
  {
   console.log('Scope 3');
   let scope = 'a third scope';
   console.log(scope);
 }
}
fn1();

https://bit.ly/2RoOotW

Snippet 1.5: Block implementation output

Outcome

Figure 1.2: Scope outputs

You have successfully implemented block scope in JavaScript.

In this section, we covered the two types of JavaScript scope, function and block scope, and the differences between them. We demonstrated how a new instance of function scope was created inside each function and how block scope was created inside each set of curly braces. We discussed the variable declaration keywords for each type of scope, var for function scope and let/const for block scope. Finally, we covered the basics of hoisting with both function and block scope.

Declaring Variables


Basic JavaScript uses the keyword var for variable declaration. ECMAScript 6 introduced two new keywords to declare variables; they are let and const. In the world of Professional JavaScript variable declaration, var is now the weakest link. In this topic, we will go over the new keywords, let and const, and explain why they are better than var.

The three ways to declare variables in JavaScript are by using var, let, and const. All function in slightly different ways. The key differences between the three variable declaration keywords are the way they handle variable reassignment, variable scope, and variable hoisting. These three features can be explained briefly as follows:

Variable reassignment: The ability to change or reassign the variable's value at any time.

Variable scope: The extent or area of the code from which the variable may be accessed.

Variable hoisting: The variable instantiation and assignment time in relation to the variable's declaration. Some variables can be used before they are declared.

The var keyword is the older variable declaration keyword that's used to declare variables in JavaScript. All variables created with var can be reassigned, have function scope, and have variable hoisting. This means that variables created with var are hoisted to the top of the scope block, where they are defined and can be accessed before declaration. The following snippet demonstrates this, as follows:

// Referenced before declaration
console.log( example ); // Expect output: undefined
var example = 'example';

Snippet 1.6: Variables created using var are hoisted

Since variables that are created with the keyword var are not constants, they can be created, assigned, and reassigned a value at will. The following code demonstrates this aspect of the functionality of var:

// Declared and assigned
var example = { prop1: 'test' };
console.log( 'example:', example );
// Expect output: example: {prop1: "test"}
// Value reassigned
example = 5;
console.log( example ); // Expect output: 5

Snippet 1.7: Variables created using var are not constant

Variables created with var can be reassigned at any time and once the variable is created, it can be accessed from anywhere in the function, even before the original declaration point.

The let keyword functions similar to the keyword var. As expected, the keyword let allows us to declare a variable that can be reassigned at any time. This is shown in the following code:

// Declared and initialized
let example = { prop1: 'test' };
console.log( 'example:', example );
// Expect output: example: {prop1: 'test"}
// Value reassigned
example = 5;
console.log( example ); // Expect output: 5

Snippet 1.8: Variables created with let are not constant

There are two significant differences between let and var. Where let and var differ is their scoping and variable hoisting properties. Variables declared with let are scoped at the block level; that is, they are only defined in the block of code contained within a matching pair of curly braces ({}).

Variables declared with let are not subject to variable hoisting. This means that accessing a variable declared with let before the assignment will throw a runtime error. As discussed earlier, this is the Temporal Dead Zone. An example of this is shown in the following code:

// Referenced before declaration
console.log( example );
// Expect ReferenceError because example is not defined
let example = 'example';

Snippet 1.9: Variables created with let are not hoisted

The last variable declaration keyword is const. The const keyword has the same scoping and variable hoisting rules as the let keyword; variables declared with const have block scoping and do not get hoisted to the top of the scope. This is shown in the following code:

// Referenced before declaration
console.log( example );
// Expect ReferenceError because example is not defined
const example = 'example';

Snippet 1.10: Variables created with const are not hoisted

The key difference between const and let is that const signifies that the identifier will not be reassigned. The const identifier signifies a read-only reference to a value. In other words, the value written in a const variable cannot be changed. If the value of a variable initialized with const is changed, a TypeError will be thrown.

Even though variables created with const cannot be reassigned, this does not mean that they are immutable. If an array or object is stored in a variable declared with const, the value of the variable cannot be overwritten. However, the array content or object properties can be changed. The contents of an array can be modified with functions such as push(), pop(), or map() and object properties can be added, removed, or updated. This is shown in the following code:

// Declared and initialized
const example = { prop1: 'test' };

// Variable reassigned
example = 5;
// Expect TypeError error because variable was declared with const

// Object property updated
example.prop1 = 5;
// Expect no error because subproperty was modified

Snippet 1.11: Variables created with const are constant but not immutable

To understand the different keywords in more detail, refer to the following table:

Figure 1.3: Differences between var, let, and const

Now that we understand the nuances among var, let, and const, we can decide on which one to use. In the professional world, we should always use let and const, because they provide all the functionality of var and allow the programmer to be specific and restrictive with the variable scope and usage.

In summary, var, let, and const all function similarly. The key differences are in the nature of const, the scope, and the hoisting. Var is function scoped, not constant, and hoisted to the top of the scope block. let and const are both block-scoped and not hoisted. let is not constant, while, const is constant but immutable.

Exercise 2: Utilizing Variables

To utilize the var, const, and let variable declaration keywords for variable hoisting and reassignment properties, perform the following steps:

  1. Log the string Hoisted before assignment: and the value of the hoisted variable.

  2. Define a variable called hoisted with the keyword var and assign it the value this got hoisted.

  3. Log the string hoisted after assignment: and the value of the hoisted variable.

  4. Create a try-catch block.

  5. Inside the try block, log the value of the variable called notHoisted1.

  6. Inside the catch block, give the catch block the err parameter, then log the string Not hoisted1 with error: and the value of err.message.

  7. After the try-catch block, create the notHoisted1 variable with the let keyword and assign the value 5.

  8. Log the string notHoisted1 after assignment and the value of notHoisted1.

  9. Create another try-catch block.

  10. Inside the try block, log the value of the notHoisted2 variable.

  11. Inside the catch block, give the catch block the err parameter, then log the string Not hoisted2 with error: and the value of err.message.

  12. After the second try-catch block, create the notHoisted2 variable with the keyword const and assign the value [1,2,3].

  13. Log the string notHoisted2 after assignment and the value of notHoisted2.

  14. Define a final try catch block.

  15. Inside the try block, reassign notHoisted2 to the new value string.

  16. Inside the catch block, give the catch block the err parameter, then log the string Not hoisted 2 was not able to be changed.

  17. After the try-catch block, push the value 5 onto the array in notHoisted2.

  18. Log the string notHoisted2 updated. Now is: and the value of notHoisted2.

Code

index.js:
var hoisted = 'this got hoisted';
try{
 console.log(notHoisted1);
} catch(err){}
let notHoisted1 = 5;
try{
 console.log(notHoisted2);
} catch(err){}
const notHoisted2 = [1,2,3];
try{
 notHoisted2 = 'new value';
} catch(err){}
notHoisted2.push(5);

Snippet 1.12: Updating the contents of the object

Outcome

Figure 1.4: Hoisting the variables

You have successfully utilized keywords to declare variables.

In this section, we discussed variable declaration in ES6 and the benefits of using the let and const variable declaration keywords over the var variable declaration keyword. We discussed each keywords variable reassignment properties, variable scoping, and variable hoisting properties. The keywords let and const are both create variables in the block scope where var creates a variable in the function scope. Variables created with var and let can be reassigned at will. However, variables created with const cannot be reassigned. Finally, variables created with the keyword var are hoisted to the top of the scope block in which they were defined. Variables created with let and const are not hoisted.

Introducing Arrow Functions


Arrow functions, or Fat arrow functions, are a new way to create functions in ECMAScript 6. Arrow functions simplify function syntax. They are called fat arrow functions because they are denoted with the characters =>, which, when put together look like a fat arrow. Arrow functions in JavaScript are frequently used in callback chains, promise chains, array methods, in any situation where unregistered functions would be useful.

The key difference between arrow functions and normal functions in JavaScript is that arrow functions are anonymous. Arrow functions are not named and not bound to an identifier. This means that an arrow function is created dynamically and is not given a name like normal functions. Arrow functions can however be assigned to a variable to allow for reuse.

When creating an arrow function, all we need to do is remove the function keyword and place an arrow between the function arguments and function body. Arrow functions are denoted with the following syntax:

( arg1, arg2, ..., argn ) => { /* Do function stuff here */ }

Snippet 1.13: Arrow function syntax

As you can see from the preceding syntax, arrow functions are a more concise way of writing functions in JavaScript. They can make our code more concise and easier to read.

Arrow function syntax can also vary, depending on several factors. Syntax can vary slightly depending on the number of arguments passed in to the function, and the number of lines of code in the function body. The special syntax conditions are outlined briefly in the following list:

  • Single input argument

  • No input arguments

  • Single line function body

  • Single expression broken over multiple lines

  • Object literal return value

Exercise 3: Converting Arrow Functions

To demonstrate the simplified syntax by converting a standard function into an arrow function, perform the following steps:

  1. Create a function that takes in parameters and returns the sum of the two parameters. Save the function into a variable called fn1.

  2. Convert the function you just created to an arrow function and save into another variable called fn2.

    To convert the function, remove the function keyword. Next, place an arrow between the function arguments and the function body.

  3. Call both functions and compare the output.

Code

index.js:
const fn1 = function( a, b ) { return a + b; };
const fn2 = ( a, b ) => { return a + b; };
console.log( fn1( 3 ,5 ), fn2( 3, 5 ) );

Snippet 1.14: Calling the functions

Outcome

Figure 1.5: Comparing the function's output

You have successfully converted normal functions into arrow functions.

Arrow Function Syntax

If there are multiple arguments being passed in to the function, then we create the function with the parentheses around the arguments as normal. If we only have a single argument to pass to the function, we do not need to include the parentheses around the argument.

There is one exception to this rule, and that is if the parameter is anything other than a simple identifier. If we include a default value or perform operations in the function arguments, then we must include the parentheses. For example, if we include a default parameter, then we will need the parentheses around the arguments. These two rules are shown in the following code:

// Single argument arrow function
arg1 => { /* Do function stuff here */ }

// Non simple identifier function argument
( arg1 = 10 ) => { /* Do function stuff here */ }

Snippet 1.15: Single argument arrow function

If we create an arrow function with no arguments, then we need to include the parentheses, but they will be empty. This is shown in the following code:

// No arguments passed into the function
( ) => { /* Do function stuff here */ }

Snippet 1.16: No argument

Arrow functions can also have varied syntax, depending on the body of the function. As expected, if the body of the function is multiline, then we must surround it with curly braces. However, if the body of the function is a single line, then we do not need to include the curly braces around the body of the function. This is shown in the following code:

// Multiple line body arrow function
( arg1, arg2 ) => { 
  console.log( `This is arg1: ${arg1}` );
  console.log( `This is arg2: ${arg2}` );
  /* Many more lines of code can go here */
}

// Single line body arrow function
( arg1, arg2 ) => console.log( `This is arg1: ${arg1}` )

Snippet 1.17: Single line body

When using arrow functions, we may also exclude the return keyword if the function is a single line. The arrow function automatically returns the resolved value of the expression on that line. This syntax is shown in the following code:

// With return keyword - not necessary
( num1, num2 ) => { return ( num1 + num2 ) }
// If called with arguments num1 = 5 and num2 = 5, expected output is 10

// Without return keyword or braces
( num1, num2 ) => num1 + num2
// If called with arguments num1 = 5 and num2 = 5, expected output is 10

Snippet 1.18: Single line body when value is returned

Since arrow functions with single expression bodies can be defined without the curly braces, we need special syntax to allow us to split the single expression over multiple lines. To do this, we can wrap the multi-line expression in parentheses. The JavaScript interpreter sees that the line are wrapped in parentheses and treats it as if it were a single line of code. This is shown in the following code:

// Arrow function with a single line body
// Assume numArray is an array of numbers
( numArray ) => numArray.filter( n => n > 5).map( n => n - 1 ).every( n => n < 10 )

// Arrow function with a single line body broken into multiple lines
// Assume numArray is an array of numbers
( numArray ) => (
  numArray.filter( n => n > 5)
          .map( n => n - 1 )
          .every( n => n < 10 )
)

Snippet 1.19: Single line expression broken into multiple lines

If we have a single line arrow function returning an object literal, we will need special syntax. In ES6, scope blocks, function bodies, and object literals are all defined with curly braces. Since single line arrow functions do not need curly braces, we must use the special syntax to prevent the object literal's curly braces from being interpreted as either function body curly braces or scope block curly braces. To do this, we surround the returned object literal with parentheses. This instructs the JavaScript engine to interpret curly braces inside the parentheses as an expression instead of a function body or scope block declaration. This is shown in the following code:

// Arrow function with an object literal in the body
( num1, num2 ) => ( { prop1: num1, prop2: num2 } ) // Returns an object

Snippet 1.20: Object literal return value

When using arrow functions, we must be careful of the scope that these functions are called in. Arrow functions follow normal scoping rules in JavaScript, with the exception of the this scope. Recall that in basic JavaScript, each function is assigned a scope, that is, the this scope. Arrow functions are not assigned a this scope. They inherit their parent's this scope and cannot have a new this scope bound to them. This means that, as expected, arrow functions have access to the scope of the parent function, and subsequently, the variables in that scope, but the scope of this cannot be changed in an arrow function. Using the .apply(), .call(), or .bind() function modifiers will NOT change the scope of an arrow function's this property. If you are in a situation where you must bind this to another scope, then you must use a normal JavaScript function.

In summary, arrow functions provide us with a way to simplify the syntax of anonymous functions. To write an arrow function, simply omit the function keyword and add an arrow between the arguments and function body.

Special syntax can then be applied to the function arguments and body to simplify the arrow function even more. If the function has a single input argument, then we can omit the parentheses around it. If the function body has a single line, we can omit the return keyword and the curly braces around it. However, single-line functions that return an object literal must be surrounded with parentheses.

We can also use parentheses around the function body to break a single line body into multiple lines for readability.

Exercise 4: Upgrading Arrow Functions

To utilize the ES6 arrow function syntax to write functions, perform the following steps:

  1. Refer to the exercises/exercise4/exercise.js file and perform the updates in this file.

  2. Convert fn1 with basic ES6 syntax.

    Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.

  3. Convert fn2 with single statement function body syntax.

    Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.

    Remove the curly braces ({}) around the function body. Remove the return keyword.

  4. Convert fn3 with Single input argument syntax.

    Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.

    Remove the parentheses around the function input argument.

  5. Convert fn4 with no input argument syntax.

    Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.

  6. Convert fn5 with object literal syntax.

    Remove the function keyword before the function arguments. Add an arrow between the function arguments and function body.

    Remove the curly braces ({}) around the function body. Remove the return keyword.

    Surround the returned object with parentheses.

Code

index.js:
let fn1 = ( a, b ) => { … };
let fn2 = ( a, b ) => a * b;
let fn3 = a => { … };
let fn4 = () => { … };
let fn5 = ( a ) => ( …  );

Snippet 1.21: Arrow function conversion

Outcome

Figure 1.6: Converting the function's output

You have successfully utilized the ES6 arrow function syntax to write functions.

In this section, we introduced arrow functions and demonstrated how they can be used to greatly simplify function declaration in JavaScript. First, we covered the basic syntax for arrow functions: ( arg1, arg2, argn ) => { /* function body */ }. We proceeded to cover the five special syntax cases for advanced arrow functions, as outlined in the following list:

  • Single input argument: arg1 => { /* function body */ }

  • No input arguments: ( ) => { /* function body */ }

  • Single line function body: ( arg1, arg2, argn ) => /* single line */

  • Single expression broken over multiple lines: ( arg1, arg2, argn ) => ( /* multi line single expression */ )

  • Object literal return value: ( arg1, arg2, argn ) => ( { /* object literal */ } )

Learning Template Literals


Template literals are a new form of string that was introduced in ECMAScript 6. They are enclosed by the backtick symbol (``) instead of the usual single or double quotes. Template literals allow you to embed expressions in the string that are evaluated at runtime. Thus, we can easily create dynamic strings from variables and variable expressions. These expressions are denoted with the dollar sign and curly braces (${ expression }). The template literal syntax is shown in the following code:

const example = "pretty";
console.log( `Template literals are ${ example } useful!!!` ); 
// Expected output: Template literals are pretty useful!!!

Snippet 1.22: Template literal basic syntax

Template literals are escaped like other strings in JavaScript. To escape a template literal, simply use a backslash (\) character. For example, the following equalities evaluate to true: `\`` === "`",`\t` === "\t", and `\n\r` === "\n\r".

Template literals allow for multiline strings. Any newline characters that are inserted into the source are part of the template literal and will result in a line break in the output. In simpler terms, inside a template literal, we can press the Enter key on the keyboard and split it on to two lines. This newline character in the source code will be parsed as part of the template literal and will result in a newline in the output. To replicate this with normal strings, we would have to use the \n character to generate a new line. With template literals, we can break the line in the template literal source and achieve the same expected output. An example of this is shown in the following code:

// Using normal strings
console.log( 'This is line 1\nThis is line 2' );
// Expected output: This is line 1
// This is line 2

// Using template literals
console.log( `This is line 1
This is line 2` );
// Expected output: This is line 1
// This is line 2

Snippet 1.23: Template literal multi-line syntax

Exercise 5: Converting to Template Literals

To convert standard string objects to template literals to demonstrate the power of template literal expressions, perform the following steps:

  1. Create two variables, a and b, and save numbers into them.

  2. Log the sum of a and b in the format a + b is equal to <result> using normal strings.

  3. Log the sum of a and b in the format a + b is equal to <result> using a single template literal.

Code

index.js:

let a = 5, b = 10;
console.log( a + ' + ' + b + ' is equal to ' + ( a + b ) );
console.log( `${a} + ${b} is equal to ${a + b}` );

Snippet 1.24: Template literal and string comparison

Outcome

Figure 1.7: Logging the sum of the variable's output

You have successfully converted standard string objects to template literals.

Template literals allow for expression nesting, that is, new template literals can be put inside the expression of a template literal. Since the nested template literal is part of the expression, it will be parsed as a new template literal and will not interfere with the external template literal. In some cases, nesting a template literal is the easiest and most readable way to create a string. An example of template literal nesting is shown in the following code:

function javascriptOrCPlusPlus() { return 'JavaScript'; }
const outputLiteral = `We are learning about ${ `Professional ${ javascriptOrCPlusPlus() }` }`

Snippet 1.25: Template literal nesting

A more advanced form of template literals are tagged template literals. Tagged template literals can be parsed with a special function called tag functions, and can return a manipulated string or any other value. The first input argument of a tag function is an array containing string values. The string values represent the parts of the input string, broken at each template expression. The remaining arguments are the values of the template expressions in the string. Tag functions are not called like normal functions. To call a tag function, we omit the parentheses and any whitespace around the template literal argument. This syntax is shown in the following code:

// Define the tag function
function tagFunction( strings, numExp, fruitExp ) { 
  const str0 = strings[0]; // "We have"
  const str1 = strings[1]; // " of "
  const quantity = numExp < 10 ? 'very few' : 'a lot';
  return str0 + quantity + str1 + fruitExp + str2;
}
const fruit = 'apple', num = 8;
// Note: lack of parenthesis or whitespace when calling tag function
const output = tagFunction`We have ${num} of ${fruit}. Exciting!`
console.log( output )
// Expected output: We have very few of apples. Exciting!!

Snippet 1.26: Tagged template literal example

A special property named raw is available for the first argument of a tagged template. This property returns an array that contains the raw, unescaped, versions of each part of the split template literal. This is shown in the following code:

function tagFunction( strings ){ console.log( strings.raw[0] ); }
tagFunction`This is line 1. \n This is line 2.`
// Expected output: "This is line 1. \n This is line 2." The characters //'\' and 'n' are not parsed into a newline character

Snippet 1.27: Tagged template raw property

In summary, template literals allow for the simplification of complicated string expressions. Template literals allow you to embed variables and complicated expressions into strings. Template literals can even be nested into the expression fields of other template literals. If a template literal is broken into multiple lines in the source code, the interpreter will interpret that as a new line in the string and insert one accordingly. Template literals also provide a new way to parse and manipulate strings with the tagged template function. These functions give you a way to perform complex string manipulation via a special function. The tagged template functions also give access to the raw strings as they were entered, ignoring any escape sequences.

Exercise 6: Template Literal Conversion

You are building a website for a real estate company. You must build a function that takes in an object with property information and returns a formatted string that states the property owner, where the property is located (address), and how much they are selling it for (price). Consider the following object as input:

{
  address: '123 Main St, San Francisco CA, USA',
  floors: 2,
  price: 5000000,
  owner: 'John Doe'
}

Snippet 1.28: Object Input

To utilize a template literal to pretty-print an object, perform the following steps:

  1. Create a function called parseHouse that takes in an object.

  2. Return a template literal from the function. Using expressions, embed the owner, address, and price in the format <Owner> is selling the property at <address> for <price>.

  3. Create a variable called house and save the following object into it: { address: "123 Main St, San Francisco CA, USA", floors: 2, price: 5000000, owner: "John Doe" }

  4. Call the parseHouse function and pass in the house variable.

  5. Log the output.

Code

index.js:
function parseHouse( property ) {
 return `${property.owner} is selling the property at ${property.address} for ${property.price} USD`
}
const house = {
 address: "123 Main St, San Francisco CA, USA",
 floors: 2,
 price: 5000000,
 owner: "John Doe"
};
console.log( parseHouse( house ) );

Snippet 1.29: Template literal using expressions

Outcome

Figure 1.8: Template literal output

You have successfully utilized a template literal to pretty-print an object.

In this section, we covered template literals. Template literals upgrade strings by allowing us to nest expressions inside them that are parsed at runtime. Expressions are inserted with the following syntax: `${ expression }`. We then showed you how to escape special characters in template literals and discussed how in-editor newline characters in template literals are parsed as newline characters in the output. Finally, we covered template literal tagging and tagging functions, which allow us to perform more complex template literal parsing and creation.

Enhanced Object Properties


ECMAScript 6 added several enhancements to object literals as part of the ES6 syntactic sugar. ES6 added three ways to simplify the creation of object literals. These simplifications include a more concise syntax for initializing object properties from variables, a more concise syntax for defining function methods, and computed object property names.

Note

Syntactic sugar is a syntax that is designed to make expressions easier to read and express. It makes the syntax "sweeter" because code can be expressed concisely.

Object Properties

The shorthand for initializing object properties allows you to make more concise objects. In ES5, we needed to define the object properties with a key name and a value, as shown in the following code:

function getPersionES5( name, age, height ) {
  return {
    name: name,
    age: age,
    height: height
  };
}
getPersionES5( 'Zachary', 23, 195 )
// Expected output: { name: 'Zachary', age: 23, height: 195 }

Snippet 1.30: ES5 object properties

Notice the repetition in the object literal returned by the function. We name the property in the object after variable name causing duplication (<code>name: name</code>). In ES6, we can shorthand each property and remove the repetition. In ES6, we can simply state the variable in the object literal declaration and it will create a property with a key that matches the variable name and a value that matches the variable value. This is shown in the following code:

function getPersionES6( name, age, height ) {
  return {
    name,
    age,
    height
  };
}
getPersionES6( 'Zachary', 23, 195 )
// Expected output: { name: 'Zachary', age: 23, height: 195 }

Snippet 1.31: ES6 object properties

As you can see, both the ES5 and ES6 examples output the exact same object. However, in a large object literal declaration, we can save a lot of space and repetition by using this new shorthand.

Function Declarations

ES6 also added a shorthand for declaring function methods inside objects. In ES5, we had to state the property name, then define it as a function. This is shown in the following example:

function getPersonES5( name, age, height ) {
  return {
    name: name,
    height: height,

    getAge: function(){ return age; }
  };
}
getPersonES5( 'Zachary', 23, 195 ).getAge()
// Expected output: 23

Snippet 1.32: ES5 function properties

In ES6, we can define a function but with much less work. As with the property declaration, we don't need a key and value pair to create the function. The function name becomes the key name. This is shown in the following code:

function getPersionES6( name, age, height ) {
  return {
    name,
    height,

    getAge(){ return age; }
  };
}
getPersionES6( 'Zachary', 23, 195 ).getAge()
// Expected output: 23

Snippet 1.33: ES6 function properties

Notice the difference in the function declaration. We omit the function keyword and the colon after the property key name. Once again, this saves us a bit of space and simplifies things a little.

Computed Properties

ES6 also added a new, efficient way to create property names from variables. This is through computed property notation. As we already know, in ES5, there is only one way to create a dynamic property whose name is specified by a variable; this is through bracket notation, that is, : obj[ expression ] = 'value' . In ES6, we can use this same type of notation during the object literal's declaration. This is shown in the following example:

const varName = 'firstName';
const person = {
  [ varName ] = 'John',
  lastName: 'Smith'
};
console.log( person.firstName ); // Expected output: John

Snippet 1.34: ES6 Computed property

As we can see from the preceding snippet, the property name of varName was computed to be firstName. When accessing the property, we simply reference it as person.firstName. When creating computed properties in object literals, the value that's computed in the brackets does not need to be a variable; it can be almost any expression, even a function. An example of this is shown in the following code:

const varName = 'first';
function computeNameType( type ) {
  return type + 'Name';
}

const person = {
  [ varName + 'Name' ] = 'John',
  [ computeNameType( 'last' ) ]: 'Smith'
};

console.log( person.firstName ); // Expected output: John
console.log( person.lastName ); // Expected output: Smith

Snippet 1.35: Computed property from function

In the example shown in the preceding snippet, we created two variables. The first contains the string first and the second contains a function that returns a string. We then created an object and used computed property notation to create dynamic object key names. The first key name is equal to firstName. When person.firstName is accessed, the value that was saved will be returned. The second key name is equal to lastName. When person.lastName is accessed, the value that was saved will be returned.

In summary, ES6 added three ways to simplify the declaration of object literals, that is, property notation, function notation, and computed properties. To simplify property creation in objects, when properties are created from variables, we can omit the key name and the colon. The name property that's created is set to the variable name and the value is set to the value of the variable. To add a function as a property to an object, we can omit the colon and function keyword. The name of the property that's created is set to the function name and the value of the property is the function itself. Finally, we can create property names from computed expressions during the declaration of the object literal. We simply replace the key name with the expression in brackets. These three simplifications can save us space in our code and make object literal creation easier to read.

Exercise 7: Implementing Enhanced Object Properties

You are building a simple JavaScript math package to publish to Node Package Manager (NPM). Your module will export an object that contains several constants and functions. Using ES6 syntax, create the export object with the following functions and values: the value of pi, the ratio to convert inches to feet, a function that sums two arguments, and a function that subtracts two arguments. Log the object after it has been created.

To create objects using ES6 enhanced object properties and demonstrate the simplified syntax, perform the following steps:

  1. Create an object and save it into the exportObject variable.

  2. Create a variable called PI that contains the value of pi (3.1415).

  3. Create a variable called INCHES_TO_FEET and save the value of the inches to feet conversion ratio (0.083333).

    Using ES6 enhanced property notation, add a property called PI from the variable PI. Add a property called INCHES_TO_FEET from the INCHES_TO_FEET variable, which contains the inches to feet conversion ratio.

    Add a function property called sum that takes in two input arguments and returns the sum of the two input arguments.

    Add a function property called subtract that takes in two input arguments and returns the subtraction of the two input arguments.

  4. Log the object exportObject.

Code

index.js:
const PI = 3.1415;
const INCHES_TO_FEET = 0.083333;
const exportObject = {
 PI,
 INCHES_TO_FEET,
 sum( n1, n2 ) {
   return n1 + n2;
 },
 subtract( n1, n2 ) {
   return n1 - n2;
 }
};
console.log( exportObject );

Snippet 1.36: Enhanced object properties

Outcome

Figure 1.9: Enhanced object properties output

You have successfully created objects using ES6 enhanced object properties.

In this section, we showed you enhanced object properties, a syntactic sugar to help condense object property creation into fewer characters. We covered the shorthand for initializing object properties from variables and functions, and we covered the advanced features of computed object properties, that is, a way to create an object property name from a computed value, inline, while defining the object.

Left arrow icon Right arrow icon

Key benefits

  • Explore the new ES6 syntax, the event loop, and asynchronous programming
  • Learn the test-driven development approach when building apps
  • Master advanced JavaScript concepts to enhance your web developments skill

Description

If you are looking for a programming language to develop flexible and efficient applications, JavaScript is an obvious choice. Advanced JavaScript is a hands-on guide that takes you through JavaScript and its many features, one step at a time. You'll begin by learning how to use the new JavaScript syntax in ES6, and then work through the many other features that modern JavaScript has to offer. As you progress through the chapters, you’ll use asynchronous programming with callbacks and promises, handle browser events, and perform Document Object Model (DOM) manipulation. You'll also explore various methods of testing JavaScript projects. In the concluding chapters, you'll discover functional programming and learn to use it to build your apps. With this book as your guide, you'll also be able to develop APIs using Node.js and Express, create front-ends using React/Redux, and build mobile apps using React/Expo. By the end of Advanced JavaScript, you will have explored the features and benefits of JavaScript to build small applications.

Who is this book for?

This book is designed to target anyone who wants to write JavaScript in a professional environment. We expect the audience to have used JavaScript in some capacity and be familiar with the basic syntax. This book would be good for a tech enthusiast wondering when to use generators or how to use Promises and Callbacks effectively, or a novice developer who wants to deepen their knowledge on JavaScript and understand TDD.

What you will learn

  • Examine major features in ES6 and implement those features to build applications
  • Create promise and callback handlers to work with asynchronous processes
  • Develop asynchronous flows using Promise chaining and async/await syntax
  • Manipulate the DOM with JavaScript
  • Handle JavaScript browser events
  • Explore Test Driven Development and build code tests with JavaScript code testing frameworks.
  • List the benefits and drawbacks of functional programming compared to other styles
  • Construct applications with the Node.js backend framework and the React frontend framework

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Jan 31, 2019
Length: 330 pages
Edition : 1st
Language : English
ISBN-13 : 9781789800104
Languages :
Tools :

What do you get with a Packt Subscription?

Free for first 7 days. $19.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing

Product Details

Publication date : Jan 31, 2019
Length: 330 pages
Edition : 1st
Language : English
ISBN-13 : 9781789800104
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 131.97
Advanced JavaScript
$38.99
Professional JavaScript
$43.99
Modern JavaScript Web Development Cookbook
$48.99
Total $ 131.97 Stars icon

Table of Contents

6 Chapters
Introducing ECMAScript 6 Chevron down icon Chevron up icon
Asynchronous JavaScript Chevron down icon Chevron up icon
DOM Manipulation and Event Handling Chevron down icon Chevron up icon
Testing JavaScript Chevron down icon Chevron up icon
Functional Programming Chevron down icon Chevron up icon
The JavaScript Ecosystem Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Half star icon Empty star icon 3.5
(4 Ratings)
5 star 25%
4 star 0%
3 star 75%
2 star 0%
1 star 0%
FM Jul 02, 2022
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Forget about what people are saying below about the book and the dumb reviews. This book is by far the best JS book I've ordered so far! It's modern JS, covers all the points you need and more. If you want a book about design patterns, look elsewhere. But design paterns are general and applicable to (almost) every programming language out there. The book does what says on the cover, shows you concepts both basic and advanced! 5 stars from me!
Amazon Verified review Amazon
Lee Apr 27, 2024
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
I've only almost completed the first chapter, the concepts introduced herein are clear and precise, but the amount of errata is very distracting. Most errata encountered thus far were likely caused by copying and pasting codes that are repeated throughout the same section of narrative. I wish all Packt represented books could receive stricter typo and errata screening, because this class of flaws has been around for way too long. Both authors and publishers have their responsibilities to make their books relatively joyful to read. I also think that customers should be provided with reading tools that allow the highlighting of typo and errata and the input of their reasons and correction suggestions. I requested these in multiple conversations with their reps already.
Subscriber review Packt
Mark cooper Feb 24, 2021
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
Decent overview of several core Javascript areas. A little disjointed (went from a chapter on asynchronous programming to one on the DOM and jQuery) but overall worth the money.
Amazon Verified review Amazon
Scott J Pearson Aug 15, 2021
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
In the past decade, the JavaScript language has witnessed a renaissance of new activity. Once pigeon-holed as a language for web browser eye-candy, JavaScript can now be used for the entire stack (server-side, client-side, testing, and even command-line). In this book, Shute attempts to keep developers up to date with a high-level review of the advancements. While this book is not a classic (and what modern computer-language-specific book is a classic?), it serves the needs of the IT community quite well.Shute starts by informing readers about the modernization of JavaScript in a form cryptically called ES6. This language allows for more compact and more powerful expression, including new features dealing with asynchronous functions. Most programmers who have done a deep dive into some form of JavaScript are familiar with the challenges of its asynchronous nature.In case anyone is still not familiar with the Document Object Model (DOM) and jQuery, a tutorial is provided. (Most programmers will likely not gain much other than review from this section.) A section on automated testing is provided along with a conceptual introduction to functional programming. Finally, the “ecosystem” of Node.js, Express, and React are described in broader terms.As you can see, Shute does not miss much of the recent developments. However, he stays pretty high in his overview and provides few deep dives to entertain readers as well. This is the main limitation of the book. For instance, I bought another book on Node.js to supplement while reading this one. That said, this book did inspire me to buy a book instead of merely being bored in the first place – a definite accomplishment.This book’s intended audience really consists of only the software development community – hence its higher price-tag. The materials were put together well with a sturdy cover and clear font. Due to the technical content, few pictures accompany the text. Overall, this book updated me on a high level but left me wanting to take a deep dive or two into more difficult (and interesting) topics.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is included in a Packt subscription? Chevron down icon Chevron up icon

A subscription provides you with full access to view all Packt and licnesed content online, this includes exclusive access to Early Access titles. Depending on the tier chosen you can also earn credits and discounts to use for owning content

How can I cancel my subscription? Chevron down icon Chevron up icon

To cancel your subscription with us simply go to the account page - found in the top right of the page or at https://subscription.packtpub.com/my-account/subscription - From here you will see the ‘cancel subscription’ button in the grey box with your subscription information in.

What are credits? Chevron down icon Chevron up icon

Credits can be earned from reading 40 section of any title within the payment cycle - a month starting from the day of subscription payment. You also earn a Credit every month if you subscribe to our annual or 18 month plans. Credits can be used to buy books DRM free, the same way that you would pay for a book. Your credits can be found in the subscription homepage - subscription.packtpub.com - clicking on ‘the my’ library dropdown and selecting ‘credits’.

What happens if an Early Access Course is cancelled? Chevron down icon Chevron up icon

Projects are rarely cancelled, but sometimes it's unavoidable. If an Early Access course is cancelled or excessively delayed, you can exchange your purchase for another course. For further details, please contact us here.

Where can I send feedback about an Early Access title? Chevron down icon Chevron up icon

If you have any feedback about the product you're reading, or Early Access in general, then please fill out a contact form here and we'll make sure the feedback gets to the right team. 

Can I download the code files for Early Access titles? Chevron down icon Chevron up icon

We try to ensure that all books in Early Access have code available to use, download, and fork on GitHub. This helps us be more agile in the development of the book, and helps keep the often changing code base of new versions and new technologies as up to date as possible. Unfortunately, however, there will be rare cases when it is not possible for us to have downloadable code samples available until publication.

When we publish the book, the code files will also be available to download from the Packt website.

How accurate is the publication date? Chevron down icon Chevron up icon

The publication date is as accurate as we can be at any point in the project. Unfortunately, delays can happen. Often those delays are out of our control, such as changes to the technology code base or delays in the tech release. We do our best to give you an accurate estimate of the publication date at any given time, and as more chapters are delivered, the more accurate the delivery date will become.

How will I know when new chapters are ready? Chevron down icon Chevron up icon

We'll let you know every time there has been an update to a course that you've bought in Early Access. You'll get an email to let you know there has been a new chapter, or a change to a previous chapter. The new chapters are automatically added to your account, so you can also check back there any time you're ready and download or read them online.

I am a Packt subscriber, do I get Early Access? Chevron down icon Chevron up icon

Yes, all Early Access content is fully available through your subscription. You will need to have a paid for or active trial subscription in order to access all titles.

How is Early Access delivered? Chevron down icon Chevron up icon

Early Access is currently only available as a PDF or through our online reader. As we make changes or add new chapters, the files in your Packt account will be updated so you can download them again or view them online immediately.

How do I buy Early Access content? Chevron down icon Chevron up icon

Early Access is a way of us getting our content to you quicker, but the method of buying the Early Access course is still the same. Just find the course you want to buy, go through the check-out steps, and you’ll get a confirmation email from us with information and a link to the relevant Early Access courses.

What is Early Access? Chevron down icon Chevron up icon

Keeping up to date with the latest technology is difficult; new versions, new frameworks, new techniques. This feature gives you a head-start to our content, as it's being created. With Early Access you'll receive each chapter as it's written, and get regular updates throughout the product's development, as well as the final course as soon as it's ready.We created Early Access as a means of giving you the information you need, as soon as it's available. As we go through the process of developing a course, 99% of it can be ready but we can't publish until that last 1% falls in to place. Early Access helps to unlock the potential of our content early, to help you start your learning when you need it most. You not only get access to every chapter as it's delivered, edited, and updated, but you'll also get the finalized, DRM-free product to download in any format you want when it's published. As a member of Packt, you'll also be eligible for our exclusive offers, including a free course every day, and discounts on new and popular titles.