My Name Is Bound, Method Bound ...
it seems to me the most obvious thing ever but I keep finding here and there these common anti pattern:
// 1. The timer Case
this.timer = setTimeout(
this.doStuff.bind(this), 500
);
// 2. The Listener Case
(objOrEl || this).addEventListener(
type, this.method.bind(this), false
);
What Is Wrong
I have explained a while ago what's wrong and how to improve these cases but I understand the code was too scary and the post was too long so here the summary:- every
setTimeout()
call will create a new bound object and this is both redundant and inefficient plus it's not GC friendly - there is no way to retrieve that listener created inline so it's impossible to remove the listener any time is necessary ... yes, even after, when you do refactoring 'cause you will need to clean up listeners
What You Need
The short version is less than a tweet, 64bytes:function b(o,s,t){return(t=this)[s="@"+o]||(t[s]=t[o].bind(t))}
This is the equivalent of:
// as generic prototype method
function bound(methodName) {
var boundName = "__bound__" + methodName;
return this[boundName] || (
this[boundName] = this[methodName].bind(this)
);
}
// as generic utility
function bound(object, methodName) {
var boundName = "__bound__" + methodName;
return object[boundName] || (
object[boundName] = object[methodName].bind(object)
);
}
// as stand alone dependencies free prototype method
var bound = function(){
function bound(methodName) {
var boundName = uniqueId + methodName;
return this[boundName] || (
this[boundName] = bind.call(this[methodName], this)
);
}
var
uniqueId = "__bound__", // + Math.random(),
bind = bound.bind || function bind(self) {
var callback = this;
return function bound() {
return callback.apply(self, arguments);
};
}
;
return bound;
}();
// really ... you can write
// this little thing in many ways
Pick One And Use It !
These are benefits over the simple, ultra fast, performance oriented, and memory safe approach:
// 1. The timer Case
this.timer = setTimeout(
this.bound("doStuff"), 500
);
// 2. The Listener Case
(objOrEl || this).addEventListener(
type, this.bound("method"), false
);
- every
setTimeout()
call, if any, will create one single bound object - you can remove the listener at any time through the same call, i.e.
(objOrEl || this).removeEventListener(type, this.bound("method"), false);
Comments
Post a Comment