-4

In the code below, I think the way the prototypal chain works (basically) is that if a child object (mike, in this case) doesn't have a method itself, it looks up the prototype chain, via __ proto__, to see if a parent object has it within its prototype object, and if it does, then 'mike' should have access to it. Right?

If that's right, just about, why is 'farewell' is not available to mike? Obviously I can see it's the 'this.' (or lack thereof) that's making the difference, but if __ proto__ allows a child object to access the methods in the prototype objects of parents, why do we need to bother with this. at all??

Thanks very much!

function PersonConstructor() {
  this.greet = function sayHello() {
    console.log("hello");
  };
  farewell = function sayBye() {
    console.log("Bye");
  };
}

function personFromConstructor(name, age) {
  const person = new PersonConstructor();
  person.name = name;
  person.age = age;
  return person;
}

const mike = personFromConstructor("Mike", 30);

console.log(mike.greet); // [Function: sayHello]
console.log(mike.farewell); // undefined
deceze
  • 510,633
  • 85
  • 743
  • 889
desalwe
  • 19
  • 6
  • It will just become a global var otherwise.. – Keith Jan 27 '20 at 15:11
  • 2
    So it belongs to the instance. – Dave Newton Jan 27 '20 at 15:12
  • 1
    `farewell` is just a local variable inside the constructor function (well, because you're omitting `var` it's not, but let's put that aside)… It is not attached to the object in any way as a property, much less to any prototype. – deceze Jan 27 '20 at 15:12
  • 1
    What else would `farewell` be? Without the `this`, what would be getting that value? It may seem "obvious" that you want the function attached to the function you are calling within, but the syntax rules would be assigning that value to `farewell` which would be expected to be a variable outside the scope of that function. The most terse answer is "Because that's how the language works". I don't know how else to put it. – zero298 Jan 27 '20 at 15:13
  • @Dave *What* belongs to the instance…? – deceze Jan 27 '20 at 15:14
  • You should read this as well. [Declaring variables without var keyword](https://stackoverflow.com/q/6888570/691711). – zero298 Jan 27 '20 at 15:15
  • 1
    Just a slight observation too, doing -> `this.greet =` inside your constructor function negates the whole point of this and prototype. If you do this every instance will have it's own `greet` method,. To have the advantages of using a prototype chain you should be doing -> `PersonConstructor.prototype.greet = .....` or use class syntax, rather than method syntax. – Keith Jan 27 '20 at 15:18
  • We should probably have a canonical about `this.foo` not being equal to `foo` in JavaScript. I see that error relatively recently and I think it comes from people more familiar with languages like Java where the two are equivalent within a class and dropping `this.` is even a preferred coding style in some places. But in JavaScript `foo` is a variable and `this.foo` is a completely different property, the two are *never* going to be the same. – VLAZ Jan 27 '20 at 15:20
  • @deceze As per the title: "why do I need `this` before a method [...]" where "method" is the subject of the sentence, making it the reference in followup sentences. – Dave Newton Jan 27 '20 at 15:22
  • 1
    @Dave I see. I usually try to refer to the last question within the body instead of the title, so that connection wasn't entirely obvious. – deceze Jan 27 '20 at 15:24

1 Answers1

1

This doesn't have much to do with prototypes at all. What happens when you do new PersonConstructor() is, simplified:

let obj = {};
/* [ here be dragons and details about setting up prototype chains ] */
PersonConstructor.call(obj);  // `this` inside PersonConstructor is obj
return obj;

Essentially, it's equivalent to:

let obj = {};
obj.greet = function sayHello() {
  console.log("hello");
};
farewell = function sayBye() {
  console.log("Bye");
};

And that should illustrate why farewell is not ending up as part of the object in any way.

deceze
  • 510,633
  • 85
  • 743
  • 889