DEV Community

Daniel Joo
Daniel Joo

Posted on

Function-level Scoping in pre-ES6

Before the introduction of const and let in ES6,var reigned supreme and was used for all declarations/identifiers. The use of var is still quite common today, either through legacy code or in new code. Although there is a lot of debate over where and when var declarations should be used, I want to show some of the pre-ES6 function scoping.

function difference(x,y) {
    if (x > y) {
        var z = x;    
        x = y;
        y = z;
    }

    return y - x;
}

In this example here, we have a function where we want the difference between the two numbers to be positive. If x is greater than y, then we assign the value of x to z, which is declared in this function scope. Then, we take steps to essentially switch the values of x and y. In the end, we return y-x, which should be a positive number.

I want to bring attention to z declaration in this function. var identifiers within functions are accessible across the whole function. They attach themselves to the nearest enclosing function, no matter where they may be within that function. So in this case, although z may have been declared in the if block, it still belongs to the function scope. Unlike let or const, var declarations cannot create their own block scope. So although z has been declared inside a block, it does not create a block scope. Also, to be completely clear, not all blocks create their own scopes as well.

Theoretically then, for the function above, we could change it so that it looks like this:

function difference(x,y) {
    var z;

    if (x > y) {
        z = x;    
        x = y;
        y = z;
    }

    return y - x;
}

This version of the function would exhibit the exact same behavior since z belongs to the function scope. One possible argument I could have against this version, however, is that putting z outside the if block would signal that it's available and ready to be used within the whole function. While this is true, it's only technically needed for the set of statements within the if block. So putting the declaration of z inside the if block would semantically show that z is only needed for the part of the function inside the if block, although functionally, nothing changes. In other words, it semantically shows that z is block scoped.

In ES6+, we could incorporate let and simply swap out var for let.

function difference(x,y) {
    if (x > y) {
        let z = x;    
        x = y;
        y = z;
    }

    return y - x;
}

In this ES6+ version, this let declaration also creates its own block scope within the if statement.

Top comments (0)