Skip to main content

Command Palette

Search for a command to run...

Understanding Variables and Data Types in JavaScript

Every Large Building is Builded on Blocks...Let's have a look on JavaScript Blocks

Updated
β€’21 min readβ€’View as Markdown


Understanding Variables and Data Types in JavaScript

What you should already know

Nothing...Just patience and will to learn Building Blocks, When Everyone else is Vibe-Coding...

*Warning : I Have used some emojis in article to make it more interactive , so Please do not consider it is AI generated article I have really worked hard on it from my side...πŸ™πŸ™

So let's start :

JavaScript has three kinds of variable declarations.

var

Declares a variable, optionally initializing it to a value.

let

Declares a block-scoped, local variable, optionally initializing it to a value.

const

Declares a block-scoped, read-only named constant.

I hope you have not understood πŸ˜‰ because when I tried to understand this, I didn't get it either 😁... And if you have understood this, congratulations! You are really smart. But if you want to add a little more value, I hope this article will help you...

So let start from Basics :

In every programming language we write some Statement...But what are Statements ?

Statements : In a computer programming language, a statement is a line of code commanding a task. Every program consists of a sequence of statements.

But How we write Statements ?...Okk, To write Statements every programming lanuage have some syntax and we are here to understand some part of that synatx. So Here we will understand What are Variables firstly ?

Variables : We use Variables as symbolic names for values in our application.The name of variables, called identifiers, conform to certain rules.

A JavaScript identifier usually starts with a letter, underscore (_), or dollar sign ($). Subsequent characters can also be digits (0 – 9). Because JavaScript is case sensitive, letters include the characters A through Z (uppercase) as well as a through z (lowercase).

Some examples of legal names are : first_name , address20 , $credit and _age .

Declaring Variables :

We can declare Variable in Two ways :

  • With the keyword var. For example, var x = 42. This syntax can be used to declare both local and global variables, depending on the execution context.

  • With the keyword const or let. For example, let y = 13. This syntax can be used to declare a block-scope local variable. We will discuss Variable Scope Below.

Variables *should always be declared before they are used. JavaScript used to allow assigning to undeclared variables, which creates an undeclared global variable. This is an error in strict mode and should be avoided altogether.

Declaration in detail :

I have tried my best to explain these concepts in detail due to which it get's lengthy...At the time of writing this article i don't know how to write it concisely...Sorry for thatπŸ™

Var

The var statement declares function-scoped or globally-scoped variables, optionally initializing each to a value.

Let's try it :

var x = 1;

if (x === 1) {
  var x = 2;

  console.log(x);
  // Expected output: 2
}

console.log(x);
// Expected output: 2

// * If you have some doubts how this happen,they will be cleared by end of this section...keep understanding!!!. It's good to run Brain.exe 

The name of the variable to declare. Each must be a legal JavaScript identifier .

Initial value of the variable. It can be any legal expression. Default value is undefined.

The scope of a variable declared with var is one of the following curly-brace-enclosed syntaxes that most closely contains the var statement:

  • Function body

  • Static initialization block (for now understand it scope inside classes)

Or if none of the above applies:

  • The current module for code running in module mode

  • The global scope, for code running in script mode.

function foo() {
  var x = 1;
  function bar() {
    var y = 2;
    console.log(x); // 1 (function `bar` closes over `x`)
    console.log(y); // 2 (`y` is in scope)
  }
  bar();
  console.log(x); // 1 (`x` is in scope)
  console.log(y); // ReferenceError, `y` is scoped to `bar`
}

foo();

Other block constructs , including block statements, try...catch, switch, they do not create scope for var , and variables declared inside them can also be used outside the block.

eg :

for (var a of ["hello", "how", "are","you"]);
console.log(a); // you

And while writing this article I also came to know once a variable declared can't be deleted using delete as it is non-configurable as delete only delete object properties. [*This is interesting topic due to length I can't expain it in detail here...You can research it on your own πŸ˜”].
For further Understanding we have to Understand Hoisting .

Hoisting :

var declarations, wherever they occur in a script, are processed before any code within the script is executed. Declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it's declared. This behavior is called ************ hoisting,*********** as it appears that the variable declaration is moved to the top of the function, static initialization block, or script source in which it occurs.

eg .

first_name = "Peter";
var first_name;

This is implicitly understood as :

var first_name;
first_name = "Peter";

So for that reason it is recommended to declare variables at top of scopes(the top of global scope and top of functions scope) so it's clear which variables are scoped to the current function.

And also remember that only the variable declaration is hoisted, not it's initialization. The initialization happens only when the assignment statement is reached.Until then variable remain undefined but declared ):

eg.

function myfunction() {
  console.log(myVariable); // undefined
  var myVariable = 111;
  console.log(myVariable); // 111
}

It will inplicitly understood as :

function myfunction() {
  var myVariable;
  console.log(myVariable); // undefined
   myVariable = 111;
  console.log(myVariable); // 111
}

Redeclarations :

And also duplicate variable declaration using var will also not trigger any error, even in strict mode , and the variable will not lose it's value , unless the declaration has initializer.

eg .

var x = 50;
var x = 30;
console.log(x); // 30
var x;
console.log(x); // 30

And interestingly var declarations can be in the same scope as a function declaration. As you know hoisting is done before initialization so also in hoisting functions are hoisted before the variables hoisted...then initialization of var then can overrides the value of hoisted variable.

You can understand it by this example :

var a = 1;
function a() {}
console.log(a); // 1    

Here function are VIP's 😎 one to get hoisted first.

var declarations can not be in the same scope as a let, const , class or import declaration.

eg :

var a = 1;
let a = 2; // SyntaxError: Identifier 'a' has already been declared

Because var declarations are not scoped to block, this also applies to the following case :

let a = 1;
{
  var a = 1; // SyntaxError: Identifier 'a' has already been declared
}

And it does not apply to the case where let is in child scope of var , not the same scope

eg :

var a = 1;
{
  let a = 2;
}

A var declaration within a function can have the same name as a parameter.

Some gotchas in var :

Just run these code blocks either in your browser's console of IDE they will make your understanding on var more clear : )

var x = y,
  y = "A";
console.log(x, y); // I would love to see your answers...reach me at my X profile below

Be careful of the var x = y = 1 syntax β€” y is not actually declared as a variable, so y = 1 is an unqualified identifier assignment, which creates a global variable in non-strict mode.

eg :

var x = 0;
function f() {
  var x = y = 1; // Declares x locally; declares y globally.
}
f();

console.log(x, y); // 0 1

// In non-strict mode:
// x is the global one as expected;
// y is leaked outside of the function, though!

**********************And In strict mode *****************************
"use strict";

var x = 0;
function f() {
  var x = y = 1; // ReferenceError: y is not defined
}
f();

console.log(x, y);

This was all abot just var . Let's move into next one...

let :

The let declaration declares re-assignable, block-scoped local variables, optionally initializing each to a value.

Not understood...Don't worry just be focused you will get it.

So before moving further try it ...

let x = 1;

if (x === 1) {
  let x = 2;

  console.log(x);
  // Expected output: 2
}

console.log(x);
// Expected output: 1

The scope of a variable declared with let is one of the following curly-brace-enclosed syntaxes that most closely contains the let declaration:

Or if none of the above applies:

  • The current module, for code running in module mode

  • The global scope, for code running in script mode.

Now we already know about var let see in which manner let is differnet from var .

  • let declarations are scoped to blocks as well as functions.

  • let declarations can't be accessed before it's declarations...we will see it in depth and will tell you something about Temporal Dead Zone.

  • let declarations do not create properties on globalThis when declared at the top level of a script.

  • let declarations can not be redeclared by any other declaration in the same scope.

  • let begins declarations , not statements. That means you cannot use a lone let declaration as the body of a block...as there's no way to access the variable.

if (true) let a = 1; // SyntaxError: Lexical declaration cannot appear in a single-statement context

And it is interesting that let is allowed as an identifier name when declared with var or function in non-strict mode,but you should avoid using let as an identifier name to prevent unexpected syntax ambiguities.

Temporal Dead Zone (TDZ) :

Suppose you declared a variable using let , const or class then Temporal Dead Zone will be the zone from the start of the block until code execution reaches the place where the variable is declared and initialized.
While inside the Temporal Dead Zone the variable has not been initialized with a value and any attempt to access it will result in a Reference error . The variable is initialized with a value when execution reaches the place in the code where it was declared. If no initial value was specified with the variable declaration , it will be initialized with a value of undefined .
And if you remember that if we try to access the variables declared with var before they declare return a value of undefined.
The code below will make you understanding more clear :

{
  // TDZ starts at beginning of scope
  console.log(bar); // "undefined"
  console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
  var bar = 1;
  let foo = 2; // End of TDZ (for foo)
}

Using the typeof operator for a variable in it's TDZ will throw a RefernceError.

{
  typeof i; // ReferenceError: Cannot access 'i' before initialization
  let i = 10;
}

Redeclarations :

Unlike var let redeclarations cannot be in the same scope.

eg :

{
  let myVariable;
  let myVariable; // SyntaxError: Identifier 'myVariable' has already been declared
}

Also let declaration within a function's body cannot have the same name as parameter.
Same rule applies for catch.

function foo(a) {
  let a = 1; // SyntaxError: Identifier 'a' has already been declared
}
try {
} catch (e) {
  let e; // SyntaxError: Identifier 'e' has already been declared
}

And while using switch in you can also counter this error as switch is only one block.

let x = 1;

switch (x) {
  case 0:
    let foo;
    break;
  case 1:
    let foo; // SyntaxError: Identifier 'foo' has already been declared
    break;
}

And if you want to avoid this error , wrap each case in a new block element.

let x = 1;

switch (x) {
  case 0: {
    let foo;
    break;
  }
  case 1: {
    let foo;
    break;
  }
}

Examples ;

These are some examples below they will make your understanding on let more clear.

 function varTest() {
  var x = 1;
  {
    var x = 2; // same variable!
    console.log(x); // 2
  }
  console.log(x); // 2
}

function letTest() {
  let x = 1;
  {
    let x = 2; // different variable
    console.log(x); // 2
  }
  console.log(x); // 1
}

And also remember this property that on top level of programs and functions , let unlike var ,does not create a property on the global object. For example :

var x = "global";
let y = "global";
console.log(this.x); // "global"
console.log(this.y); // undefined

When we use let inside a block , let limits the variable's scope to that block. Note the difference between var , whose scope is inside the function where it is declared.

var a = 1;
var b = 2;

{
  var a = 11; // the scope is global
  let b = 22; // the scope is inside the block

  console.log(a); // 11
  console.log(b); // 22
}

console.log(a); // 11
console.log(b); // 2

However the combination of let and var below is syntax error because var not being block scoped , leading to them being in same scope. This results in an implicit re-declaration of the variable.

let a = 5;
{
   var a = 40; // SyntaxError for re-declaration
}

const :

The const declaration declares block-scoped local variables. The value of a constant can't be changed through reassignment using the assignment operator , but if const is an object it's properties can be added , updated and removed.

eg :

const number = 50;

try{
   number = 25;
} catch(err){
  console.log(err);
  // Expected output : TypeError: invalid assignment to const 'number'
  
}
console.log(number);
 // Expected output : 50

Hope you got it...now and if not we will discuss more examples.

Description :

The const declaration is very similar to let :

  • const declarations are scoped to blocks as well as functions.

  • const declarations can only be accessed after the place of their declaration is reached πŸ‘€. Remember we have discussed about Temporal Dead Zone .

  • const declarations do not create properties on globalThis when declared at the top level of script.

  • const declarations cannot be redeclared by any declaration in the same scope.

An initializer for a constant is required. It's value must be initialized in the same declaration and it makes sense that it can't be changed later.

eg:

const myVariable; // SynatxError: Missing initializer in const declaration

The const declaration creates an immutable reference ot a value. It does not mean that the value it holds in immutable. It means that the variable identifier cannot be reassigned. Means for a case where the variable is object , it means the object's contents e.g, it's properties can be altered.

You should understand const declarations as "create a variable whose identity remains constant",not "whose value remains constanat" -or , "create immutable bindings", not immutable values.

Let's have a look on some examples :

Examples

Basic const usage

Constants can be declared with uppercase or lowercase, but a common convention is to use all uppercase letters.

const MY_FAV = "JavaScript";

console.log(`I just like to talk in ${MY_FAV} πŸ™ƒ`)
// Re-assigning to a constant variable throws an error
MY_FAV = "JavaScript"; // TypeError: Assignment to constant variable

// Redeclaring a constant throws an error
const MY_FAV = "Python"; // SyntaxError: Identifier 'MY_FAV' has already been declared
var MY_FAV = 50; // SyntaxError: Identifier 'MY_FAV' has already been declared
let MY_FAV = 20; // SyntaxError: Identifier 'MY_FAV' has already been declared

Block Scoping :

It's important to note the nature of block scoping.

const MY_FAV = 7;

if (MY_FAV === 7) {
  // This is fine because it's in a new block scope
  const MY_FAV = 20;
  console.log(MY_FAV); // 20

  // var declarations are not scoped to blocks so this throws an error
  var MY_FAV = 20; // SyntaxError: Identifier 'MY_FAV' has already been declared
}

console.log(MY_FAV); // 7 

const in objects and arrays

const also works objects and arrays. Attempting to overwrite the objects throws an error "Assignment to constant variable".

const MY_OBJECT = { key: "value" };
MY_OBJECT = { OTHER_KEY: "value" };  // TypeError: Assignment to constant MY.

However, object keys are not protected, so the folowing statement is executed without problem.

MY_OBJECT.key = "otherValue";

And if you want to make an object immutable then Object.freeze() can be used.

And the same applies to the arrays.


Till now we have seen how we declare variables now let understand Data Types.

What we mean by Data Types ?

It can be understand by it's name "Data Types" that it is type of data a variable can store.

So in JavaScript we have 7 primitive DataType and 1 non-primitive DataType.

Before giving light on 7 types we should first understand what is mean by Primitive ?

So in JavaScript , a Primitive(primitive value , primitive data type) is data that is not an object and has no methods or properties.

Dynamic and weak typing

Javascript is a dynamic language. Variables in JavaScript are not directly assosiated with any particular value type, and any variable can be assigned( and re-assigned) values of all types:

eg.

let myBirthday = 14; // myBirthday is now a number
myBirthday = "fourteen"; // myBirthday is now a string
myBirthday = true; // myBirthday is now a boolean

JavaScript is also weakly typed language, which means it allows implicit type conversion when an operation involves mismatched types, insted of throwing errors.

const  myBirthday = 42; // myBirthday is a number
const result = myBirthday + "1"; // JavaScript coerces myBirthday to a string, so it can be concatenated with the other operand
console.log(result); // 421

We have 7 primitive DataType in javascript which are :

  • string

  • number

  • bigint

  • boolean

  • undefined

  • symbol

  • null

All primitives are immutable; that is , they can not be altered.Please don't be confuse primitve itself with a variable assigned to primitve value. The variable may be reassgined to a new value, but the existing value can not be changed in the ways that objects, arrays and functions can be altered. The language does not offer utilities to mutate primitive values.

All primitive types, except null, can be tested by the typeof operator. typeof null returns "object", so one has to use ===null to test for null.

All primitive types, except null and undefined, have their corresponding object wrapper types, which provide useful methods for working with the primitive values. For example, the Number object provides methods like toExponential(). When a property is accessed on a primitive value, JavaScript automatically wraps the value into the corresponding wrapper object and accesses the property on the object instead. However, accessing a property on null or undefined throws a TypeError exception, which necessitates the introduction of the optional chaining operator.

1 . Boolean

If you propose your crush there will be just two outcomes...If you are lucky one that it might be "yes" 😍and if not it will be "no"😏.

So for such cases JavaScript has special datatype for these value which is Boolean , so Boolean is a logical data type that can have only the values true or false .

And while writing Backend you will mostly use them to decide which segment of code to run at which condition.

Below is some javaScript PseudoCode which will help you to understand this concept.

***These are not truly executable code.

/* JavaScript if statement */
if (boolean conditional) {
  // code to execute if the conditional is true
}

let propose = true;
if(propose) {
  console.log("Bhai , I have proposed her πŸ™ƒ");
}
else{
console.log("Sorry, I do not have courage to propose her😭😭")

}

2 . null

A null value represents a reference that points, generally intentionally, to a nonexistent or invalid object or address.

A very famous gotcha for null is for displaying typeof of null .

console.log(typeof null); // "object"

Although it is found in category of Primtitive data type but returns "object" in case of it's typeofπŸ™ƒπŸ™ƒ.

This is considered a bug, but one which can not be fixed because it will break too many scripts...so it is like that if it's working do not touch it.

It is one of two pure primitive datatype...not it's your turn to find reason behind it🏊.

And also remember that Because JavaScript is case-sensitive, null is not the same as Null, NULL, or any other variant.

3 . undefined

It is just a primitive value automatically assigned to variables that have just been declared.

eg.

let z; // create a variable but assign it no value

console.log(`z's value is ${z}`); // logs "z's value is undefined"
  • A return statement with no value (return;) implicitly returns undefined.

  • Accessing a nonexistent object property (obj.iDontExist) returns undefined.

  • A variable declaration without initialization (let x;) implicitly initializes the variable to undefined.

  • Many methods, such as Array.prototype.find() and Map.prototype.get(), return undefined when no element is found.

4 . Number

Number just stores numbers like 54 , -56 , 59.55 .

There is a Number constructor that contains constants and methods for working with numbers.

A number literal like 58 in JavaScript code is a floating-point value, not an integer.

255 === 255.0; // true

When used as a function, Number(value) converts a string or other value to the Number type. If the value can't be converted, it returns NaN.

eg.

Number("123"); // returns the number 123
Number("123") === 123; // true

Number("sharmaji"); // NaN
Number(undefined); // NaN

Number.parseFloat() and Number.parseInt() are similar to Number() but only convert strings, and have slightly different parsing rules. For example, parseInt() doesn't recognize the decimal point, and parseFloat() doesn't recognize the 0x prefix.

Notably, when converted to integers, both undefined and null become 0, because undefined is converted to NaN, which also becomes 0.

5 . BigInt

The BigInt type is a numeric primitive in JavaScript that can represent integers with arbitrary magnitude. With BigInts, you can safely store and operate on large integers even beyond the safe integer limit (Number.MAX_SAFE_INTEGER) for Numbers.

A BigInt is created by appending n to the end of an integer or by calling the BigInt() function.

6 . String

According to mdn docs ...The String object is used to represent and manipulate a sequence of characters.

Strings can be created as primitives, from string literals.

const string1 = "A string primitive";
const string2 = 'Also a string primitive';
const string3 = `Yet another string primitive`;

There are many operation on String which we will further discuss in upcoming Blogs.

7 . Symbol

A Symbol is a unique and immutable primitive value and may be used as the key of an Object property . In some programming languages, Symbols are called "atoms". The purpose of symbols is to create unique property keys that are guaranteed not to clash with keys from other code.

Till now we have covered Primitive Data Types now let move to non-primitive one...Objects.

Object

It is used to store various keyed collections and more complex entities. Objects can be created using Object() constructor or using object initializer / literal syntax.

Nearly all objects in JavaScript are instances of Object; a typical object inherits properties (including methods) from Object.prototype, although these properties may be shadowed (a.k.a. overridden).

Changes to the Object.prototype object are seen by all objects through prototype chaining, unless the properties and methods subject to those changes are overridden further along the prototype chain. This provides a very powerful although potentially dangerous mechanism to override or extend object behavior. To make it more secure, Object.prototype is the only object in the core JavaScript language that has immutable prototype β€” the prototype of Object.prototype is always null and not changeable.

For more information about object see object.