user1622544
user1622544

Reputation: 53

Prototype puzzle with JavaScript

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.

Upvotes: 3

Views: 95

Answers (3)

user1622544
user1622544

Reputation: 53

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!

Upvotes: 0

Willem van der Veen
Willem van der Veen

Reputation: 36630

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);

Upvotes: 0

goto-bus-stop
goto-bus-stop

Reputation: 11824

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!)

Upvotes: 3

Related Questions