Difference between primitive data types and reference types
The difference between primitive data types and reference types is the way in which the respective values are stored. Each time a variable is declared, the computer allocates memory space for it and stores the variable and its value in a memory address provided for this purpose.
1. The principle of primitive data types
With primitive data types, every time a value is assigned to a variable, the entire value is copied to this memory address. For example, if a variable x is created via let x = 5;, the computer saves this variable internally and stores the value 5.
let x = 5; // x --> 5
If the instruction let y = x; is now executed, the value of x (5) is assigned to the variable y. Internally, the computer copies this value into the register intended for the variable.
let x = 5; // x --> 5
let y = x; // y --> 5
2. The principle of reference types
The situation is slightly different with reference types. Here, the computer does not store the value itself in the register provided for the respective variable, but only a reference to it (also called a pointer).
let x = 5; // x --> 5
let y = x; // y --> 5
let rick = { // rick
firstName: 'Rick', // firstName Rick
lastName: 'Sample' // lastName Sample
}
let rick2 = rick;
The variable rick is initialized here with an object, i.e. a reference type. However, this object, which is composed of various primitive data types, is not stored directly in the register, but only referenced via a pointer.
If you now create a second variable (rick2) and assign the content of the variable rick to it, it is not the object stored there that is copied, but the pointer to the object. Both variables then point to the same object.
let x = 5; // x --> 5
let y = x; // y --> 5
let rick = { // rick
firstName: 'Rick', // firstName Rick
lastName: 'Sample' // lastName Sample
}
let rick2 = rick; // --> rick2 --> firstName Rick, lastName Sample
If two or more variables point to the same object, as in the example, this also means that you always work with the same object, regardless of which variables you access. So if you change a property of the referenced object via one of the variables, this also has an effect on the other variable:
let x = 5; // x --> 5
let y = x; // y --> 5
let rick = { // rick
firstName: 'Rick', // firstName Morty
lastName: 'Sample' // lastName Sample
}
let rick2 = rick; // --> rick2 --> firstName Morty, lastName Sample
rick2.firstName = 'Morty'
Access to object properties and object methods via dot notation:
const rick = {
firstName: 'Rick',
lastName: 'Sample'
}
const rick2 = rick;
rick2.firstName = 'Morty';
console.log(rick2.firstName); // "Morty"
console.log(rick.firstName); // "Morty"
3. Primitive data types and reference types as function arguments
If arguments of a primitive data type are passed to a function, for example the number 420, the values are copied to the corresponding parameters of the function. If you change the value of a parameter within the function, this does not change the value of the variable that was passed to the function as an argument.
Complete Code - Examples/Part_112/main.js...
function example(x) {
console.log(x); // 420
x = 6;
console.log(x); // 420
}
let y = 420;
console.log(y); // 6
example(y);
console.log(y); // 420
Here, the variable y is first initialized with the value 420 and then passed to the function example(). Within this function, the parameter x is set to the value 6. However, this does not change the value of y.
If you change the example and replace the variable y and the parameter x with an object, the behavior is different. If you now pass the variable y as an argument to the function example(), you pass the pointer to the object that is assigned to the variable y. Within the function, x now also points to this object. This means that if you change a property on x, you change the same object that y points to:
Complete Code - Examples/Part_113/main.js...
function example(x) {
console.log(x.value); // 420
x.value = 6;
console.log(x.value); // 420
}
let y = {
value: 420
};
console.log(y.value); // 6
example(y);
console.log(y.value); // 6
4. Determine the type of a variable
As the type of a variable is not specified in the declaration, the question arises as to how to recognize it. This is possible using the typeof operator. This is a unary operator, i.e. it only expects an operand for which the type is to be determined. The operator returns a character string as the return value.
Return value of the typeof operator | Returned for... |
---|---|
boolean | boolean values |
number | numeric values |
string | character string |
symbol | symbols |
function | functions |
object | all types of objects and the value null |
undefined | undefined variables |
Application of the typeof operator for different values
console.log(typeof true); // boolean
console.log(typeof false); // boolean
console.log(typeof 420); // number
console.log(typeof 42.42); // number
console.log(typeof 'Rick Sample'); // string
console.log(typeof function () {}); // function
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof null); // object
console.log(typeof undefined); // undefined
console.log(typeof Symbol('ยง')); // symbol
In addition to the typeof operator, there is another operator that has something to do with determining the type of variables, namely the instanceof operator. The operator returns a Boolean value.
The object rick is of type Object, but not of type Array. The object numbers, on the other hand, is of both type Object and type Array. This is because the type Array is a "lower type" of Object in JavaScript. The type of functions, Function, is also a "lower type" of "Object", so that the instanceof operator for the function add() returns true in both cases:
const rick = {
firstName: 'Rick',
lastName: 'Sample'
}
const numbers = [2,3,4,5,6,7,8,9];
function add(x, y) {
return x + y;
}
console.log(rick instanceof Object); // true
console.log(rick instanceof Array); // false
console.log(numbers instanceof Object); // true
console.log(numbers instanceof Array); // true
console.log(add instanceof Function); // true
console.log(add instanceof Object); // true
Object is the type from which all other reference types are derived. The instanceof operator therefore returns the value true for all variables of any reference type.
In contrast to the typeof operator, the instanceof operator only works for values that contain a reference type. For values of primitive data types, on the other hand, the operator always returns false:
console.log(true instanceof Object); // false
console.log(420 instanceof Object); // false
console.log('Rick Sample' instanceof Object); // false
Note
To check whether a variable is an array, the Array.isArray() method is available as an alternative to the instanceof operator:
const rick = {
firstName: 'Rick',
lastName: 'Sample'
}
const numbers = [2, 3, 4, 5, 6, 7, 8, 9];
console.log(Array.isArray(rick)); // false
console.log(Array.isArray(numbers)); // true
Related links: