Sure, it’s a great question, and one that has broken lesser beings.
so Vegetable is not an object in itself. Instead, being a class, its like the blueprint of an object. Now, objects can have properties, and those properties are just… data. So we can have something like:
const carrot = {
name: 'Carrot',
scientific_name: 'Daucus carota'
}
It’s simply an object literal. If we were to do carrot.scientific_name
, we would get the property at that key.
But remember, in javascript, functions are first-class citizens. That means a function is simply treated as data, just like a string or a number or a boolean or whatever. So we could define a function, and assign it to a property of our object.
const carrot = {
name: 'Carrot',
scientific_name: 'Daucus carota',
harvest: function() {
alert("ACK!! YOU PICKED ME!");
}
}
// and, if we were to
carrot.harvest();
// it would display the alert
Now that’s great, but we have no means of getting at the values of our carrot… within our carrot. That is, without some sort of context, we can’t reference the properties from inside our object. Which is where this
comes in.
In javascript, we have “context” or “execution scope”. When a function is run, it runs from a given place. Our carrot.harvest()
function (sometimes called a method, when its a function attached to an object) is executed in the context of our carrot
object. And javascript provides the reserved this
keyword to refer to the actual context our function is running in.
So if we have a class, like Vegetable
, and it has a constructor method, that is in the “blueprint” or prototype of our carrot
object. That means, when we create a new Vegetable, we create an empty object, and then we run the Vegetable.constructor
as though it were being run inside our new object. It says to javascript “when you run .constructor()
, the this
property should be the new empty object.”
So when we do this.name = name;
, while the function itself is stored in the “blueprint” (the class Vegetable
), javascript knows that the function is being executed within our new carrot
object, making this
(our context) our carrot
.
this
is a thing to be very cautious of. It is not something to take lightly, as it’s very easy, as you advance, to nest functions inside other functions, and inadvertently change context, rendering this
as something you don’t expect.
The reason we use this
in the example, might be made clearer by an extension of that example:
class Vegetable{
constructor(name){
this.name = name;
}
harvest(){
// here, the parameter "name" doesn't exist. We have
// to use the object itself, using 'this'
console.log("The "+this.name+" was picked.")
}
}
So, by using this.name
, we can pass values to functions within our object. We couldn’t necessarily pass the parameter itself, but by assigning it to a property within our object, we can reference it elsewhere… within the object.