Book Image

Advanced JavaScript

By : Zachary Shute
Book Image

Advanced JavaScript

By: Zachary Shute

Overview of this book

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.
Table of Contents (9 chapters)

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.