JavaScript Overview — Declaring and Using Variables

Vlad Antsitovich
6 min readJul 13, 2022

Scope

Scope is the set of rules that controls how references to variables are resolved. Scope is all about the visibility of variables in your code — it controls which variable can be used where. Each scope can “look out” into the scope around it. Scope is static and contains a fixed set of variables available at the moment and location you define a function.

Scopes are like buckets, and variables are like marbles you put into those buckets. — You Don’t Know JS Yet

JavaScript knows three types of scope: Global Scope, Function Scope, Block Scope.

Global Scope is the scope that contains, and is visible in, all other scopes.

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.

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.

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.

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

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).

Hoisting

JavaScript Hoisting refers to the process whereby the interpreter movie the declaration of functions, variables, or classes to the top of their scope, prior to execution of the code.

You can think of hoisting being a feature that is based on two ‘phases’ of code execution:

  • Compile Phase (where code is also analyzed)
  • Execution Phase (where the code is then executed)

JavaScript allocates memory for all variables and functions defined in the program before execution. And JavaScript only hoists declarations, not the initializations.

Declaration –> Initialisation/Assignment –> Usage

More:

Bindings

To catch and hold values, JavaScript provides a thing called a binding, or variable.

let myName = “Joe”

In this sentence the keyword let indicates that we are going to define a binding. It is followed by the name of the binding and, if we want to immediately give it a value, by an = operator and an expression. This binding called (binding name)myName and uses to grab and hold of the Joe string. Bindings don’t contains values, they grab tham.

After a binding has been defined, its name can be used as an expression.

If we define a binding without giving it a value there nothing to grab so we will get the value undefined.

JavaScript systems always put a number of useful standard bindings into your environment, like: alert() , console.log()

Each binding has a scope, which is the part of the program in which the binding is visible. A variable or binding can only be used in its scope and any nested scope.

For bindings defined outside of any function or block, the scope is the whole program — you can refer to such bindings wherever you want. These are called global.

But bindings created for function parameters or declared inside a function can be referenced only in that function, so they are known as local bindings.

More:

var, let and const

Basic JavaScript uses the keyword var for variable declaration and

ECMAScript 6 (ES6/ES2015) introduced the let and const keywords that support the declaration of block scope local variables. This means the variable will be confined to the scope of a block that it is defined in, such as an if statement or for loop and will not be accessible outside of the opening and closing curly braces of the block.

This is contrary to var declarations which are accessible outside blocks they are defined in.

var-declared variables are function-scoped

The difference between let and const is that a const declaration is, as the name implies, constant — a read-only reference to a value. This does not mean the value is immutable, just that the variable identifier cannot be reassigned.

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.

Sources and more:

Temporal Dead Zone (TDZ)

Temporal Dead Zone (TDZ) is the term to describe the state where variables are un-reachable. They are in scope, but they aren’t declared. And we get ReferenceError. Variables declared by let or const have TDZs.

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.

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.

Let’s look at some example:

If we run this code we will get ReferenceError . Why? When we declaring variable const x = 5 in block scope {} we create TDZ for x that we use in console.log(x)

You can find more examples here.

Global object

Let’s look at one example:

ES6 introduced a distinction for JavaScript global object (window in browsers, global in Node.js):

  • All properties of the global object are global variables. In global scope, the following declarations create such properties: var declarations, Function declarations
  • But there are now also global variables that are not properties of the global object. In global scope, the following declarations create such variables: let and const declarations, class declarations

The environments for various variables form the following chain:

Module variables → Global variables → Global object

Function declarations and class declarations

Function declarations:

  • are block-scoped, like let.
  • create properties in the global object (while in global scope), like var.
  • are hoisted: independently of where a function declaration is mentioned in its scope, it is always created at the beginning of the scope.

Class declarations:

  • are block-scoped.
  • don’t create properties on the global object.
  • are not hoisted.

--

--