An Introduction to JavaScript variable types

An Introduction to JavaScript variable types

·

5 min read

A variable is simply a container that holds a certain value and keeps it in the memory. The value might be a string, a number, etc...

So a variable is a record in the memory that has a specific type, according to the given value. In JavaScript, the are 2 variable types and they differentiate by the way they're stored in the memory.

The 2 variable types are:

  • Primitive value types.
  • Reference type.

The primitive types are:

  • String
  • Boolean
  • Number
  • BigInt
  • Null
  • Undefined
  • Symbol

The reference type:

  • Object

Primitive types

The primitive data type values are stored directly on the memory stack. So, the variable (name) can access the location where its value is saved.

let myString = "hello world";

myString is stored in the memory in binary format, like that:

01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100

Reference type

---> functions and arrays are objects

  • The reference data type values aren't stored directly in the memory (stack) but in the heap.
    let myObj = { name: "John", age: 29, job: "marketing director" };
    
    myObj is a javascript object and as it's a reference type, it's accessed through a pointer. A pointer is simply a variable that hold the memory address of some data stored in the computer memory.

In our case, let's suppose that the pointer value to myObj is named myPtr and its value is 0x1062.

The way that javascript object value is accessed is as follow:

  • We declared a variable called myobj and gave it an object as a value.
  • The object is stored in the heap of the memory.
  • The variable name myObj doesn't refer to the memory block holding the object but to the pointer myPtr that itself holds the memory address that refers to where the object is located in the heap.

if we update myObj value to

let myObj = { name: "Emma", age: 35, job: "marketing director" };

Only the data value in the heap will change but the pointer myPtr will remain the same.

Mutability and immutability

  • An immutable data means that the data cannot be updated after it's been created. In contrast to mutable data that can be changed after its creation.
  • Primitive data types are immutable whereas reference types are mutable.
    let str = 'Hello world';
    console.log(str.toUpperCase()) // 'HELLO WORLD'
    console.log(str) // 'Hello world'
    
  • str is a String which is an primitive (immutable) data, when we called the toUpperCase method on str it generated a temporary version of the string in uppercase but it didn't change its original state.
let student = { name: 'John', age: 27, job: 'developer' };
console.log(student) // { name: 'John', age: 27, job: 'developer' }
student.location = 'USA' // updated the student object
console.log(student) // { name: 'John', age: 27, job: 'developer', location: 'USA' }
  • After creating our student object, we were still able to update its value.

Comparison in practice

let a = 5;
let b = a;
// lets reset the value of b and see what's going to happen to the value of a.
b = 10;
console.log(a); // output is 5
console.log(b); // output is 10

In the example above even though 'b' equals to the value of 'a', when updating the 'b', 'a' remains the same and that's because when we gave 'b' the value of 'a', we created a new block in the memory that contains the same value as 'a' that we can refer to it by calling 'b'. So, when we create a primitive type, we make a new memory block that contains the given value and we can access, update it or delete it through the given variable name. Now, let's see the case of the reference type.

let me = { name: 'John', age: 27, job: 'developer' };
let copyMe = me;

console.log(me); // { name: 'John', age: 27, job: 'developer' }
console.log(copyMe); // { name: 'John', age: 27, job: 'developer' }

// lets update 'copyMe' now and see what's gonna happen to 'me'.
copyMe.country = 'USA';

console.log(copyMe); // { name: 'John', age: 27, job: 'developer', location: 'USA' }
console.log(me); // { name: 'John', age: 27, job: 'developer', location: 'USA' }

Unlike the case of the primitive types, when we create a new variable whose value is a variable name of another object, then updated the new variable, it updated the original object as well. That's because the two variable names, reference to the same pointer that refers to the memory block containing the object information. So, we simply created another variable that refers to the same object. But to create an actual copy (clone) of an object, there are 3 different ways:

  • Spread operator

    let me = { name: 'John', age: 27, job: 'developer' };
    let copyMe = { ...me, };
    
  • With Object.assign() method

    let me = { name: 'John', age: 27, job: 'developer' };
    let copyMe = Object.assign({}, me);
    
  • With JSON.stringify() and JSON.parse()

    let me = { name: 'John', age: 27, job: 'developer' };
    let copyMe = JSON.parse(JSON.stringify(me));
    

Now, when we update the 'copyMe' object, the 'me' object will remain the same and that's because we created a new memory block that contains the same content as the 'me' object.

// updating the copyMe object
copyMe.location = 'USA';

console.log(me); // { name: 'John', age: 27, job: 'developer' }
console.log(copyMe); // { name: 'John', age: 27, job: 'developer', location: 'USA' }