Today we'll look at how primitives and objects are stored and what happens to them when they are passed into functions.
We looked at arrays on day two. Arrays are great for storing independent values, but don't scale well when we want to describe a subject in more detail.
// not ideal!
['name: Dan', 'age: 35', 'shoeSize: 9'];
The example above would be very tricky to manage and wouldn't be an efficient approach. This is where objects come to the rescue. An object is a collection of information about, well, an object!
let person = {
name: 'Daniel',
age: 35,
shoeSize: 9,
smokes: false,
hobbies: ['motorbikes', 'cats', 'dogs', 'football'],
};
Information in objects is stored in key/value pairs. Above, name
is the key and Daniel
is the value.
Accessing an object is as easy as using what's known as dot notation:
console.log(person.name); // Daniel
You may see other ways of accessing the object, such as:
console.log(person['name']); // Daniel
Objects are mutable, so any change you make will change the object directly. Changing is as easy as re-assigning the value:
person.name = 'Dan';
console.log(person.name); // Dan
You can also push new items to an array within an object:
person.hobbies.push('Scrabble');
console.log(person.hobbies); // hobbies: ["motorbikes", "cats", "dogs", "football", "Scrabble"]
You have been asked to construct a for loop that can list the contents of an array in an object, in reverse order. How should you complete the code below?
/*
Expected result in console:
"Claude"
"Whiskers"
"Smokey"
"Tiddles"
*/
var myObject = {
names: ['Tiddles', 'Smokey', 'Whiskers', 'Claude'],
};
for (;;) {
console.log();
}
JavaScript primitives include:
Here are some examples of primitives:
"Bob"
true
35
Primitives are immutable, meaning they cannot change. The size of a primitive is fixed, so JavaScript stores the value in memory on the call "stack".
Imagine a variable as a box containing a primitive value. The variables could be assigned a new value (unless they are const
s, however the primitive value itself cannot be changed.
A box with no value in it is an "undefined" variable.
Using what you have learnt above, can you explain how the following snippet of code works?
let name = "daniel";
name.toUpperCase();
console.log(name); // still "daniel" - strings are immutable
In contrast to primitives, objects are mutable, meaning they can change.
Here is an example to help explain further:
let person = {
name: 'Daniel',
age: 35,
shoeSize: 9,
smokes: false,
hobbies: ['motorbikes', 'cats', 'dogs', 'football'],
};
person.name = 'Dan';
console.log(person.name); // Dan - has been modified
We don't know how big an object will get therefore JavaScript holds the object in an area in something called the "heap" - imagine this as a very large area of memory that can handle objects growing or shrinking. Continuing with our box analogy from early, the box representing the variable "person" above, actually holds a reference or pointer to the memory address of the object on the heap.
When we pass a primitive to a function, a copy of the primitive is taken and stored in a new variable which just has function scope. The 2 variables are completely unrelated so any change to either has no effect on the other. Here's an example to help illustrate this:
function addTen(a, b) { // a & b are *copies* of the variables passed in
a = a+10;
b = b+10;
}
let x = 2;
let y = 4;
addTen(x, y)
console.log(x); // unchanged - still 2
console.log(y); // unchanged - still 4
When we pass an object to a function, a copy of the variable holding the reference is taken - the original and copy both point to exactly the same object in memory, hence changes affect both.
Look at this example:
function updateNames(cats, firstCatsName) {
firstCatsName = 'Ginger';
cats.names[0] = 'Ginger';
}
var cats = {
names: ['Tiddles', 'Smokey', 'Whiskers', 'Claude'],
};
var firstCatsName = 'Gizmo';
updateNames(cats, firstCatsName);
console.log(cats, firstCatsName);
Remember, primitives can't be modified after they've been created, whereas objects and arrays can. firstCatsName
is a string primitive so will not be changed. cats
is an object so any changes will be reflected.
The result will be:
/*
{
names: ["Ginger", "Smokey", "Whiskers", "Claude"]
}, "Gizmo"
*/
Objects passed into a function can be modified by the function, primitive values passed to function are never modified
What is logged in the console?
function multiplyIt(x) {
x *= 3;
return x;
}
var a = 2;
var result = multiplyIt(a);
console.log(a);
console.log(result);
What is logged in the console?
function borrow(name, number, book) {
name = name.toUpperCase();
number = number + "-1";
book.name.toUpperCase();
book.author.toUpperCase();
}
let name = 'shanie';
let number = '123678';
let book = {name: 'Intro to Java', author:'A. Guru'};
borrow(name, number, book);
console.log(name, number, book.name);