3

I cannot understand why the following code produces 'Smith' as output, and not 'Smith Foo'. Can you please clarify why it is happening? I cannot figure out how a childFoo property lookup in the prototype chain finds a way to a prototype of child.

var parent = {};
var child = Object.create(parent); 
Object.getPrototypeOf(parent).Surname = 'Smith';  

var parentFoo = function parentFoo() {};
var childFoo = new parentFoo(); //Object.create(parentFoo);   
Object.getPrototypeOf(parentFoo).Surname = 'Smith Foo';   

console.log(childFoo.Surname);
// this outputs 'Smith' only.
6
  • you changed the prototype of parentFoo not childFoo Commented Oct 14, 2018 at 8:39
  • Yes, but I created childFoo with new parentFoo(). Doesn't it happen like with normal objects that root prototype of childFoo is also a root prototype of parentFoo? Even worse, I cannot find any common prototype of child and childFoo by Object.getPrototypeOf() function. Commented Oct 14, 2018 at 8:42
  • yeah, I'm trying to unravel why you're doing it like this in the first place :p Commented Oct 14, 2018 at 8:56
  • new parentFoo does something completely different than Object.create(parentFoo)?! Commented Oct 14, 2018 at 12:03
  • 1
    Why exactly are you using Object.getPrototypeOf in your examples? Especially because Object.getPrototypeOf(parent) is Object.prototype, and you should absolutely not modifiy that. Commented Oct 14, 2018 at 12:05

3 Answers 3

3

The source of the confusion here, I think, is the difference between getPrototypeOf(a) and a.prototype.

  • a.prototype is the prototype that will be used to create instances of a, like in new a().
  • Object.getPrototypeOf(a) returns the prototype that was used to create a, like in a = new AClass().

So, when you do a = new AClass(), Object.getPrototypeOf(a) is equal to AClass.prototype, the prototype that was used to create a.

Object.getPrototypeOf(parent).Surname = 'Smith';

Here, getPrototypeOf returns the prototype used to create {}, which is Object.prototype. This line is equivalent to Object.prototype.Surname = 'Smith'.

Object.getPrototypeOf(parentFoo).Surname = 'Smith Foo';

Here, getPrototypeOf returns the prototype used to create parentFoo, which is a function(){}: The return value is Function.prototype. This line is equivalent to Function.prototype.Surname = 'Smith Foo'.

console.log(childFoo.Surname);

childFoo is an instance of parentFoo, but parentFoo.prototype was not modified, so it is an empty object (except for builtins). Thus, childFoo.Surname goes up the prototype chain, ending up at Object.prototype—the root that all JS objects inherit from. That's where it finds the Surname property that you defined earlier, 'Smith'.

And if you do (function () {}).Surname, you'll see the 'Smith Foo' string, because it was defined on Function.prototype.

(This can be a really tricky part of JS to wrap your head around, so I hope that made sense!)

Sign up to request clarification or add additional context in comments.

Comments

0

You did change the prototype of the Object object from which every object inherits (unless explicitly specified) with this line of code:

Object.getPrototypeOf(parent).Surname = 'Smith';  

Here we can see the devtools which shows that you to a property Surname with the value of Smith on the Object prototype.

enter image description here

Then with the following line of code :

Object.getPrototypeOf(parentFoo).Surname = 'Smith Foo'; 

You put the string 'Smith Foo' as a surname property on the function prototype. Here is how this looks in the chrome devtools:

enter image description here

Here is what you should do to get your desired result:

var parent = {};
var child = Object.create(parent);
Object.getPrototypeOf(parent).Surname = 'Smith';

var parentFoo = function parentFoo() {};
var childFoo = new parentFoo(); //Object.create(parentFoo);   
// change parentFoo to childFoo
Object.getPrototypeOf(childFoo).Surname = 'Smith Foo';

console.log(childFoo.Surname);

Comments

0

Here is the final answer:

function parentFoo() {};
var childFoo = new parentFoo(); //Object.create(parentFoo);   

parentFoo.__proto__.Surname = 'Smith Foo';   
console.log(childFoo.Surname);
console.log(parentFoo.__proto__);

parentFoo.__proto__.__proto__.Surname = 'Smith Foo';   
console.log(childFoo.Surname);
console.log(parentFoo.__proto__.__proto__);

Here is what I found:

  1. When using directly constructor function and 'new' keyword, your new object's immediate prototype will be special function prototype

    • and next one in the chain will be the special common object prototype.
  2. When using directly constructor function and 'new' keyword, your new object's immediate prototype will be special function prototype

    • and that prototype has nothing to do with prototype of function itself.

I hope I got it right this time :) Thank you all for helping out!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.