Search code examples
ecmascript-6let

Let variables and block scope


Why does the first console log print out "James" when it should print out "Ken"? Shouldn't the let 'student' variable be scope to the 'if-statement' and retain its value as "Ken"? Also, shouldn't there be an error as I'm redeclaring the same variable name 'student'?

(function (){
    let student = {name: 'James'};
    function createStudent(name){
        if(true){
         let student = {name: name};
        }
        return student;
    }
    console.log(createStudent('Ken'));
    console.log(student);
})();

Solution

  • let is block scoped so this line of code:

    let student = {name: name};
    

    is scoped only to the brackets inside the if statement. So, when you later do

    return student;
    

    outside of the if block and outside of where the other student variable was defined, that variable is no longer in scope so the only student variable that is in scope is the James one.

    Here's an annotated version:

    (function (){
        let student = {name: 'James'};
        function createStudent(name){
            if(true){
             // define new student variable that is only in scope
             // within this block
             let student = {name: name};
            }
            // here, the student variable on the previous line is no longer
            // in scope so referencing it here sees the first declaration
            return student;
        }
        console.log(createStudent('Ken'));
        console.log(student);
    })();
    

    Shouldn't the let 'student' variable be scope to the 'if-statement' and retain its value as "Ken"?

    It is block scoped to the if statement. But, when you do the return, it's outside that block so there is no access to the Ken student variable any more so the only one that is in scope is the James one.

    Also, shouldn't there be an error as I'm redeclaring the same variable name 'student'?

    It is not an error to define a variable that was already defined in a higher scope. Instead, the new declaration shadows or hides the other declaration within that scope, temporarily overriding it within that scope.