In any script/programming language, variable is a logical storage where you can assign value into, and JS has three types of variables; var, let, and const.
Let’s get familiar with some of the variable-related terms first.

To verify the scope & behavior of JS variables, we will be using console.log(); a JS method that outputs a message to the (web) console.


What is var?

var is the oldest variable in JS. The scope of var can be either global or block, and let’s see how global scoped var variable works first.

  var hi = 'hi there';  // 1. declare & init global variable hi
  console.log(hi);  // 2. print 'hi there'
  function myFunction() {
    console.log(hi); // 4. print 'hi there'
  }
  myFunction();  // 3. call the function
  1. The var variable hi declared on the top is global scoped being outside myFunction() and is assigned (initialized) with the value ‘hi there’.
  2. console.log(hi); that is executed outside of myFunction() successfully prints ‘hi there’ (because hi is a global scoped variable).
  3. The code myFunction(); executed outside of myFunction() calls the function myFunction().
  4. Within the function, console.log(hi); prints ‘hi there’ successfully. The reason it’s available is because hi is a global scoped variable and it can also be accessed from anywhere inside any block {} such as function, inner function, if-else statement, etc.


Now, let’s slightly modify the code snippet to see how block scoped var variable works as seen below.

  var hi = 'hi there';  // 1. declare & init global variable hi
  console.log(hi);  // 2. prints 'hi there'
  function myFunction() {
    var hello = 'hello there'; // 4. declare & init block scope variable hello
  }
  console.log(hello); // 3. Uncaught ReferenceError: hello is not defined

hi still works as a global variable and you can see that console.log(hi); prints ‘hi there’ as expected. However, when console.log(hello); is executed outside of myFunction(), it outputs an error. The reason is because hello is a block scoped variable that is declared and is initialized inside myFucntion(){}.

How can we fix it? The solution is simply not breaking the scope rule of var.

  var hi = 'hi there';  // 1. declare & init global variable hi 
  console.log(hi);  // 2. prints 'hi there'
 function myFunction() {
    var hello = 'hello there';  // declare & init block scope variable hello
    console.log(hello); // 4. prints 'hello there'
 }
 myFunction(); // 3. call myFunction()

As you can see above, the code myFunction(); only calls the function myFunction() (and its job is done).
console.log(hello); inside myFunction() then prints ‘hello there’ successfully without any error, because, again, hello is a block scope variable within the function.

Reusability of var

You can re-declare another var variable with the same name as the existing one, as well as re-initializing (re-assigning) a new value into either the existing or a new var variable.

  var hi = 'hi there';
  var hi = 'hello there';
  hi = 'hi there again';

  console.log(hi);  // prints 'hi there again'

You can even use var variable without a proper variable declaration in type. The following code declares the variable hi as var in type by default, and hi keeps on being re-initialized with new value with no error.

  hi = 'hi there';  
  hi = 'hello there';
  hi = 'hi there again';

  console.log(hi);  // prints 'hi there again'

Moreover, you can even use any var variable without initialization (no value in it).

 var hi;
 console.log(hi);  // prints 'undefined'

Do you think it’s a cool stuff or a headache? It should absolutely be cool if you consciously use var variables, knowing how it works. On the other hand, what if you have hundreds of thousands lines of codes with complex logic? You will be likely to unrealize when and where var variables are (re)declared and (re)initialized. Also, it’s hardly easy to find errors and bugs once something goes wrong. All of these behaviors of var is deeply related to hoisting.

Hoisting var

Hoisting in JS means moving variable declarations onto the top of their scope before any code execution. Say, you try to use a var variable hi before declaring and initializing it in either one of the following ways.
Both will work with no errors. How and why can they work without any errors?

Because the JS hoisting mechanism restructures both cases as follows.

var hi;
console.log(hi); // undefined
hi = 'hi there';
console.log(hi);  // hi there
  1. Hoist (move) the variable declaration var hi; to the top of its scope and initialize it with such an empty value undefined, which is quite similar to null (not the same!) in some of the programming languages.
  2. Print it.
  3. Re-initialize hi with the value ‘hi there’.
  4. Print it.

In a sense, this hoisting behavior makes it easier to do coding as you can use var anytime and anywhere in your program. However, although it’s completely up to you in taking advantages of var, many programmers and developers have found that it’s difficult to deal with var due to its loose syntax; easy-to-use origin. Roughly speaking, it is error prone in use rather than the syntax of var itself is so.

If you are new to JS, I recommend to not use var variable for a while, but, instead, go for let and/or const variables first. Later, when you get used to JS variables in overall, use var consciously in your code as necessary!

What is let?

let came out to the JS world overcoming the drawbacks of var. Variable declared with let is a block scoped variable that can only be used within a block enclosed with curly brackets {} such as function, and if-else, for, while, etc.

Let’s see an example below.
The let variable num is declared and is initialized with a numeric value 1 as a block scope variable in myFunction(). On the function call, console.log(num) that is executed in the same function block successfully prints ‘1’.

function myFunction() {
let num = 1;  // block scope variable in the function
console.log(num); // prints 1
}
myFunction();  // call the function

If console.log(num) is executed outside myFunction(), it outputs an error, because num is, again, a block scoped variable that is only accessible within the function block it’s declared and initialized.

function myFunction() {
let num = 1;  // block scope variable in the function
}
myFunction();  // call the function
console.log(num); // Uncaught ReferenceError: num is not defined

Let’s see another example below.
num still works as a block scope variable as verified by console.log(num); printing ‘1’ successfully.
Now, have a close look at the if statement block and guess why console.log(printMe); outputs an error.

function myFunction() {
  let num = 1;  // block scope variable in the function
  console.log(num); // prints 1
  if (num == 1) { // if block; an inner block in the function
     // a block scope variable in the if block
     let printMe = 'print me'; // 'print me'
  }
  console.log(printMe); // ReferenceError: printMe is not defined
}
myFunction();  // call the function

Within myFunction(), there’s an if statement having a let variable printMe in its block. In other words, the if block is an inner block within the myFunction() block.
console.log(printMe); that is executed inside myFunction(), but outside the if block then occurs a reference error, because printMe is another let variable at block scope that can only be consumed inside the if block.

If so, how can we fix it?
To not break the block scope rule of let, we can simply move the code console.log(printMe); into the if block as seen below.

function myFunction() {
  let num = 1;  // block scope variable in the function
  console.log(num); // prints 1
  if (num == 1) { // if block; an inner block in the function  
    // a block scope variable in the if block
    let printMe = 'print me'; // 'print me'
    console.log(printMe); // prints 'print me'
  }
}
myFunction();  // call the function


Lastly, let’s slightly modify the code snippet and check what changes are as follows.

  function myFunction() {
    let num = 1;  // block scope variable in the function
    if (num == 1) { // if block; an inner block in the function
      // a block scope variable in the if block
      let printMe = 'I got number ' + num;  // 'I got number 1'
      console.log(printMe); // prints 'I got number 1'
   
      num = num + 1; //num = 2;
      printMe = 'I got number ' + num;  // 'I got number 2'
      console.log(printMe); // prints 'I got number 2'
    }
  }
  myFunction();  // call the function

While num is a block scoped variable declared in myFunction, it can also be global to any inner block like the if block that is in myFunction(). That means, let variable can be global or local (block scoped) to the block in which it is declared.
As highlighted above, num is accessible inside the if block, and printMe, as a result, is able to update (re-initialize) its value by accessing num globally within the function.

Reusability of let

You can re-initialize the existing let variable with a new value.

function myFunction() {
  let num = 1;  //block scope 
  num = 2;  //num is reinitialized with 2
  console.log(num); //prints '2'
}
myFunction();  // call the function

However, you cannot re-declare another let variable with the same name as the existing one in the same block.

function myFunction() {
  let num = 1;  // block scope 
  num = 2;  
  let num = 1000; // error point
  console.log(num); // SyntaxError: Identifier 'num' has already been declared
}
myFunction();  // call the function

Hoisting let

Hoisting a let variable moves its declaration to the top of its scope, but without initialization.

Look at the example below.
console.log(hi); only accesses and reads the variable declaration let hi; that is hoisted to the top of its scope from the code let hi = 'hi there'; on the next line, and it outputs a reference error. Because the JS program interprets that hi is not initialized due to the hoisting syntax of let. Thus, if you attempt to use a let variable before a proper declaration (and initialization), the JS program simply doesn’t move to the next line, as opposed to var being initialized with undefined by default.

function myFunction() {
  //Uncaught ReferenceError: Cannot access 'hi' before initialization
  console.log(hi);
  let hi = 'hi there';
}
myFunction();

In other words, the JS program interprets the code above like below.

function myFunction() {
  //Uncaught ReferenceError: Cannot access 'hi' before initialization
  console.log(hi);
  let hi;
}
myFunction();

However, if you declare a let variable first and then use it, there’s no error.
As seen below, console.log(hi); prints undefined, because hi is initialized with undefined when it’s declared.

function myFunction() {
  let hi;
  console.log(hi);  // prints 'undefined'

  hi = "I have some value";
  console.log(hi);  // prints 'I have some value'
}
myFunction();

What is const?

In JS, a variable declared with const in type is block scoped, working fairly the same as let variable in that it can only be consumed within the block it’s declared and initialized.

function myFunction() {
  const hi = 'hi there';  // block scope
  console.log(hi);  // prints 'hi there'
}
myFunction();  // call the function
console.log(hi);  // Uncaught ReferenceError: hi is not defined

Also, a const variable cannot be re-declared with the same variable name as the existing one in the same block.

function myFunction() {
  const hi = 'hi there';  //block scope in a function
  const hi = 'hi there again'; // SyntaxError: Identifier 'hi' has already been declared
  console.log(hi);
 }
myFunction();  // call the function

Like let, const variable can be global or local (block scoped) to the block in which it is declared and is initialized. Let’s take a look at the following example.

function myFunction() {                  
  const hello = 'hello';  // block scope in the function
   
  // if block; an inner block in the function
  if (hello.length === 5) {  
       
    // a block scope variable in the if block
    // with the value ' consists of 5 letters.'
    const there = ' consists of ' + hello.length + ' letters.';

    // prints 'The word hello consists of 5 letters.'
    console.log('The word ' + hello + there);
  }
}
myFunction();  // call the function

The const variable hello is declared and is initialized in myFunction(), and the if statement block, that is an inner block in myFunction(), has a const variable there.
Within the if block, part of the value in there is initialized with ‘5’ by accessing hello.length, and console.log('The word ' + hello + there); successfully outputs ‘The word hello consists of 5 letters.’, which is a derive result by accessing hello globally and there locally within the function.
To emphasize again, as hello is declared and initialized in myFunction(), while it’s a block scope variable (local scope variable) to the myFunction() block, it’s also a global scope variable to any inner block within the myFunction() block.

Now, let’s move onto having a look at what differences are between const and let.
A const variable cannot be re-initialized with any new value unlike let. The keyword const is short for constant meaning that it’s fixed, immutable, or static in Maths. Thus, a const variable should be declared and be initialized at the same time as a single statement.

function myFunction() {
  const hi = 'hi there'; // valid
  hi = 'hi there again'; // TypeError: Assignment to constant variable.
  console.log(hi); 
}
myFunction();  // call the function

Also, you cannot use any const variable without initialization.

function myFunction() {
  const hi;  //Uncaught SyntaxError: Missing initializer in const declaration
  console.log(hi);
}
myFunction();  // call the function

const variable as an object

Ironically, the properties of a const object can be updated (re-initialized).
As you can see the code snippet below, the const object transaction has updated the values of its properties at the end.

function myFunction() {
  const transaction = {
    item: "apple",
    price: 2
  };
  console.log(transaction); // { item: 'apple', price: 2 }

  transaction.item = "banana";
  transaction.price = 5;
  console.log(transaction); // { item: 'banana', price: 5 }
}
myFunction();  // call the function

Hoisting const

The declaration of a const variable is hoisted to the top of its scope without initialization.

Let’s have a look at the reference error message below.
console.log(hi); knows the existence of hi as it accesses and reads the variable hi whose declaration const hi; is hoisted to the top of the function block from the code const hi = 'hi there';. However, it cannot access the value of hi since the initialization of hi is not hoisted.

function myFunction() {
  //Uncaught ReferenceError: Cannot access 'hi' before initialization
  console.log(hi);  
  const hi = 'hi there';
}
myFunction();

What about the following code snippet?
When console.log(hi); is executed, there shows a slight different error in type, apparently looking the same error as above.
The declaration of hi is still hoisted to the top of its scope, and the error this time is a syntax error “Missing initializer in const declaration” meaning that const variable must be initialized on its declaration. Thus, make sure to stick to using const variables after declaration & initialization!

function myFunction() {
  //Uncaught SyntaxError: Missing initializer in const declaration
  console.log(hi);
  const hi;  // hi is declared, but is not initialized
}
myFunction();

It may take a little time to understand JS variables, but you will soon get used to features, behaviours, and syntax of them, as far as you keep on getting your hands dirty writing JS codes!

convert your manuscript to epub (fiverr gig @whatthehekkist) convert your manuscript to epub (fiverr gig @whatthehekkist) dedicated assistance to your jekyll website, blog, portfolio, or project (fiverr gig @whatthehekkist) dedicated assistance to your jekyll website, blog, portfolio, or project (fiverr gig @whatthehekkist)



What The Hekk is HTML/CSS/JS? a complete guide to creating a web app in 5 min from scratch!

Kindle Edition

What The Hekk is HTML/CSS/JS? a complete guide to creating a web app in 5 min from scratch!

PDF






You May Also Enjoy

  • Web Dev

    Batch Image Loader

    2023-08-20

    Features lazy load batch (bulk) images zoom in an image on click load more images on every 100 entry skip broken or blocked image source URLs (src) Tech Stack Frameworks: Jekyll (Ruby) & Liquid template Frontend: HTML/CSS/JS & Jquery Data:...

  • Programming

    Image crawling with Python on Chrome browser

    2022-07-09

    Step by step insturction 1. Install selenium and beautiful soup on terminal pip install bs4 pip...

  • Web Dev

    what is switch statement?

    2023-05-26

    what is switch statement? switch statement is a conditional statement in JS (and in most programming languages) to execute a certain action over multiple inner blocks called case. switch takes an expression (input condition) that looks for a match...

  • Web Hack

    Insert screenshot into Markdown doc in a second

    2022-07-11

    What is Markdown? Markdown is a free open-source web-focused markup language that gives you hassle-free writing experiences (indeed, once you get familiar with it). As you can so easily find many of how-to-posts on syntax, structure, and so...

  • Web Dev

    Bootstrap Nav, Browser inspection, and Browser rendering process

    2023-04-23

    Bootstrap navigation Bootstrap navigation is one of the most widely used navigation templates and there are a lot of practical points that help get familiar with frontend. In this post, we are going to have a close look at...

  • Web Dev

    [Gitpod] 웹에서 코딩하기

    2022-07-12

    Gitpod은 오픈소스 원격 개발 플랫폼이다. 이미 굉장히 많은 사용자들이 있고, 이 블로그 또한 처음부터 Gitpod 사용했다. 개인적으로 생각하는 Gitpod의 가장 큰 장점은 사용자가 본인 컴퓨터에 로컬 개발환경 세팅에 시간을 너무 많이 투자해야 할 필요가 없고, 모든 걸 Gitpod이 제공하는...