Prototype: objects linked

In notebook:
FrontEndMasters Advanced JavaScript
Created at:
2016-10-06
Updated:
2016-10-07
Tags:
Fundamentals JavaScript
Snippet:
  function Foo(who) {
  this.me = who;
}
Foo.prototype.identify = function() {
  return "I am" + this.me;
};

function Bar(who) {
  Foo.call(this,who);
}
// Bar.prototype = new Foo(); // Or...
Bar.prototype = Object.create(Foo.prototype);
// NOTE: .constructor is borked here, need to fix

Bar.prototype.speak = function() {
  alert("Hello, " + this.identify() + ".");
};

var b1 = new Bar("b1");
var b2 = new Bar("b2");

b1.speak(); // alerts: "Hello, I am b1."
b2.speak(); // alerts: "Hello, I am b2."
He wants to create a child class ​Bar​ from ​Foo​. 
​Bar​ is supposed to inherit or extend from ​Foo​.

Option 1.
Line#11 Call ​new Foo()​ but this would actually run ​Foo​ and create ​this.me​ and other side effects. 

Option 2.
Or use ​Object.create()​ from ES5 as in line#12. It's similar to ​new​. It does the first two steps from ​new​:
  1. create a new object from thin air
  2. link it to the object passed as the argument
But doesn't do steps 3 and 4 from the ​new​ call (bind ​this​ and ​return this​)

Line#22 explained: ​b1.speak()
The prototype chain in action:
​b1​ has no ​.speak​ -> ​Bar​ has no ​.speak​ -> ​Foo​ has ​.speak
The prototype delegation is very powerful, but if you think in terms of classes and inheritance, it can lead to some problems:

Line#13
Where should ​b1.constructor​ point to? We would want to point to ​Bar​ (in the logic of ​.constructor​ meaning "constructed by" – not exactly true)
Let's see then where's the ​.constructor​ property of ​b1​:
  • ​b1​: has no ​constructor
  • ​Bar.prototype​ had a constructor on line#8, but it has been removed on line#12​ with ​Object.create
  • so we move up the prototype chain to ​Foo​. 
  • finally ​b1.constructor​ is ​Foo​. 
One way to fix this, is to add manually the ​.constructor​ on line#13 and make it point to ​Bar​. But! You cannot just do ​Bar.prototype.constructor = Bar​. This would create an enumerable property, and this would break your ​for​ loops (enumerate the properties of an object). You would need to do ​defineProperty​ and set is properties correctly. Very awkward.