In JavaScript, we can represent a value in its literal form, for example, 5
, true
, {a: 5, b: 6}
; or we can store the value in a variable, and anywhere we need to represent that value, we make use of the variable where we stored the value. We can think of the variable as a container for the value.
Before we can make use of a variable, it has to be declared (created). In JavaScript, there are different ways to declare variables. It is more common to say that we can declare variables in three ways, using var
, let
, or const
. But there are even more ways to declare variables in JavaScript, and if you have been writing JavaScript for a while, you may have used some (or all) of them without realizing that they were creating variables.
Generally, any statement that creates a container for a value, and makes it possible to use an identifier to reference that value, is a variable declaration. The eight ways we will explore in this article include,
var
let
-
const
function
- Function parameters
- The
catch
clause in atry-catch
statement class
import
In the following sections, we will look at how these syntaxes work, how they behave, and the scope of the variables they create. Before we proceed, let us look at what variable scope means.
What is variable scope?
Variable scope is the area in a program where a variable can be accessed. In JavaScript, there are three types of scope.
- Global scope. Variables with global scope can be accessed from anywhere in the program.
- Function scope. Variables with function scope can only be accessed in the function that houses them. This means we cannot access the variable from outside the function.
-
Block scope. Variables with block scope can only be accessed from within the block where they are defined. In JavaScript, a block is used to group zero or more statements. The statements are placed within a pair of curly braces
{}
. For example,
{
let x = 2;
let y = 5;
console.log("x + y = ", x + y)
}
With this out of the way, let us explore these different methods of variable declaration.
var
declaration
var varName = value;
// For example
var example = 45;
Variables declared with the var
keyword have the following features.
- It is optional to initialize the variable when declaring it, and we can reassign their values at any point in the program.
var example;
example = 45; // valid
- We can overwrite a variable declared with
var
with another variable declaration.
var example = 42;
console.log("first value ", example); // First value 42
var example = 75;
console.log("second value ", example); // second value 75
- Variables declared with
var
are hoisted. This means that before the execution of the code, their declaration is moved to the top of the scope where they are defined. The effect of this is that we can access the variable even before they are declared. Note that it is only the variable declaration that is moved to the top, not the initialization. This means that if we try to access the value before the declaration, we will getundefined
.
console.log("value ", example); // value undefined
var example = 75;
/* This is how JavaScript interpreted the above code */
var example;
console.log("value ", example); // value undefined
example = 75;
- Variables declared with
var
have global scope when declared outside a function, and function scope when declared inside a function.
var x = 1; // Global scope
if (true) {
console.log("inside the block, x is", x); // inside the block, x is 1
var y = 2; // Global scope
}
function foo() {
console.log("inside the function, x is ", x); // inside the function, x is 1
console.log("inside the function, y is ", y); // inside the function, y is 2
var z = 3; // function scope
console.log("inside the function, z is ", z); // inside the function, z is 3
}
foo();
console.log("outside the function, z is ", z); // ReferenceError: z is not defined
let
declaration
let varName = value;
// For example
let example = 45;
Variables declared with the let
keyword have the following features.
- It is optional to initialize the variable in its declaration, and we can reassign their values at any point in the program.
let example;
example = 45; // valid
- A variable declared with
let
cannot be re-declared in the same scope.
let example = 42;
console.log("first value ", example);
let example = 75; // SyntaxError: Identifier 'example' has already been declared
console.log("second value ", example);
- Variables declared with
let
are not hoisted. This means that if we try to access the value before the declaration, instead of gettingundefined
as we did withvar
, we will get a runtime error.
console.log("value ", example);
let example = 75; // ReferenceError: Cannot access 'example' before initialization
- Variables declared with
let
have block scope.
let x = 1; // Global scope
if (true) {
let x = 2; // block scope
console.log("declared in a block, x is", x); // declared in a block, x is 2
}
console.log("outside the block, x is ", x); // outside the block, x is 1
if (true) {
console.log("inside the block, x is", x); // ReferenceError: Cannot access 'x' before initialization
let x = 3; // block scope
}
const
declaration
const varName = value;
// For example
const example = 45;
const
has some similarities with let
. Variables declared with the const
keyword have the same scope and hoisting rules as those declared with let
. The key difference between const
and let
is that variables declared with const
must be initialized as soon as they are declared, and we cannot reassign their values at any point in the program.
const example; // SyntaxError: Missing initializer in const declaration
example = 45;
const example = 45; // valid
const example = 45;
console.log("example is, ", example); // example is, 45
example = 45; // TypeError: Assignment to constant variable.
It is important for us to note that the fact that const
variables cannot be reassigned does not imply that they are immutable. This is because their values can still be changed even though the variable itself cannot be re-assigned. This only happens with mutable values - objects and arrays.
const mutableObject = { foo: 5, bar: 6 };
console.log("mutable object, ", mutableObject); // mutable object, { foo: 5, bar: 6 }
mutableObject.foo = 43;
console.log("mutable object, ", mutableObject); // mutable object, { foo: 43, bar: 6 }
const mutableArray = [2, 3, 5];
console.log("mutable array", mutableArray); // mutable array [ 2, 3, 5 ]
mutableArray[2] = 44;
console.log("mutableArray", mutableArray); // mutableArray [ 2, 3, 44 ]
function
declaration
The function
keyword is used to declare a variable and assign a function to it. For example,
function foo(bar) {
return bar;
}
This creates a variable named foo
and assigns the function to it. This is the same as assigning a function as a value to a variable declared with the var
keyword.
var foo = function(bar) {
return bar;
}
Note.
function
only declares variables whose value is a function.
Variables declared with the function
keyword are similar to variables declared with the var
keyword in the following ways.
- It is possible to overwrite their values with another declaration
function foo(bar) {
return bar;
}
function foo(bar) {
return bar * 4;
}
console.log(foo(8)); // 32
- They have the same scope as variables declared with the
var
keyword, that is, they have global scope when declared at the top-level or in blocks, and function scope when declared inside another function.
if (true) {
function foo(bar) {
return bar;
}
}
function zoo() {
function foo(bar) {
return bar * 4;
}
console.log(foo(8)); // 32
}
zoo();
console.log(foo(8)); // 8
- They have the same hoisting rule as
var
. This means that we can call a function declared with thefunction
keyword even before they are declared. For context, we will declare a function with thefunction
keyword, and we will declare another function with theconst
keyword and try to access both before their declaration.
foo(); // I am accessible
function foo(bar) {
console.log("I am accessible");
}
bar(); // ReferenceError: Cannot access 'bar' before initialization
const bar = () => {
console.log("I am accessible");
};
Function parameters
A function parameter is a variable passed into a function that can be accessed everywhere in the function. When a function with parameters is called, and arguments are passed to the call, for each parameter-argument, a variable is created and the argument is assigned to it as its value. If you are not sure of the difference between function parameters and arguments, this article explains it.
function foo(x, y) {
return x + y;
}
console.log(foo(5, 7));
Take a look at the function defined above. When we call the function, with 5 and 7 as arguments, it creates two variables x = 5
, and y = 7
.
Variables created by function parameters have the following features.
- They can be reassigned.
function foo(x, y) {
x = 10;
return x + y;
}
console.log(foo(5, 7)); // 17
- Their values are not always initialized immediately they are declared. This behavior depends on the arguments passed to it. For example, if a function has two parameters and while calling it, we pass one argument to it, the variable that the second parameter will create will be assigned a value of undefined, and can be initialized within the function.
function foo(x, y) {
console.log("y before initialization is ", y); // y before initialization is undefined
y = 10;
console.log("y after initialization is ", y); // y after initialization is 10
}
foo(5);
- They can be overridden by another variable declaration done with the
var
keyword.
function foo(x) {
var x = 20;
console.log("x is", x); // x is 20
}
foo(5);
The variables created by function parameters are declared immediately the function is called, so we cannot access it before its declaration.
Function parameters are not hoisted to the top of the program
Function parameters are function-scoped. This means that they can only be accessed throughout the function where they are declared.
function foo(x) {
console.log("x inside the function is ", x); // x inside the function is 5
}
foo(5);
console.log("x outside the function is ", x); // ReferenceError: x is not defined
The catch
clause in a try-catch
statement
try {
throw new Error();
} catch (err) {
console.log(err);
}
A try-catch
statement is made up of a try
block and a catch
block. The content of the try
block is first executed. If an exception (or error) is thrown in the try
block, the catch
block catches the error and the content of the catch
block is executed. When this happens, JavaScript creates a variable that stores the exception (or error) caught by the catch
block. We can give the variable any name we want if we intend to make use of it. In our case, we name it err
.
This err
variable is block-scoped. This means that we can only access it in the catch
block. This variable behaves in the same way as a variable declared with the let
keyword.
class
declaration
class Foo {
constructor(bar) {
this.bar = bar;
}
}
The class
keyword creates a variable and assigns a class to it. A variable created this way behaves the same way as a variable created with the let
keyword. The above class definition is similar to this.
let Foo = class {
constructor(bar) {
this.bar = bar;
}
};
import
statement
The import
keyword is used to import live bindings that are exported from another module.
// bar.js
let foo = 8;
export default foo;
// import
import foo from "./bar.js";
console.log("foo", foo);
There are different ways to use the import
keyword to import values from another module. Each method creates a new variable in the current module and assigns it the value that it imported. The above snippet is similar to creating a variable foo
and assigning it a value of 8 which was imported from "./bar.js"
.
Variables declared this way are constants, and behave in the same way as variables created with the const
keyword.
Note.
import
declarations can only be done at the top-level of a module.
In conclusion
We have come to the end of this article. We have been able to break away from the subconscious knowledge that there are three methods of declaring variables in JavaScript, and we explored eight different ways that it is done.
It was wonderful learning all these with you.
Till we meet again,
Bye.
Top comments (5)
Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 🫰
This isn't actually quite true, there is a case you haven't covered where implicit declaration occurs ('we' didn't declare the variable). You kind of covered this with:
but I think it is worth mentioning...
Put this inside a page - it will work just fine:
You only need to explicitly declare a variable if you are in
strict
mode, where the implicit declaration shown above will not happen. The fact that explicit variable declaration is not actually required is taken advantage of in 'code golf' competitions to shorten code as much as possible.Using variables in this manner is not good practice however, as they can all end up in the global namespace (
window
in the case of the browser) - potentially creating a confusing mess.Well, I'd say that even in this example you gave, a variable was declared, and an assignment was done.
Plus, I don't think the 8 I listed covers everything. It's just 8 Ways of Declaring Variables, not All Ways of Declaring Variables. So I explored 8 of the ways, and it's a good thing you mentioned one other, and there could even be more. The main aim was to make us understand that there are more instances where variables are declared, other than the most common three -
var
,let
, andconst
.Thanks again for your observation.
A variable was declared, yes, but implicitly. It's important to know that JS will do this
I agree with you. I'll just rephrase the paragraph. Thanks for pointing it out.