const - JS | lectureJavaScript Fundamentals 2

Object Methods

JavaScript Fundamentals 2

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.

script.js
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.

script.js
// 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.

script.js
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.

script.js
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.

script.js
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.

script.js
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.

script.js
const user = {
  .
  .
  calcAge: function() {
    return 2021 - this.birthYear
  }
};

When calling it, we don't need to pass an argument.

script.js
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.

script.js
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.

script.js
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.

script.js
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.

script.js
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.

script.js
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

script.js
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:

script.js
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.