Modern JavaScript: Let
Welcome to the Let lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
Before 2015, local variables in JavaScript were declared with the
varkeyword. When we define avarinside a function, it's only visible inside the function. We're allowed to usevarin strict mode.>
function defineX() {var x = 1;return x + 1;}defineX();Result:
2
However, trying to reference the variable outside of the function is an error.
Here's a code problem:
Reference
xoutside of the function, which will cause an error. For example, you can use aconsole.logor assignxa new value.function defineX() {var x = 1;}defineX();console.log(x);- Goal:
ReferenceError: x is not defined
- Yours:
ReferenceError: x is not defined
Functions create a variable scope. Variables defined inside the function are visible within the function, and invisible outside the function. This is good!
We expect an
ifblock to behave the same way. If we put avarinside anif (...) { ... }, we expect the variable to be visible inside theifblock, which it is:>
function f() {if (true) {var x = 1;return x + 1;}}f();Result:
2
However, the variable is also visible to the rest of the function body, even outside of the
ifblock!Here's a code problem:
Modify the function to return
x + 1.function f() {if (true) {var x = 1;}return x + 1;}f();- Goal:
2
- Yours:
2
All
vars are "function-scoped", which means that they're visible to the entire function body, no matter how they're defined within the function. This was a mistake in JavaScript's design:var x = 1inside anifshouldn't be visible outside theif. It's too easy to declare a variable, thinking that it will be local to theif, then accidentally use it later in the function.Fortunately, this problem was fixed in 2015, when
letwas introduced. Withlet, a variable defined inside theifisn't visible outside theif. Trying to access it will cause an error. (You can typeerrorwhen a code example will throw an error.)>
function f() {if (true) {let x = 1;}return x;}f();Result:
ReferenceError: x is not defined
lethandles nested scopes properly. For example, we can define anxin the function body, then define anotherxinside anif. Changing the "inner"xwon't change the "outer"x.>
function f() {let x = 'outer';if (true) {let x = 'inner';}return x;}f();Result:
'outer'
Those variables hold different values even though they have the same name. That's called "shadowing": the inner
let xshadows the outerlet x. Opinions vary on whether shadowing should be used sparingly, or avoided altogether. Our opinion is: use it sparingly, and only when all of the alternatives feel awkward.We've been using
iffor our examples, butletscoping rules apply to any block of code in curly braces, like{ ... }. For example, an outer scope can't access a variable defined inside awhile; that causes an error.>
function f() {let iterating = true;while (iterating) {let x = 1;iterating = false;}return x;}f();Result:
ReferenceError: x is not defined
We can also introduce new scopes without using a construct like
iforwhile. Any code contained in{ ... }will have its own scope.>
function f() {let x = 'outer';{let x = 'inner';}return x;}f();Result:
'outer'
Given that
lethas clearer and less error-prone behavior thanvar, we recommend that you always useletinstead ofvarwhen declaring variables.