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:
  1. every setTimeout() call will create a new bound object and this is both redundant and inefficient plus it's not GC friendly
  2. 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
);
  1. every setTimeout() call, if any, will create one single bound object
  2. you can remove the listener at any time through the same call, i.e. (objOrEl || this).removeEventListener(type, this.bound("method"), false);

Is That It ?

You are free to over complicate this concept as much as you want as long as you got the point: there's no need to create a new bound Object per each call plus your life will be much easier following this pattern focusing on logic rather than possible typos, boring variable assignments, etc etc ... this works and it's what you need and what you want now. I'm also moving my hands as a Jedi so I hope I've convinced you!

Comments

Popular posts from this blog

8 Things you should not be afraid of as a Developer

News

Why REST is so important