you have an object.
var o = {
a : 4,
log : function () {
console.log('a:', this.a);
}
};You make another one.
var p = Object.create(o);
p.a = 7;
p.log = function () {
console.log('zippededee');
// how duz I call o.log on this object?
};We overrode o.log, so we can’t just do this.log, it’s infinite recursion. The simplest solution would be o.log.call(this), but that’s ugly: We have to know who our parent is, and there’s that call.
How about this, then: Object.getPrototypeOf(this).log.call(this)
…I don’t think I have to explain why this isn’t a good and feasible solution in the long run.
Whatever can we do!?
“Don’t worry”, say proxies, “I shall save your ass!”
“Shave my ass?” you ask, bewildered “…how did you know my ass is hairy?”
“I..uh…what?” proxies reply, equally bewildered, “I said save your ass, not shave your ass”.
“Oh”, you say, “that’s allright then.”
“…weirdo”.
Proxies! We can define a property (say super) on the child object which proxies all property accesses to the prototye object, and when we request a function, bind it to the child! In our example above, if p.super was such a proxy:
p.log = function () {
console.log(this.a); // 7
console.log(this.super.a); // 4, since o.a === 4
this.super.log(); // a: 7
};Neat, huh? this.super functions as a shorthand for Object.getPrototypeOf(this), with the awesome side effect that functions are automatically bound to this.
The implementation isn’t tricky at all, but there is a very big drawback. Give the code a read over, think it over, and come back here. I’ll wait.
Did you finish? Did you really finish, or are you just saying it? Okay, I believe you. Can you think where this method falls short? Let’s do the example over using Object.inherit.
var o = {
a : 4,
log : function () {
console.log('a:', this.a);
}
};
var p = Object.inherit(Object.create(o), {
a : 7,
log : function () {
console.log('zippededee');
this.super.log();
}
});
p.log(); // works as planned
// But what if we add another object?
var q = Object.inherit(Object.create(p), {
a : 14,
log : function () {
console.log('mooo');
this.super.log();
}
});
q.log(); // What happens now?Think it over a bit. It took longer than I’m willing to admit to debug it.
We get a RangeError because of infinite recursion. q.super.log() binds p.log to q, so when inside p.log we call this.super.log, what’s actually called is q.super.log, which is again p.log, and so forth until the tomatoes take over.
I have no solution, because that’s correct behaviour according to the system because of the dynamity of the this keyword (which we use). So know this exists. Also, you probably don’t want to use any of this anyway, so win.