Particularly in JavaScript object oriented programming:
If I have a class like this, for example:
class Animals{
constructor(name, species){
this.name = name;
this.species = species;
}
}
Why do we need to use this.yyyy = yyyy in the constructor? I have read explanations many times but still can’t get it, please explain like I’m 5
In: 28
Have you ever heard about “shadowing” ? It’s when two objects have the same name, but one has been defined “closer to you”, so you see this one.
For instance :
let a = 1;
if (true){
let a = 2;
console.log(a);
}
console.log(a);
Will print 2, then 1. Inside of the “if”, there is a variable a declared that “hides in its shadow” the variable a that was 1.
So when you do
class Animals{
constructor(name, species){
this.name = name;
this.species = species;
}
}
Inside the constructor, what is “name” ? Well it’s the value that has been defined in the innermost block. But an “name” is defined right in the constructor : the parameter. So name will only refer to this parameter, and you can never access the attribute.So you say “this.name” to get the attribute : it’s the name inside “this”.
If I remember correctly, in JavaScript, you always have to say “this” before you access to an attribute. But in C++ for instance, those two would work :
class Animals
{
private:
std::string name;
std::string species;
public:
Animals(std::string name, std::string species)
{
this->name = name;
this->species = species;
};
}
class Animals2
{
private:
std::string m_name; std::string m_species;
public:
Animals2(std::string name, std::string species)
{
m_name = name;
m_species = species;
};
}
Because, in the second class, m_name is not shadowed.
I’m surprised I haven’t seen this comment yet but we don’t need “this” keyword at all. We don’t even need constructors. In fact, as far as I know, no computer ever has ever had the concept of “classes” built into its instruction set.
So “this” keyword, as well as constructors, as well as classes and OOP in general, is an abstraction. It’s an artifact of the language you are using. But the underlying bare metal you are running your code on doesn’t see or care about any of that. So in short we don’t need it at all to run code, it’s just a nice feature of a language for the purposes of clarity
It is because Javascript does not enforce the fact 2 variables accessible in the same scope must be written differently. So if you don’t put the this it will use the locally defined one, the one received in parameter. If your member variable was written differently you would not need the this.
Some languages prevent you from doing that, they will throw an error saying duplicate variable name or something like that which will force you to use proper naming so your code is easier to read.
Other answers have explained the concept of [shadowing](https://en.wikipedia.org/wiki/Variable_shadowing), which is a related concept:
// Create variables named ‘a’ and ‘b’ on the “outside”
let a = 1;
let b = 2;
function doAThing() {
// Create a new variable, also named ‘a’ on the “inside”:
let a = 10;
// We are “inside” the function, so this will look for a variable
// named ‘a’ that exists on the “inside” first. In this case, we find
// the one above.
console.log(a); // Prints “10”
// There is no “inside” version of ‘b’. But there is an “outside”
// version of ‘b’ that we can use as a fallback. So we use that.
console.log(b); // Prints “2”
// At the end of the function, the “inside” version of ‘a’ is destroyed.
}
doAThing();
// We are “outside” the function now, so the “outside” value for ‘a’ is
// used here.
console.log(a); // Prints “1”
But when it specifically comes to classes and class methods, it’s a little more nuanced. Consider:
let name = ‘Kevin’;
class Animal() {
constructor() {
let name = ‘Chris’;
}
}
let a = new Animal();
console.log(a.name); // “undefined”
A constructor is just a special function. So in most ways, it behaves like any function would. In this example, we’re creating an “inside” version of the variable `name`, and assigning it the value `’Chris’`. But in the previous example, it was shown that all “inside” variables defined in functions like this get destroyed when the function runs to completion. This is also true inside of constructors. If you ran this code, the `Animal` you create won’t have a name set on it.
If you want to attach a value to the instance of the class you’ve created, you need to explicitly tell JavaScript to do that. The `this` keyword inside of classes is how you do that:
class Animal() {
constructor() {
// ‘name’ here is just an “inside” variable that will be destroyed when
// the constructor finishes
let name = ‘Kevin’;
// ‘this.name’ tells JavaScript that you want this variable to persist
// on the class instance
this.name = ‘Chris’;
}
}
let a = new Animal();
console.log(a.name); // “Chris”
In fact, the `this` keyword is nothing more than a variable that magically holds the same thing the constructor will eventually return. So this:
class Animal() {
constructor(name, species) {
this.name = name;
this.species = species;
}
}
let a = new Animal(‘Chris’, ‘cat’);
console.log(a.name); // “Chris”
Is basically identical to this:
class Animal() {
constructor() {
// Do nothing at all
}
}
let a = new Animal();
a.name = ‘Chris’;
a.species = ‘cat’;
console.log(a.name); // “Chris”
Latest Answers