Prototype: objects linked
Snippet:
The prototype delegation is very powerful, but if you think in terms of classes and inheritance, it can lead to some problems:
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
:- create a new object from thin air
- link it to the object passed as the argument
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
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 noconstructor
Bar.prototype
had a constructor on line#8, but it has been removed on line#12
withObject.create
- so we move up the prototype chain to
Foo
. - finally
b1.constructor
isFoo
.
.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.