Object Methods
We learned that objects, just like arrays, can hold different types of data. They can hold even arrays, and in fact, they could even hold objects inside objects. Let's take this a little bit further, and for that, remember when we said that functions are really just another type of value. Meaning if a function is just a value, then that means that we can create a key-value pair in which the value is a function. Thus this means that we can add functions to objects.
const user = {
firstName: 'John',
lastName: 'Doe',
job: 'Software Engineer',
birthYear: 1958,
fruits: ['Banana', 'Apple', 'Melon'],
friends: ['Eric', 'Ulrich', 'Mary'],
hasRetired: true,
calcAge: function(birthYear) {
return 2021 - birthYear
}
};
As you can see on the above user object, we have a function assigned to the calcAge
property, which is pretty similar to the below code, which we saw in the previous lectures.
// Exactly what we used to do before (Regular function expression)
const calcAge = function (birthYear) {
return 2021 - birthYear;
};
The difference only lies in the syntax because calcAge
in our object isn't a variable but a property of the user
object. That's why it was very important to understand what a function expression is because, in our object, we need a function expression to create our method.
So note that every function that is attached to an object is called a method.
We can't define a function declaration in an object. You can't do something like the below code snippet; else, you will get an error.
const user = {
.
.
function calcAge(birthYear) {
return 2021 - birthYear
}
};
Just like we can access every property of an object, we can also access the calcAge
property or method.
console.log(user.calcAge(1958)); // Result ==> 63
We can also access this method using the bracket notation because it is just like any other property.
console.log(user['calcAge'](1958)); // Result ==> 63
Like we saw in the lecture on operator precedence, user.calcAge
is first computed, making it the function value. With the parenthesis that follows, we call that function value with the value 1958
. The same thing happens with the bracket square notation.
You can see that the birth year (1991
) which we passed in the function has already been defined in the user object. Thus writing the same number in both places is not ideal because we might make an error in writing the same number, and also, doing so does not keep the code DRY.
So what if we could access the birthYear
property directly from the user object instead of passing it into the function.
Actually, we can, and that is because JavaScript gives us access to a special variable called this
in all methods.
The this
keyword or variable is equal to the object on which the method is called, or in other words, it is equal to the object calling the method.
When using the this
keyword, always ask yourself: WHO IS CALLING THE METHOD?
Let's consider the below code we previously wrote.
user.calcAge(1958);
From the above, we can see that the object calling the calcAge
method is user
, which means that inside the calcAge
method the this
keyword will point to user
. Here is how our function will finally look like in our object.
const user = {
.
.
calcAge: function() {
return 2021 - this.birthYear
}
};
When calling it, we don't need to pass an argument.
console.log(user.calcAge()); // Result ==> 63
Just to show you that the this
keyword points to the object calling the method, try logging the this
keyword inside the calcAge
function, and you will see that in the console, you get the user object.
const user = {
.
.
calcAge: function() {
console.log(this) // Result ==> user object
return 2021 - this.birthYear
}
};
So if the this
keyword points to the user
object then this.birthYear
is equal to 1958
which is the value of the birthYear
property in our user
object. The this
keyword is something really useful in JavaScript, and we will learn more about tit in greater details in a later lecture. I just felt it was necessary to introduce you to this concept right now, and it can really be confusing at the beginning. Just take time and read over again if you feel like you don't get it right.
You might argue that we don't need the this keyword and just have something like this.
const user = {
.
.
calcAge: function() {
return 2021 - user.birthYear
}
};
It will work just the same, but it will violate the DRY principle. Also, what if we decided to change the object name from, let say, user
to myuser
and then call the function again.
console.log(myuser.calcAge());
Executing the above won't work anymore because user
is not defined. You will have to manually rename or change user
to myuser
in the calcAge
function. Meanwhile, with the this
keyword, everything will keep working without us having to change something because now, this
will simply point to myuser
because that is the object calling the method.
So remember that it is always a good idea to reference the object itself and not hard code the object's name.
Let's take it a little further. Don't worry; it is not going to be a lot more confusing. We are just going to see a slight variation of the this
keyword.
Let's say we want to access the age
multiple times throughout our program. That would be like calling user.calcAge()
a couple of times.
console.log(user.calcAge());
console.log(user.calcAge());
console.log(user.calcAge());
What happens here is that we call the function three times, and so the calcAge
function body will be executed three times. In this case, that is no big deal, but it might be a heavy computation, for example, a function with like a hundred lines of code that takes much time to execute. It would then be a bad practice to do this multiple times.
Instead, we can just calculate the age ones, store it in the object, and when we need it at a later point, we can then retrieve the age as a property from the object.
const user = {
.
.
calcAge: function() {
// this.age creates a new property on the user object
this.age = 2021 - this.birthYear
return this.age
}
};
Now let's try this out
user.calcAge();
console.log(user.age); // Result ==> 63
console.log(user.age); // Result ==> 63
You can now see that we just calculated the age once, and on the following lines, we retrieve the age value that we had already calculated before
To finish this lecture, I want to make a link with the array method lecture we earlier had. Remember that we used methods on arrays previously; for example, we used the push method by doing:
fruits.push('Apple')
What this means is that arrays are also objects. They are just special kinds of objects with functions or methods that we can use to manipulate them.