How to define a variable
There are three different ways to define a variable in JavaScript, using the keywords let
, const
, and var
.
The let variables
let
defines a mutable variable, meaning you can change the value after it has been declared. For example,
1let variable = 123;
2
3variable = null;
4console.log(variable);
5
6variable = 0;
7console.log(variable);
8
9variable = "John Doe";
10console.log(variable);
1null
20
3John Doe
Using let
, you are allowed to declare the variable first, and then assign a value later. Before the value is assigned, the variable will be automatically assigned undefined
.
1let variable;
2console.log(variable);
3
4variable = 123;
5console.log(variable);
1undefined
2123
The const variables
const
, on the other hand, defines an immutable constant. If you try to change its value, an error will be returned.
1const variable = 123;
2
3variable = 100;
4console.log(variable);
1/Users/. . ./index.js:3
2variable = 100;
3 ^
4
5TypeError: Assignment to constant variable.
6 at Object.<anonymous> (/Users/. . ./index.js:3:10)
7 . . .
8
9Node.js v21.6.0
With const
, you cannot declare the variable first and then assign the value later.
1const variable;
2
3variable = 100;
4console.log(variable);
1/Users/. . ./index.js:1
2const variable;
3 ^^^^^^^^
4
5SyntaxError: Missing initializer in const declaration
6 at internalCompileFunction (node:internal/vm:77:18)
7 . . .
8
9Node.js v21.6.0
However, object is a special case. After defining a const
with an object, you are not allowed to assign it to a different object:
1const obj = {
2 name: "",
3};
4
5obj = {
6 name: "John Doe",
7};
8
9console.log(obj);
1/Users/. . ./index.js:5
2obj = {
3 ^
4
5TypeError: Assignment to constant variable.
6 at Object.<anonymous> (/Users/. . ./index.js:5:5)
7 . . .
8
9Node.js v21.6.0
But you can change the properties inside the object.
1const obj = {
2 name: "",
3};
4
5obj.name = "John Doe";
6
7console.log(obj);
1{ name: 'John Doe' }
The var variables
The var
keyword is the legacy method of defining a variable. In terms of mutability, it behaves just like let
. You can change its value after being declared.
1var variable = 123;
2
3variable = 100;
4console.log(variable);
1100
The feature that makes var
unique has to do with its scope. var
cannot be block-scoped. It can only be either function-scoped, or global-scoped.
To understand what this means, we have to first discuss what is a scope.
Variable scope
The scope refers to the section of the code where a variable is accessible.
A variable defined inside a block (if
statement, for
loops, functions...) is only accessible from within that block. It is called a local variable. For example,
1if (true) {
2 let local = 100;
3 console.log(local); // -> 100
4}
5
6console.log(local); // -> Error
1100
2/Users/. . ./index.js:6
3console.log(local);
4 ^
5
6ReferenceError: local is not defined
7 at Object.<anonymous> (/Users/. . ./index.js:6:13)
8 . . .
9
10Node.js v21.6.0
A variable defined in the parent block is also accessible in the child block.
1if (true) {
2 const parent = 100; // This variable is defined in the parent
3
4 function child() {
5 console.log(parent); // But it is accessible in the child block
6 }
7
8 child();
9}
1100
However, a variable defined in the child block will not be accessible in the parent block.
1if (true) {
2 function child() {
3 const local = 100; // This variable is defined in the child block
4 }
5
6 console.log(local); // It cannot be accessed in the parent block
7}
1/Users/. . ./index.js:6
2 console.log(local); // It cannot be accessed in the parent block
3 ^
4
5ReferenceError: local is not defined
6 at Object.<anonymous> (/Users/. . ./index.js:6:15)
7 . . .
8
9Node.js v21.6.0
A variable defined outside of any blocks is a global variable, and it will be accessible anywhere in the file.
1let global = 100; // This is a global variable
2
3console.log(global); // It is accessible here
4
5if (true) {
6 console.log(global); // Here
7
8 function child() {
9 console.log(global); // And here
10 }
11
12 child();
13}
1100
2100
3100
However, variables defined with var
works differently. A var
variable defined in a function would be local to that function.
1if (true) {
2 function child() {
3 var local = 100; // This variable is defined in a function block
4 console.log(local); // It can be accessed from within the function
5 }
6
7 child();
8
9 console.log(local); // But not here
10}
1100
2/Users/. . ./index.js:9
3 console.log(local); // But not here
4 ^
5
6ReferenceError: local is not defined
7 at Object.<anonymous> (/Users/. . ./index.js:9:15)
8 . . .
9
10Node.js v21.6.0
However, a var
variable defined in any other blocks will be a global variable and accessible anywhere.
1if (true) {
2 if (true) {
3 var global = 100; // This variable is defined in an if block, but it is actually a global variable
4 console.log(global); // So it is accessible here
5 }
6
7 console.log(global); // Here
8}
9
10console.log(global); // And here
1100
2100
3100
var
is the legacy method of declaring variables, and you should not use it in your code. We are only covering it here because it is used in some of the older software. But today, the block-level variables like let
and const
have become the industry standard.
Nested functions and closure
Think about this example:
1function parent() {
2 let num = 123;
3
4 return function child() {
5 console.log(num);
6 };
7}
Inside the parent()
function, we defined a variable num
and a child()
function. The child()
function will be returned as the parent()
function's output.
The child()
will have access to all the variables defined in the parent()
.
1function parent() {
2 let num = 123;
3
4 return function child() {
5 console.log(num);
6 };
7}
8
9let x = parent();
Now, this is where things get interesting. Here we called the function parent()
, and its output, the child()
function, will be assigned to x
. At this point, the parent()
has reached the end of its life cycle. The return
statement has been executed, and the function has been terminated.
So the question is, would the child()
function still have access to the variable num
? After parent()
has been terminated?
For many other programming languages, the answer would be no. The variables inside a function's scope only live as long as the function itself. After the function has been terminated, the variables will be cleared.
But for JavaScript, there is something called closure. It is basically an environment that allows the child functions to have access to the variables of the parent function, even after the parent is terminated.
The closure allows us to do this:
1function parent() {
2 let variable = 123;
3
4 return function child() {
5 console.log(variable);
6 };
7}
8
9let x = parent();
10
11x(); // <- This is not possible in many other programming languages
1123