In Javascript there are 2 categories of data types:
1- Primitive data types:
All primitives are immutable (unchangeable) 🛌, there are 7 primitive data types:
-
Number
: for numbers of any kind: integer or float. -
String
: may have zero or more characters. -
Boolean
: has only two values (true and false). -
Null
: for unknown values – a standalone type that has a single valuenull
. -
Undefined
: for unassigned values – a standalone type that has a single valueundefined
. -
Symbol
: for unique identifiers. -
BigInt
: is for integer numbers of arbitrary length.
2- Non-Primitive data type:
Non-primitive is mutable (changeable) 🦎, there is only one non-primitive data type:
-
Object
: for more complex data structures.
Arrays and functions in JavaScript belong to the object
data type.
Let's dive deeper into these data types
Look at this code, I will use a string (primitive) and an array (non-primitive).
var str = 'Berlin'
var arr = [1,2,3]
You can access the value inside them by the same way
console.log(str[0]) // 'B'
console.log(arr[0]) // 1
You can change array's item, like this..
arr[0] = 5
console.log(arr[0]) // 5
What about a string? can we do the same and change any char in this string?
str[0] = 'G'
console.log(str) // ??
So here is the point, you can't do that with string 🙅♂️.
Because a string is a primitive data type. And you can't change any primitive value.
str[0] = 'G'
console.log(str) // 'Berlin'
What about this case?
var city = 'Berlin'
city = 'Frankfurt'
console.log(city) // ??
The variable may be reassigned a new value, but the existing value can't be changed in the ways that objects, arrays, and functions. Immutability here doesn't make any effect, look how this happens..
Here we assign a brand new value 'Frankfurt', so there is no problem.
What about this case?
function square(x){
x = x * x
}
var num = 10
square(num)
console.log(num) // ??
In this case, square()
will only ask, what the value of variable num
? then it receives this value as argument.
So square()
will not effect the value of num
.
console.log(num) // 10
Now we are in objects phase, let's explore it.. 🔭
var num1 = 5, num2 = 5, obj1 = {}, obj2 = {};
console.log(num1 === num2) // ?
console.log(obj1 === obj2) // ?
In primitive data types, if we have 2 variables with the same value, so they both will pointing to this value, like this..
But with objects (non-primitive) it's different, every time we assign object {} to a variable, Javascript will create a brand new object value. The same goes for array, dates, functions and other objects, look how..
The image above explain us this answers.
console.log(num1 === num2) // true
console.log(obj1 === obj2) // false
Let's dive deeper in objects to see how they are mutable!
var car1 = {
model:'G 63',
brand: {
name: 'Mercedes'
}
}
var car2 = {
model:'GT 63 S',
brand: car1.brand
}
car2.model = 'GT Coupe'
car2.brand.name= 'Audi'
console.log(car1.model); // ?
console.log(car1.brand.name); // ?
console.log(car2.model); // ?
console.log(car2.brand.name); // ?
Let's break this problem down to figure out the answers..
1- First object's draw:
2- Second object's draw:
3- Then 2 changes:
As you saw, we can change the properties value within the object, this is called 'Mutation'.
console.log(car1.model); // "G 63"
console.log(car1.brand.name); // "Audi"
console.log(car2.model); // "GT Coupe"
console.log(car2.brand.name); // "Audi"
Well done, diver, you are in an interesting area. Go on.. 👏
var city = {
name:'München',
}
var _location = {
state:'Bavaria',
}
console.log(_location.name); // ?
Yes, as you said the answer is undefined
, but how do we access property name
from object location
?
First off, let's see how the console prints the object.
var _location = {
state:'Bavaria',
}
console.log(_location);
Each object in Javascript by default contains a property called __proto__
, so we will use this property to achieve our goal, as follows..
var _location = {
__proto__: city,
state:'Bavaria',
}
Now we will draw our visual explanation after this modification:
Based on this case, we can access name
from location
object, but we can't access state
from city
object.
console.log(_location.name); // 'München'
console.log(city.state); // undefined
Look at this example and try to get the answer.
var city = {
name:'München',
}
var _location = {
__proto__: city,
name:'Bavaria',
}
console.log(city.name); // ?
console.log(_location.name); // ?
The location
object will look for a name
property in the city
object, only when it does not contain the required property name
.
In this example, the location
object has its own property name
, so the city
object will not be seen.
console.log(city.name); // 'München'
console.log(_location.name); // 'Bavaria'
Last interesting point about using __proto__
var humans = {}
var animals = {}
var plants = {}
humans.__proto__.need= 'Water'
console.log(humans.need); // 'Water'
console.log(animals.need); // 'Water'
console.log(plants.need); // 'Water'
As you saw if we add property need
to __proto__
we can access the value of this property need
from any other object.
This is where our diving trip ends 📍 I hope you have enjoyed and found it a useful trip. Wait for me on other exciting diving trips ✨.
Resources:
- just javascript a great email list (highly recommend course), explaining the basic principles of Javascript using mental models (illustrations in the article 👆) to explain how they work behind the scenes.
- MDN web docs.
- Javascript info.
- All illustrations were made using excalidraw.
Top comments (5)
Very useful article <3 .
Very interesting article. Thanks for sharing.
Thanks, you are welcome. 😃
Nice one! Reminds me of Dan Abramov's ideas on JavaScript mental models in justjavascript.com/ which I definitely recommend to anyone looking to expand on these ideas.
Thank you, of course it's an amazing way by Dan to understand these principles, and i have mentioned that at the bottom of the article.