DEV Community

Cover image for JS: VAR, LET, and CONST feat. Hoisting
Anthony DiPietrantonio
Anthony DiPietrantonio

Posted on • Edited on

JS: VAR, LET, and CONST feat. Hoisting

TLDR at bottom.

If you're reading this, you're probably just starting your journey into the exciting(❓😅) world of Javascript OR you're just coming back for a refresher — and that is 🆗!

Understanding the difference between var, let, and const is likely one of the first things you'll encounter as you learn Javascript. But first... hoisting.

Hoisting

When we refer to "hoisting" we are talking about when a variable or function is "brought to the top" of your code. The quotes around "brought to the top" are there for a reason — your code is not actually moved, but simply added to memory so that your code knows about variables and functions before a single line of code is actually executed, so that when your code executes or evaluates a variable or function, it already knows about it/knows you created it. It is the reason we are able to do something like this:

Your Code

sayName("Mike")

function sayName(name){
    console.log("My dog's name is" + name)
}

// returns "My dog's name is Mike"
Enter fullscreen mode Exit fullscreen mode

Your Code Interpreted

//function sayName is hoisted("brought to the top") here.. to the top of your code
sayName("Mike") //allowing you to use it here, even though the function itself is below it

function sayName(name){
    console.log("My dog's name is" + name)
}

// returns "My dog's name is Mike"
Enter fullscreen mode Exit fullscreen mode

Note: Only variable DECLARATIONS are hoisted. The variable will NOT be initialized/have a value until given one in execution. Check code snippets below:

Your Code

var firstName = "Mike"

console.log(`My name is ${firstName} ${lastName}.`)

var lastName = "Smith"
Enter fullscreen mode Exit fullscreen mode

Your Code Interpreted

//firstName and lastName declarations are hoisted("brought to the top") here
var firstName = "Mike"

console.log(`My name is ${firstName} ${lastName}.`)
// returns "My name is Mike undefined" as lastName was not initialized with "Smith" yet, but
// your code knows it exists / was declared.

**//Note: for let and const declarations, lastName will trigger a ReferenceError and will NOT
//return undefined as it did with var declaration**

var lastName = "Smith"

console.log(`My name is ${firstName} ${lastName}.`)
//returns "My name is Mike Smith" because lastName was finally initialized / given a value
Enter fullscreen mode Exit fullscreen mode

Whether it is a variable or a function, it is always "brought to the top" (hoisted) of the context/scope that it is defined in. For example, in the code snippets above we were just writing them loosey goosey outside of any functions or blocks, so our variables and functions were being hoisted globally, rather than inside of another function or block (note: var is NOT block scoped, it is only globally or functionally scoped) Meaning:

var dogName = "Mike" 
function sayName(name){
    var owner = "Tony"
    console.log("The name of " + owner +"'s dog is " + name)
}

console.log(dogName) 
// returns "Mike"
console.log(owner) 
// ReferenceError: owner is not defined
// ^ this because owner is only accessible / scoped to inside of our sayName function

sayName(dogName)
// returns "The name of Tony's dog is Mike"

if (dogName === "Mike"){
    var dogName = "Lucas" 
        // remember that var is NOT block scoped, so we are actually reassigning dogName here
}
//SO....
sayName(dogName)
//returns "The name of Tony's dog is Lucas"
Enter fullscreen mode Exit fullscreen mode

https://media.giphy.com/media/l0MYwsjZt5Mrwyva8/giphy.gif

PHEW. OK..

🥁 The moment you've all been waiting for

As of ES6, we can now make use of two other declarations for our variables: let and const. They are similar to var, but protect us from a lot of the tricky bits that come with var as we saw above.

TLDR: Differences of VAR, LET, and CONST

VAR

  • Global / functional scope (see code snippet above)
  • can be redeclared

    var five = "five"
    var five = "five, but a new five :)"
    // no errors
    
  • can be reassigned

    var five = "five"
    five = "five, but a new five :)"
    console.log(five) // returns "five, but a new five :)"
    //no errors
    

LET

  • Block scoped

    let dogName = "Mike" 
    if (dogName === "Mike"){ 
        let dogName = "Lucas" // this is NOT THE SAME / NOT overwriting dogName from above!
        console.log(dogName) // returns "Lucas"
            // dogName inside of the if-statement is block scoped.
    }
    console.log(dogName)
    //returns "Mike" since we are out of the if-statement and referring to the first dogName
    
  • can not be redeclared

    let five = "five"
    let five = "five, but a new five :)"
    //SyntaxError: Identifier 'five' has already been declared
    
  • can be reassigned

    let five = "five"
    five = "five, but a new five :)"
    console.log(five) // returns "five, but a new five :)"
    //no errors
    

CONST

  • Block scoped

    const dogName = "Mike" 
    if (dogName === "Mike"){ 
        const dogName = "Lucas" // this is NOT THE SAME / NOT overwriting dogName from above!
        console.log(dogName) // returns "Lucas"
            // dogName inside of the if-statement is block scoped.
    }
    console.log(dogName)
    //returns "Mike" since we are out of the if-statement and referring to the first dogName
    
  • can not be redeclared

    const five = "five"
    const five = "five, but a new five :)"
    //SyntaxError: Identifier 'five' has already been declared
    
  • can not be reassigned

    const five = "five"
    five = "five, but a new five :)"
    //TypeError: Assignment to constant variable
    
  • CAN BE MUTATED

    const numbers = [1,2,3,4]
    
    // 🚫 this doesn't work
    const numbers = [4,3,2,1] 
        // returns Uncaught SyntaxError: Identifier 'numbe' has already been declared
    
    // 🚫 neither does this
    numbers = numbers = [4,3,2,1] 
        // returns Uncaught TypeError: Assignment to constant variable.
    
    // ✅ but this does 
    numbers.push(5)
    console.log(numbers) // returns [1,2,3,4,5]
    
    //Same for Objects
    
    const idCard = {
        firstName: "Tony",
        lastName: "Smith",
    }
    
    // 🚫 this will not work.. returns TypeError: Assignment to constant variable.
    idCard = {
      firstName: "Mike",
        lastName: "Jordan",
    }
    
    // ✅ this works
    idCard.firstName = "Tom"
    idCard.eyeColor = "blue"
    console.log(idCard)
    //returns { firstName: 'Tom', lastName: 'Smith', eyeColor: 'blue' }
    

As always, refer to MDN for more info:
Hoisting: https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
VAR: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
LET: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
CONST: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Feel free to reach out on any of my socials for questions, feedback (good and bad), or just to connect / say hello 👋.

Top comments (0)