Lazy binding of "this" for inherited JavaScript instance methods
// The more efficient way (maybe?)
function createLazyBoundMethod(Ctor, method, fn) {
// Create a get accessor that, only when accessed the first time, creates
// a bound method on the instance. If the property is never accessed, the
// per-instance closure is never created.
Object.defineProperty(Ctor.prototype, method, {
enumerable: true,
configurable: true,
get: function() {
var m = "__" + method;
if (!this[m]) { this[m] = fn.bind(this); }
return this[m];
},
});
}
// No closures are created in the constructor.
function Thing(prop) {
this.prop = prop;
}
// One closure is created per-prototype method, up-front
createLazyBoundMethod(Thing, "setProp", function(prop) {
this.prop = prop;
});
createLazyBoundMethod(Thing, "getProp", function() {
return this.prop;
});
// The normal way
// In the constructor, binding all methods to the instance creates one closure
// per method, for every instance, at the time the instance is created. If
// there are 2 methods and 100 instances, that's 200 closures created up-front.
function Thing(prop) {
this.prop = prop;
for (var method in this) {
if (typeof Thing.prototype[method] === "function") {
this[method] = Thing.prototype[method].bind(this);
}
}
}
Thing.prototype.setProp = function(prop) {
this.prop = prop;
};
Thing.prototype.getProp = function() {
return this.prop;
};
// Let's assume we've got a situation where there's going to be a lot of
// binding, eg. doSomethingWith(myThing.getProp.bind(myThing)); and we want
// to simplify app code by reducing the number of times .bind(myThing) gets
// called.
var myThing = new Thing("Test");
myThing.getProp() // "Test"
myThing.getProp.call(null) // "Test"
myThing.setProp("Another Test");
myThing.getProp() // "Another Test"
myThing.getProp.call(null) // "Another Test"