Can't grasp my head around the "this" keyword... I need help!


#1

Hey there!

I'm having trouble understanding a simple "this" keyword example.

Okay, I understand that the "this" keyword will refer to the object that called the method but what I don't understand is
this line: bob.setAge = setAge; In the code below, we create a function called setAge which sets the age property of the object that called it. Okay, everything is fine, BUT, why can't we simply call object.setAge(some_parameter);? It returns an error that it's not defined.

Can some explain this thoroughly?

Thank you! :slight_smile:

// here we define our method using "this", before we even introduce bob
var setAge = function (newAge) {
  this.age = newAge;
};
// now we make bob
var bob = new Object();
bob.age = 30;
bob.setAge = setAge;
  
// make susan here, and first give her an age of 25
var susan = new Object();
susan.age = 25;
susan.setAge = setAge;

// here, update Susan's age to 35 using the method
susan.setAge(35);

#2

There are two concepts in JavaScript that are important to study and understand...

  1. Scope
  2. Context

The first refers to variable environment, the second refers to execution context.

var a;
function f() {
    var a;
}

The above is an example of scope. When a variable is declared in a function it has its own scope. These two may have the same name, but they are not in the same scope. Inside the function only the local variable is seen, as it shadows the global one. Were we to need access to the global, we would need to refer to it in its context, namely, window.

The window object is the global object and represents the top of the scope chain. Let's run the above code in global scope:

setAge(19);

No errors are thrown so something got set. What just got created and set?

console.log(age);           // 19

Where is the variable age? In window context.

console.log(window.age);    // 19

In this instance, this is window, the execution context. But that does not help bob and susan objects, does it? They have no access to the execution context. Note that the above,

setAge(19);

could be more explicitly written as,

window.setAge(19);

Starting to look familiar?

This line,

bob.setAge = setAge;

assigns a string representation of the method to the bob object, as does the similar line to the susan object. Examine the bob object and you find that method among its properties.

We do not need to define age for our objects since the method will create the attribute if if does not exist.


#3

Line by line:

// here we define our method using "this", before we even introduce bob
var setAge = function (newAge) {
  this.age = newAge;
};

Now we have function expression called setAge() with one parameter.

var bob = new Object();

Here we created bob and this object looks like:

var bob = {};

Next step:

bob.age = 30;

We defined property age and assigned value for this property. Now bob looks like:

var bob = {
   age: 30
}

On this step bob knows that he is 30 but doesn't know how to set new value for that property. So we need to create this method. But we have setAge function (not method) which was created earlier. So we can put this function as a method for bob object:

bob.setAge = setAge;
// Equals to
var bob = {
   age: 30,
   setAge: function (newAge) {
      this.age = newAge;
   }

Now bob knows how he can set new age:

bob.setAge(50);

Conclusion

why can't we simply call object.setAge(some_parameter);? It returns an error that it's not defined.

Because object bob doesn't have this method. First method must be defined as a part of object and only after that you can use it.

Actually we don't need function expression setAge() because we can create method. I think this lesson is good for practice and better object understanding.

Updated
Try this:

var setAge = function (obj, newAge) {
  obj.age = newAge;
};

var bob = new Object();
bob.age = 30;
setAge(bob, 40);
// bob.age = 40

#4

Ahh I get it now. Thank you both for a clear explanation. :slight_smile:

However, could bob.setAge = setAge; also be written as bob.setAge = setAge();?
Are these two equal or not? It seems like that the second one would call the function and not asign it to the property setAge in object bob as the first one does. Am I right?


#5

No. That would assign an undefined value or possibly raise an exception.

Edit:

My machine shut down and I didn't get a chance to compete this post. Just now getting back on scene.

Remember we said that the string representation of setAge is copied to the bob and susan? The means they should now each have a copy of the method in their own context.

 > bob.setAge.toString()
=> 'function (newAge) {\n      this.age = newAge;\n   }'

 > console.log(bob.setAge.toString())
 function (newAge) {
      this.age = newAge;
    }

Any object that is a string representation of a function has that functionality. All we need do is invoke it. Recall that this in this instance is bob.


#6

Mechanically sound, yes, notwithstanding this is the antithesis of class definitions and is unprotected in the global namespace.

Classes give a whole range of objects a relational aspect. Things connect. It is possible to find all objects in a collection that are instances of a single class. That's what makes them so versatile.

Once we define a class, we forget about the global namespace. It's in the rear view mirror as we leave town. Instances of the class have context and scope built in. We benefit by exploiting this in the way we build code constructs.


#7

Oh my, everything is clear as a day today... Seems like I just have to take a nap instead of asking stupid basic questions, haha. Looks like I just wasn't able to think yesterday. Thank you both. :slight_smile:


#8

Here is a good read if you'd like to deepen your understanding :wink:


#9

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.