Back to the basics: Primitive and Object types in Javascript
Tags: javascript, webdev, beginners, codenewbie
Published: 2021-03-29 18:42:21

Hello everyone 👋

I was watching the video [Object-oriented Programming in JavaScript: Made Super Simple | Mosh](https://www.youtube.com/watch?v=PFmuCDHHpwk) from Mosh Hamedani and I thought it may be nice to share what I'm learning/reviewing. That's why I'm planning a series of posts to cover some concepts as a way to learn more about the topics and hopefully help some people as well.

In this article I will cover Javascript Types and their differences.

## Javascript Types

There are eight data types in Javascript:

1. string
2. number
3. bigint
4. boolean
5. undefined
6. null
7. symbol
8. Object

The first 7 of them are commonly called **Primitive Types** and everything else are **Object Types**.

## Primitive Types

They can only store a single data, have no methods and are **immutable**.

_Wait, How come? They are mutable..._ Actually, they are not. We usually confuse the primitive value itself with the variable we assign the primitive value. See below:

```javascript
// We cannot mutate the string
let car = "car"
console.log(car) // car
car.toUpperCase()
console.log(car) // car
car[0] = "b"
console.log(car) // car

// But we can assign a new value to the same variable
car = car.toUpperCase()
console.log(car) // CAR
```

The variable can be reassigned a new value but the existing value of the primitive cannot be changed like we do with arrays or objects.

So this is one of the main differences between both types:
**Primitive Types are immutable and Object Types are mutable**.

_Aah, okay. Got it! But what about that they don't have methods if you've just used one?_

That's another interesting point! `Primitive Types` have no methods but, except for `null` and `undefined`, they all have object equivalents that wrap the primitive values then we're able to use methods.

For `string` primitive there is `String` object, for `number` primitive there is `Number`, and so there are `Boolean`, `BigInt` and `Symbol`.

Javascript automatically converts the primitives to their corresponding objects when a method is to be invoked. Javascript wraps the primitive and call the method.

See below how a `String` object is with its primitive value and `__proto__`(which is beyond our scope here but it's related to its object prototype) with the associated methods:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gi0fw65yc3tpid5ioapj.JPG)

That's how we can access properties like `length` and methods like `indexOf` and `substring` when working with `string` primitives.

When Javascript wraps them with their corresponding objects, it calls the `valueOf` method to convert the object back to the primitive value when Javascript finds an object where a primitive value is expected.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wv9127ydlnuj4h5wuzgv.JPG)

## Object Types 

Differently from the primitives, Objects can store collections of data, their properties, and are **mutable**.

```javascript
// We can mutate objects without needing to reassign the variable
let cars = ["bmw", "toyota"]
console.log(cars) // ["bmw", "toyota"]
cars.push("tesla")
console.log(cars) // ["bmw", "toyota", "tesla"]

let car = { brand: "tesla" }
car.year = 2021
console.log(car) // { brand: "tesla", year: "2021" };
```

Examples of `Object` types are Array and Object. Different from `Primitive Types` they have built-in methods. You can see below how an array and object is shown here on the browser with some of their methods:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f5agoeju671l6h0mx3xd.jpeg)

As crazy as it seems, `functions` are actually objects too, they are `Function` objects, which are callable.

Just to illustrate that and for curiosity, see how functions could also be created:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pt8nz01421zuy7nryrbo.png)

This is just for educational purpose since it is not recommended to use it like this and there are problems with closures as shown [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function).

Okay, we learned a bit more about these types so let’s see some of the differences when working with them.

# Differences between types

### 1. Assigning to a variable and copying value

The difference in the way the values are stored in variables is what makes people usually call `Object Types` as `Reference Types`.

#### Primitive Types

When we assign a primitive type to a variable, we can think of that variable as _containing_ that primitive value.

```javascript
let car = "tesla"
let year = 2021

// Variable - Value
// car      - "tesla"
// year     - 2021
```

So when we assign this variable to another variable, we are copying that value to the new variable. Thus, **primitive types are "copied by value"**.

```javascript
let car = "tesla"
let newCar = car

// Variable - Value
// car      - "tesla"
// newCar   - "tesla"
```

Since we copied the primitive values directly, **both variables are separate and if we change one we don't affect the other**.

```javascript
let car = "tesla"
let newCar = car

car = "audi"

// Variable - Value
// car      - "audi"
// newCar   - "tesla"
```

#### Object Types

With `Object Types` things are different. When we assign an object to a variable, the variable is given a **reference** to that value. This reference stores the `address` to the location of that value in memory(techically more than that but let's simplify). So the variable doesn't has the value itself.

Let's imagine the variable, the value it stores, the address in memory and the object in the comming snippets:

```javascript
let cars = ["tesla"]

// Variable - Value                 - Address - Object
// cars      - <#001> (The reference) - #001    - ["tesla"]
```

This way, when we assign this variable to another one we are giving it the reference for the object and not copying the object itself like it happens with the primitive value. Thus, **objects types are "copied by reference"**.

```javascript
let cars = ["tesla"]
let newCars = cars

// Variable  - Value                 - Address - Object
// cars      - <#001> (The reference) - #001    - ["tesla"]
// newCars   - <#001> (The reference stores the same address)

cars = ["tesla", "audi"]

// Variable  - Value                 - Address - Object
// cars      - <#001> (The reference) - #001    - ["tesla", "audi"]
// newCars   - <#001> (The reference stores the same address)

console.log(cars) // ["tesla", "audi"]
console.log(newCars) // ["tesla", "audi"]
```
Both of them have references to the same array object. So **when we modify the object from one of the variables the other will also have this change**.

## 2. Comparison

Understanding the differences of what is stored in variables when dealing with primitive and object types is crucial to understand how we can compare them.

#### Primitive Types

Using the strict comparison operator `===`, if we compare two variables storing primitive values **they are equal if they have the same value**.

```javascript
let year = 2021
let newYear = 2021

console.log(year === 2021) // True
console.log(year === newYear) // True
```

However, if we compare two variables which were assined `Object Types`, we are actually comparin two references instead of their objects. So **they are equal only if they reference the exactly same object**.

```javascript
let cars = ["tesla"]
let newCars = ["tesla"]

console.log(cars === newCars) // False
console.log(cars === ["tesla"]) // False

// Now we copy the reference of cars to newCars
newCars = cars
console.log(cars === newCars) // True
```
Even though, in the beginning of the code snippet we were working with the same content in the arrays the variables didn't have the same references, they had references to different array objects in memory. However, after we copied the reference to `newCars`, since now they are "pointing" to the same object the evaluation is `True`.

So, to compare objects we cannot simply use the `===` operator because even though they might have the same properties they may not reference the same object. There are some ways to do that and so I'd recommend you to read this [article](https://dmitripavlutin.com/how-to-compare-objects-in-javascript/).

## 3. Passing to functions

When we pass primitive or object types to functions it's like we are copying their values/references to the functions parameters as if we were assigning them with `=`.

Since we have seen that when we assign them to new variables we are either copying their value(for primitive types) or reference(for object types), it's easier to understand what happens with functions and their outside scope.

#### Primitive Types

When we are passing `Primitive Types` to functions we're copying their values to the functions parameters so it doesn't affect the initial variable in the outside scope.

```javascript
let year = 2021
function getYearWithoutCovid (freeYear) {
    freeYear = 2022
    return freeYear
}

const newYear = getYearWithoutCovid(year)
console.log(year) // 2021
console.log(newYear) // 2022
```

Passing `year` to the function, we are copying its value to the function parameter(`freeYear` will be 2021) so the original variable is not affected.

#### Object Types

With `Object Types`, we are copyin their references when passing them as functions parameters. So, if we change the object inside the function this will also be seen in the outside scope.

```javascript
let person = { name: "Paul", status: "unemployeed" }
function getAJob (person) {
    person.status = "employeed"
    return person
}

const newPerson = getAJob(person)
console.log(person) // { name: "Paul", status: "employeed" }
console.log(newPerson) // { name: "Paul", status: "employeed" }
```

When we pass `person` to the function, we are copying its reference to the function parameter, not its object value. Changing it inside the function will affect the initial object in the outside scope since both variables have references to the same object.

That's why its recommended to use `Pure Functions` in this case (which are not in the scope of this article but I encourage you to search about it <3). We then create a local copy of that `person` inside the function and modify it instead of the object passed.


# Conclusion

I hope that with this article you could understand a little bit more about the data types in Javascript and could also learn the key differences between them.

I just tried to share what I learned while reviewing these concepts so there are more things to add but I thought this was an educational way to explain. If you have things to add and discuss leave a comment :) If it helped you somehow leave a heart <3

Also, follow me on [Twitter](https://twitter.com/CR_Rafael22) if you want, might share nice things there too :)

# References

https://262.ecma-international.org/11.0/#sec-ecmascript-data-types-and-values
https://flaviocopes.com/difference-primitive-types-objects/
https://dmitripavlutin.com/value-vs-reference-javascript
https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0
https://codeburst.io/javascript-essentials-types-data-structures-3ac039f9877b#01e0
https://mattgreer.dev/blog/javascript-is-a-pass-by-value-language/
https://developer.mozilla.org/en-US/docs/Glossary/Primitive
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf