So then we've seen most of the types in JavaScript.
Now all these different things down here, we've still not touched on symbols yet, but we will cover
that in a later chapter.
So now we know a bit more about objects.
I'd like to introduce the idea of primitive and reference types.
Now, I don't want to get too bogged down with this right now and we will be revisiting it later.
But I do want you to understand the basic concepts.
So then what are primitive types and what are reference types?
Well, in JavaScript, primitive types are numbers, strings, booleans, null, undefined and symbols.
So that's six out of the seven types in JavaScript that are primitive types.
Now reference types are the object type, so any kind of object object literals arrays, functions,
dates and all other objects like the math object, these all fall under the object category, the object
type, and they are all reference types.
So we have primitive types and reference types.
But what does this mean exactly?
What is the difference between primitive types and reference types?
Well, it's all to do with how they are stored and used in memory.
So when we create a primitive value, like a new string or a new number or a boolean, and we assign
it to a variable, that value is stored on something called the stack like this.
Now the stack is just a stack of different values in memory and they can be accessed pretty quickly
when we need to use one.
But the space inside the stack is quite limited.
So when we create a reference type like an object literal or an array that is stored not on the stack,
but on what is known as the heap.
Now the heap has more space available so it can hold bigger and more complex types like objects and
arrays.
But it's a bit slower too.
So primitive types are stored on the stack, which is a bit quicker and reference types are stored on
the heap.
That's two different parts of memory for two different things.
But why is this so important?
Well, when we store a primitive value in a variable, it adds that value to the stack and it locks
the variable name to it as an accessor to that value.
So it knows whenever we want to access the variable score, for example, to go out and grab this value
for us.
So when we store a reference type in a variable like an object, it adds the object to the heap and
then it adds a pointer to that object on the stack.
So say for example, we make an array, it adds that array to the heap and we store this array in a
variable.
It adds a pointer to that array in the stack, and then it locks this variable name names to the pointer.
So when we access this variable in the future, it knows to get this pointer which points to this thing
on the heap and it grabs that array for us.
Now you might still be thinking that this is not important at all, but it is and it does have ramifications
and it will affect the way that we code.
So let's just go back to virtually an empty stack and an empty heap.
Now imagine we create this variable score one and we set it equal to a number 50.
Now this is a primitive type, so it's stored down here on the stack and the variable name is locked
to that value.
So when we try to access it in the future, it knows to grab this value.
Now, what if we make a copy of this variable?
If we create a new constant called Score two and we set it equal to score one?
Well, what that does, because this is a primitive type and primitive types are stored on the stack.
It creates a copy of the number and it stores that number separately on the stack.
And this variable name score two is now locked to this new number.
So we have two values now, two different values.
Well, they're the same, but they're two different positions in memory on the stack.
And we have two different variables locked into those.
So in the future, if we were to say score one is now equal to 100, it just updates this value down
here, which is attached to the score one variable.
It doesn't affect this.
This is still 50 and that's completely normal behavior, probably something you would expect to happen.
Now, what if we do this with different types of data reference types?
Well, imagine we create a new constant user one and set it equal to an object.
Well, that object is then stored on the heap because this is a reference type.
Now we have a pointer to that object on the stack and the variable name user one is locked in to that
pointer.
So in the future, if we try to access user one, it's going to find this pointer which points to the
object and return this object back to us.
Now if we create a copy of user one, if we say a new variable, user two is equal to user one, what's
going to happen?
Well, it doesn't create a new object on the heap this time.
What it does is it copies the pointer, doesn't copy the object on the heap, it copies the pointer
and we have our new variable user two locked to this.
New pointer.
So they both point now to the same object on the heap.
So if in the future I now say, okay, well user one is now going to get updated, I'm going to change
the score to 50.
So now this new object is stored on the heap.
And what that means is if we access user one in the future, it's going to get this pointer which points
to the object and bring back this object.
If we access user two, it gets this pointer.
This also points to the same object and that gets that object as well.
So when we update user one, it's also really updating user two because they both point to the same
object.
So this might not be the behavior that you'd expect when you first come to JavaScript.
When we make copies of primitive values like strings and numbers and booleans, we make a new copy of
the value on the stack.
When we try to make a copy of a reference type, we only make a copy of the pointer on the stack, which
points to the same data on the heap.
We don't make a copy of the actual data, so when we then change the copies, it does have an effect
on the original value and vice versa.
So let's see what this means in the code.
So let's take what we've just learned about primitive and reference types and see in action.
So, you know, when we come across this kind of behavior in the future, what's going on?
So primitive values.
First of all, I have right here a variable score one, and we've set it equal to 50.
Then I'm making a copy of that variable.
I'm saying let this new variable score to equal to score one.
Now remember, that creates a copy of that value and stores it separately on the stack because this
is a primitive value.
Now down here, I'm just logging to the console, a template string where we're outputting score one
and also score two.
So let's have a look at this.
They should both be 50, right?
Score one is 50 and score two is 50.
Okay, now imagine we changed score one.
So let's do that.
Let's say now score one is equal to 100.
And now I'm going to just grab this and paste it down here again so we have it output before the change
and after the change.
So if we save it, we can see that score one after the change is now 100 and score two is still 50.
So when we make a copy of primitive values like this, if we change one of them, it doesn't affect
the other.
Now let's comment this out and come down to a reference value.
So a reference types.
So down here I've created a variable or rather try to I'll use a const keyword there and a const keyword
here as well.
And what I'm doing now is creating a new object and that has a name and an age property.
Then I'm creating a copy of that variable of that object.
User two We're setting it equal to what user one is.
So remember, this is a reference type, it's an object.
So this object is stored on the heap and we get a pointer locked to this variable stored on the stack.
Now when we create a copy, it doesn't copy the actual object, it just copies the pointer on the stack.
And then user two is locked to that new pointer.
But they both still point to this same object.
Now when we log both of these users out down here, we should see the same object and we do Ryu and
Ryu 30 and 30.
Now then, if I try to change the name of one of these and I'll just do that by saying user one dot
age is now equal to 40 or something like that.
Then if I copy this again and paste it down here, we can see that now it changes both of them.
They're both now 40 because remember it's only stored once on the heap.
So if we change that value, it's changing it on the heap.
And then both of these pointers, User one and user two are pointing to that same object.
So if we update one, it updates the other and it doesn't matter if I update 1 or 2 here because they're
both pointing to the same thing.
If I change this to two, we're still going to get exactly the same result and we could do something
instead like the name.
We'll change the name to Chun-li.
So let's do that right here.
Save it.
And now we can see they both are Chun-li.
Okay, so that is primitive and reference types.
This is the kind of behavior you need to watch out for in the future when you're coding, because you
might do this at some point thinking that now we have two completely separate values when we make a
copy, but in fact we don't because they're reference types and they're stored once with two separate
pointers.
So that's the basics of primitive and reference types.
Whenever this will be affecting our code in the future, I will be sure to warn you.