8 Ways Variables Are Declared in JavaScript

8 Ways Variables Are Declared in JavaScript

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 do this :)

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 a try-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 get undefined.
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 getting undefined as we did with var, 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 the function keyword even before they are declared. For context, we will declare a function with the function keyword, and we will declare another function with the const 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.