Traditionally, JavaScript really only has two types of scope :
I will not elaborate on this, since there are already many other answers explaining the difference.
The most recent JavaScript specs now also allow a third scope :
Traditionally, you create your variables like this :
var myVariable = "Some text";
Block scope variables are created like this :
let myVariable = "Some text";
To understand the difference between functional scope and block scope, consider the following code :
// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here
function loop(arr) {
// i IS known here, but undefined
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( var i = 0; i < arr.length; i++ ) {
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( let j = 0; j < arr.length; j++ ) {
// i IS known here, and has a value
// j IS known here, and has a value
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
}
loop([1,2,3,4]);
for( var k = 0; k < arr.length; k++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
};
for( let l = 0; l < arr.length; l++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS known here, and has a value
};
loop([1,2,3,4]);
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
Here, we can see that our variable j
is only known in the first for loop, but not before and after. Yet, our variable i
is known in the entire function.
Also, consider that block scoped variables are not known before they are declared because they are not hoisted. You're also not allowed to redeclare the same block scoped variable within the same block. This makes block scoped variables less error prone than globally or functionally scoped variables, which are hoisted and which do not produce any errors in case of multiple declarations.
Whether or not it is safe to use today, depends on your environment :
If you're writing server-side JavaScript code (Node.js), you can safely use the let
statement.
If you're writing client-side JavaScript code and use a browser based transpiler (like Traceur or babel-standalone), you can safely use the let
statement, however your code is likely to be anything but optimal with respect to performance.
If you're writing client-side JavaScript code and use a Node based transpiler (like the traceur shell script or Babel), you can safely use the let
statement. And because your browser will only know about the transpiled code, performance drawbacks should be limited.
If you're writing client-side JavaScript code and don't use a transpiler, you need to consider browser support.
These are some browsers that don't support let
at all :
For an up-to-date overview of which browsers support the let
statement at the time of your reading this answer, see this Can I Use
page.
(*) Globally and functionally scoped variables can be initialized and used before they are declared because JavaScript variables are hoisted. This means that declarations are always much to the top of the scope.