Support Online
Skip to main content

Understanding Variables, Scope, and Hoisting in JavaScript

Login

Variables are a fundamental part of many programming languages and are one of the most important topics for beginners to learn.

Variables in JavaScript have various properties and there are rules that must be followed when naming them.
There are three keywords used to define a variable: var, let and const.
Each affects how the code interprets the variable differently.

In this guide, we will learn what variables are and how to define and name them.
We'll also take a closer look at the differences between var, let, and const.

In addition, we will examine the effects of the concept of hoisting and the importance of global and local scope in the behavior of variables.

Understanding Variables

A variable is like a named container used to store values.
If we need to use a piece of information more than once, we can keep it in a variable and call it back or change it later.

In JavaScript, the value inside a variable can be any data type: number, text (string), or object. For more, you can take a look at the JavaScript Data Types documentation.

Before the ECMAScript 2015 (ES6) standard, the only way to declare variables in JavaScript was to use the var keyword.
That's why in older code and sources you'll often only see variables defined with var.

We will soon examine the differences between var, let and const in a separate section.

For now, we can use var to denote the concept of variable.
In the example below, we will define a variable and assign a value to it.

// username değişkenine "kadir_dev" string değerini ata
var username = "kadir_dev";

This statement consists of several parts:

  • Defining the variable with the var keyword
  • Name of the variable (identifier), username
  • The assignment is indicated by the sign =
  • Assigned value, "kadir_dev"

We can now use the username variable in code.
JavaScript will remember that username represents the string value "kadir_dev".

// Değişkenin değeriyle eşit olup olmadığını kontrol et
if (username === "kadir_dev") {
console.log(true);
}
Output
true

As we mentioned before, variables can represent any JavaScript data type.

In this example, we will define variables with string, number, object, Boolean and null values.

// Farklı türlerde değişkenlerin atanması
var name = "Kadir";
var spartans = 300;
var kingdoms = [ "memeliler", "kuşlar", "balıklar" ];
var poem = { roses: "kırmızı", violets: "mavi" };
var success = true;
var nothing = null;

Using console.log we can see what value is stored inside a particular variable.

// spartans değişkenini konsola gönder
console.log(spartans);
Output
300

Variables store data in memory, which can be accessed and modified later.
A variable can be reassigned and given a new value.

In the simple example below, we will see how a password can be stored in a variable and updated later.

// password değişkenine değer ata
var password = "gizli123";

// Değişken değerini yeni bir değerle güncelle
password = "gizli456";

console.log(password);
Output
gizli456

In a real program, passwords would most likely be stored securely in the database.
This example was done just to show how we can update the value of a variable.

First the value of variable password was hidden123, then we reassigned it to hidden456.
After that JavaScript will recognize the new value for password.

Naming Variables

In JavaScript, variable names are called identifiers.
We previously talked about naming conventions in the Understanding Syntax and Code Structure in JavaScript section.
Let's remember it briefly here:

  • Variable names can only consist of letters (a-z), numbers (0-9), dollar sign $ and underscore _.
  • Spaces (tab or space) cannot be used in variable names.
  • No variable name can start with a number.
  • Some reserved keywords in JavaScript cannot be used as variable names.
  • Variable names are case sensitive.

camel case (e.g. camelCase) is commonly used in JavaScript.
That is, the first word starts with a lowercase letter, the first letter of each subsequent word is written in capital letters, and there is no space in between.
Variables identified with var or let usually follow this rule.

Variables that hold constant values ​​(i.e. those defined with const) are usually written in all capital letters.

These rules may seem like a lot at first, but they soon become second nature and writing correct, standard variable names becomes a natural reflex.

Differences Between var, let and const

There are three different keywords for declaring variables in JavaScript: var, let, and const.
This adds an extra layer of complexity to the language.

The differences between these three are; It is based on the concepts of scope, hoisting and reassignment.

KeywordScopeHoistingCan Be ReassignedRedefinable
there isFunction scopeYesYesYes
letBlock scopeNoYesNo
constBlock scopeNoNoNo

So which of these three should we use in our own programs?

Generally accepted approach:

  • const: Should be used whenever possible.
  • let: Preferred in loops or when the value needs to be reassigned.
  • var: Generally not used unless you are working with legacy code.

Variable Scope

In JavaScript, scope refers to the current context of the code and determines whether a variable is accessible.
There are two types of scope: global and local.

  • Global variables: Defined outside of a block.
  • Local variables: Defined inside a block.

In the example below we will create a global variable.

// Global bir değişken tanımla
var creature = "kurt";

We learned that variables can be reassigned.
Using local scope, we can define a new variable with the same name as an external variable. In this case, the value of the original variable does not change.

In the example below we will define a global variable species.
Inside the function, we will create a local variable with the same name.

When we print it to the console, we will see how the value of the variable differs depending on the scope and the original value does not change.

// Global bir değişken tanımla
var species = "insan";

function transform() {
// Local (fonksiyon scope) bir değişken tanımla
var species = "kurtadam";
console.log(species); // fonksiyon içindeki değeri yazdırır
}

// Global ve local değişkenleri konsola yazdır
console.log(species); // insan
transform(); // kurtadam
console.log(species); // insan
Output
insan
kurtadam
insan

In this example, the local variable is in the function scope.
Variables defined with the keyword var are always function-scoped; That is, it accepts functions as a separate scope.
Therefore, the local variable cannot be accessed from the global scope.

In contrast, the new keywords let and const have block scope.
So, in addition to function blocks, all blocks such as if, for, while form their own scope.

To demonstrate the difference between function scope and block scope, we will define a new variable using let within a if block.

var fullMoon = true;

// Global bir değişken tanımla
let species = "insan";

if (fullMoon) {
// Blok scope bir değişken tanımla
let species = "kurtadam";
console.log(`Dolunay var. Lupin şu anda bir ${species}.`);
}

console.log(`Dolunay yok. Lupin şu anda bir ${species}.`);
Dolunay var. Lupin şu anda bir kurtadam.
Dolunay yok. Lupin şu anda bir insan.

As a result of this example, both the global variable and the block-scoped variable will have the same value: werewolf.
This is because instead of creating a new local variable with var, you overwrite the same variable in the same scope.
var does not recognize block if as a new and different scope.

Therefore, it is recommended that you define your variables to be block-scoped (with let or const).
This way you are less likely to unintentionally crush variable values.

Hoisting

In the examples we have given so far, we generally defined a variable with var and then immediately assigned a value.
After definition and value assignment, we can access this variable or assign a new value.

If we try to use a variable before declaring and valuing it, the result is undefined.

// Değişkeni tanımlamadan önce kullanmayı dene
console.log(x);

// Değişkene değer ata
var x = 100;
Output
undefined

However, if we do not use the var keyword, we do not define the variable, we just assign a value.
In this case, JavaScript returns a ReferenceError and stops the script from executing.

// Değişkeni tanımlamadan önce kullanmayı dene
console.log(x);

// var kullanmadan değer ataması yap
x = 100;
Output
ReferenceError: x is not defined

This is due to hoisting.
Hoisting is JavaScript's behavior of moving variable and function definitions to the top of their scope.

However, here only declaration is moved up, initialization is not moved.
So in the first example the result returns undefined.

You can see more clearly how the code we wrote below is interpreted by JavaScript.

// Bizim yazdığımız kod
console.log(x);
var x = 100;

// JavaScript’in yorumladığı hali
var x;
console.log(x); // undefined
x = 100;

JavaScript saved the variable x into memory before the script was executed.
But since it was called without assigning a value, the result was undefined, not 100.
However, this did not throw a ReferenceError and did not stop the script from running.

In fact, the expression var is not physically carried up, but it is useful to think of it this way to understand the concept of hoisting.
This behavior can cause problems because the developer writing the code expects the output to be 100, but it actually returns undefined.

We will see how hoisting can lead to unpredictable results in the next example:

// Global scope'ta x değişkenini tanımla
var x = 100;

function hoist() {
// Normalde sonucu etkilememesi gereken bir koşul
if (false) {
var x = 200;
}
console.log(x);
}

hoist(); // undefined
Output
undefined

In this example, we defined the variable x globally as 100.
Depending on the condition if, the value x could have been 200, but since the condition was false, it shouldn't have actually affected the value.

However, due to hoisting, x was moved to the top of function hoist() and its value became undefined.

Such unpredictable behavior can lead to errors in programs.
let and const do not become hoist in this way because they have block scope.
They exhibit more reliable behavior as you will see below.

// Global scope'ta x değişkenini tanımla
let x = true;

function hoist() {
// Fonksiyon scope içinde x tanımla
if (3 === 4) {
let x = false;
}
console.log(x);
}

hoist(); // true
Output
true

It is possible to define the same variable more than once with var, but this gives an error with let and const.

// var ile tanımlanan bir değişkeni yeniden tanımlamayı dene
var x = 1;
var x = 2;

console.log(x); // 2
Output
2
// let ile tanımlanan bir değişkeni yeniden tanımlamayı dene
let y = 1;
let y = 2;

console.log(y);
Uncaught SyntaxError: Identifier 'y' has already been declared

In summary:
Variables declared with var may be affected due to JavaScript's hoisting mechanism.
This may result in undefined values ​​in the code.

let and const solve this problem.

  • They give an error when trying to use them before they are defined.
  • They do not allow defining the same variable more than once.

This ensures more reliable and predictable code writing.

Constants

Many programming languages contain constants.
These are variables whose values ​​cannot be changed.

In JavaScript, the const keyword works with this logic and the value assigned to it cannot be reassigned.

As a common usage convention, all const variables are written in capital letters.
In this way, they can be easily distinguished from other variants.

In the example below, we define a constant named SPECIES with const.
Trying to reassign this variable will give an error.

// const ile sabit bir değer ata
const SPECIES = "insan";

// Yeniden değer atamayı dene
SPECIES = "kurtadam";

console.log(SPECIES);
Output
Uncaught TypeError: Assignment to constant variable.

Variables defined with const cannot be reassigned.
Therefore, they must be given a value as soon as they are defined.
Otherwise, an error occurs.

// Bir const tanımla ama değer atama
const TODO;

console.log(TODO);
Output
Uncaught SyntaxError: Missing initializer in const declaration

In programming, values that cannot be changed are called immutable, and those that can be changed are called mutable.

Although variables defined with const cannot be reassigned, they can in fact be mutable.
That is, it is possible to change the properties of an object or array defined by const.

// İki özelliğe sahip bir CAR nesnesi oluştur
const CAR = {
color: "kırmızı",
price: 12000
}

// CAR nesnesinin bir özelliğini değiştir
CAR.price = 20000;

console.log(CAR);
// { color: "mavi", price: 20000 }
Output
{ color: 'kırmızı', price: 20000 }

Using const makes it clear to both your future self and other programmers working with you on the project that this variable is not intended to be reassigned.

If you expect a variable to be changed in the future, it would be a better choice to define it with let.

Result

In this guide, we learned what a variable is, variable naming rules, and how values can be reassigned.
We also examined the concepts of scope and hoisting, saw some limitations of the var keyword, and learned how let and const solve these problems.