1

why is it

Foo.prototype = Object.create(Bar.prototype) 

in order to let Foo "inherit" from Bar and not

Foo = Object.create(Bar)

or at least

Foo.prototype = Object.create(Bar)

... because isn't Bar.prototype already the "class" which Bar is in turn "inheriting" from ? Speaking of the prototype-chain (Why is it necessary to set the prototype constructor?)

But obviously, Foo.prototype means some hugely different thing than Foo.[[Prototype]]. The first one meaning things that are shared among all the instances of

new Foo(args)

such as in

a = new Foo(args)
b = new Foo(args)

Intuitively, this and Foo.prototype seem more like a distinction for instances between "instance-methods/attributes" on one side and "class-level-methods/attributes" than some kind of inheritance.

von spotz
  • 875
  • 7
  • 17
  • `Bar` is Bar's constructor function. If you want to put Bar's prototype onto your prototype-chain, you'll need `Foo.prototype = Object.create(Bar.prototype)` accordingly. `Foo = Object.create(Bar)` makes no sense, you'd set `Foo` to an object, which isn't a function, and can't be called, so also not constructed. `Foo.prototype = Object.create(Bar)` would let instances-of-Foo's prototype chain have Bar's constructor function in it, and not Bar's prototype, as desired. – ASDFGerte Mar 13 '21 at 18:40
  • I thought it would be desired to have Bar's constructor function inside Foo.prototype and not again the prototype of Bar. It's hard to wrap my head around this. Because then - and this is just a rhetorical question bc your answer is obviously correct - why even bother having a body to `function Foo();` Whatever, thanks for your answer. – von spotz Mar 13 '21 at 18:57
  • 1
    The constructor function, in the ES6 syntax sugar `class` even called `constructor`, is used to create instances, e.g. `function Foo(x) { this.myInstanceValue = x; }`. Every instance will have its own value for the property `myInstanceValue`. The prototype is one for all, and typically has e.g. functions: `Foo.prototype.printMe = function(){ console.log(this.myInstanceValue); }`. Note that there are many valid reasons to have some functions on instances as well. Now, with `const a = new Foo('hello'), b = new Foo('world');`, `a.printMe === b.printMe`, and try `a.printMe(); b.printMe();`. – ASDFGerte Mar 13 '21 at 19:46

1 Answers1

1

Both Foo and Bar are functions. That's what constructors must be, in order for them to be called, eg new Foo(). So they inherit directly from Function.prototype.

Although linked, the constructor functions are entirely different from the internal prototype of instances created with them. The .prototype property of a constructor accesses the internal prototype of instances. The .constructor property of such a prototype accesses the constructor.

These internal prototypes are plain objects, not functions. You wouldn't expect any instance to inherit from Function.prototype and be callable.

But obviously, Foo.prototype means some hugely different thing than Foo.[[Prototype]]

The internal prototype of the Foo constructor is Function.prototype.

This is how it looks when properly set up:

Object.prototype <- Function.prototype <- Foo
Object.prototype <- Function.prototype <- Bar

Object.prototype <- Bar.prototype <- bar instance
Object.prototype <- Bar.prototype <- Foo.prototype <- foo instance

The constructors do not inherit from each other - only the .prototypes, the internal prototypes (or [[Prototype]]s) of instances inherit from each other, when doing this sort of thing.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320