looking for a full-immersion/face-to-face HTML5, JavaScript, and Mobile Web Development training in the heart of London? Book your spot
Showing posts with label bind. Show all posts
Showing posts with label bind. Show all posts

Wednesday, November 28, 2012

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!

Tuesday, January 10, 2012

Introducing ObjectHandler

since the discussion about a better Function#bind will probably never end, and since a must have dependency would be the ES6 WeakMap which is in any existent shim leak prone due lack of control via ES5+, I have proposed another way to solve the problem.

ObjectHandler IDL Like


/**
* interface ObjectHandler implements EventListener {
* void handleEvent(in Event evt);
* void remitEvent(in Event evt);
* attribute Object events;
* };
*
* @link http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener
*/
var ObjectHandler = {
handleEvent: function handleEvent(e) {
var
events = this.events,
type = e.type
;
if (events.hasOwnProperty(type)) {
events[type].call(this, e);
}
},
// it could be called removeEvent too, as you wish
remitEvent: function cancelEvent(e) {
e.currentTarget.removeEventListener(
e.type, this, e.eventPhase === e.CAPTURING_PHASE
);
}
};

Above object is an Abstract implementation. In JavaScript we can borrow methods so whatever "class" would like to implement above behavior should extend the object or borrow those two methods and specify an events property.

Examples

Let's say we have a UI Class which aim is to react to certain events ... let's call it button:

function UIButton(parentNode) {
// add the node
this.el = parentNode.appendChild(
parentNode.ownerDocument.createElement("button")
);
// add quickly events to the node
for (var key in this.events) {
// add the listener ...
// NOTE: nothing to bind, no duplicated entries either
this.el.addEventListener(key, this, false);
}
}

// extends the class
Object.defineProperties(
UIButton.prototype,
{
// implements ObjectHandler
handleEvent: {value: ObjectHandler.handleEvent},
remitEvent: {value: ObjectHandler.remitEvent},
events: {value: {
// only once thanks to remitEvent
click: function (evt) {
alert("only once");
this.remitEvent(evt);
},
// some decoration on actions
mousedown: function (evt) {
this.el.style.border = "1px solid black";
},
mouseup: function (evt) {
this.el.style.border = null;
},
// recicle mouseup behavior
mouseout: function (evt) {
this.events.mouseup.call(this, evt);
}
}}
}
);

// example on window load
this.onload = function () {
new UIButton(document.body);
};

Got it? Events property is simply an object shared through the prototype with properties name that are exactly the equivalent of DOM events name ... easy!

Pros

  • memory safe, nothing to bind, trap as bound, and stuff like this ... all instances will share same logic and bind is not even needed, aka: problem solved
  • events are defined in a single place, easy to find, maintain, extend
  • events are recycled, as it was as example for mouseout, though the instance
  • most UI frameworks need the instance rather than the DOM node, to behave accordingly
  • ObjectHandler can be used same way for "ObjectTarget", those listeners/able JS implementations, in order to uniform an event driven approach
  • no risk to bind twice, no risk to remove the wrong callback, bound or not, it's the instance that makes the deal, not inline functions so it's less error prone
  • performances in therms of both memory footprint and operation per each instance ... once again, no need to bind all methods to the instance itself ... what is in events is basically bound automatically through a single entry point, defined in ObjectHandler, for every single use case


Cons

... no idea, I cannot find any and I just like this solution over the Function#bind improvements since it's both cross platform, whenever addEventListener is present, but it can be recycled for any other no DOM use case as long as the event will have a currentTarget property that points to the current instance ( I will write an example/proposal soon ... OK? )

As Summary

The main problem with proposal is adoptions and I would like to know UI Framework users feedbacks. Ideally this way to handle events could become a de facto standard dropping the redundant and massive usage of Function#bind for cases where the focus should be for the instance and not for the callback.

Wednesday, January 04, 2012

Improving Function.prototype.bind

There are a couple of things I have never liked that much about Function#bind and this post is about proposing a pattern hopefully better than common one.

At The End Of The Function

A common argument about parentheses around inline invoked functions is that developers can easily recognize them.

// considered ambiguous
var someThing = function () {
return {};
}();

// considered not ambiguous
var someThing = (function () { // note the parenthesis
return {};
}()); // note the parenthesis

// exact same behavior of latest one
// but considered slightly ambiguous
var someThing = (function () { // note the parenthesis
return {};
})(); // note the parenthesis

The parentheses version apparently wins but, specially when no assignment is needed, I believe these are even less ambiguous:

-function(){
alert("OK");
}();

+function(){
alert("OK");
}();

!function(){
alert("OK");
}();

Of course if there is an operator that function will be executed, why on earth anyone would do that otherwise?
Anyway, the problem with all of these human friendly syntax pattern recognition strategies, is that the context of the function, or the whole code behavior, could be polluted/changed via bind or call or apply so we need in any case to scroll 'till the end to better understand what is going on inside the function and what is returned, exactly.

// ES3 example
var something = (function(){
// this could be global object or something else
return this.doSomeStuff();
}.bind(unexpectedObject)); // or call for other cases

// ES5
var something = (function(){"use strict";
// if there is a this reference
// we need to reach the end to understand
// what is it
return this.doSomeStuff();
}.bind(unexpectedObject));

The summary is that bind, used inline, is more like a yoda condition rather than a developer friendly helper so the first point is that bind, as it is, forces the developer to always check the end of the function to know if this has been executed inline or it has been bound to a different context, as well as yoda conditions forces the developer to read "upside down" a statement.
Last, but not least, of course if it's just about bind, parentheses are not helping at all ... still scroll 'till the end

// perfectly valid, not even executed
// but still important to know
// what will be the context for future calls
var something = function(){
return this.doSomeStuff();
}.bind(unexpectedObject);


Team Speaking

Ok, agreed, a function bigger than 10 lines is not that good and should be split and blah blah blah ... point is that sometimes function have to be big since these provide us a way to create private variables and methods ... ok?
Also if that was "the good part", I mean just putting parentheses around, there is some conflict with the fact that functions should not be that long ... I mean, how can we mistake whatever happened in 10 lines?
The truly good part could be done by developers, specially those that work in a team.
The first good rule is to write a bloody single line comment at the very first line, this would just solve everything:

var something = function () {
//! executed inline, returns object

... the rest of the code ...
}();

var somethingElse = function () {
//! bound to variable obj

... the rest of the code ...
}.bind(obj);

var somethingCrazy = function () {
//! bound to obj + executed inline

.. the rest of the code ...
}.bind(obj)();

-function(){
// bound to obj
}.bind(obj)();

Got it? Nobody would ever complain about these little helps ... isn't it? But since we are all lazy devs, the second helper is function declaration rather than function expression.

function impossibruToConfuse(){}

var something = impossibruToConfuse.bind(obj);
var something = impossibruToConfuse();
var something = impossibruToConfuse.call(obj);

With a single line to read I believe the problem is solved ... isn't it? Still ways to improve.

Unable To Retrieve Same Bound Function

The second most annoying thing ever, something that leads inevitably to uncomfortable patterns, is the inability to retrieve an already bound function through the same object.
In my humble opinion, was a freaking design mistake indeed to create a new bound object per each bind call since I believe nobody in this world ever used this "feature".

function task(){}

// Y U NO THE SAME !!!
task.bind(window) === task.bind(window);
// false ....

If the function is the same it means it has same context, inner and outer scope of the other function bound to the same object.
If we bind twice the same object we are doing it wrong 'cause most likely we never meant/need two different bound callbacks/objects for that task ... isn't it?

An Error Prone Logic

The most basic fail of this logic is about listeners, both DOM listeners or self implemented listeners, extremely common in an always more asynchronous driven language as JavaScript is.

generic.addEventListener("stuff", stuff.bind(obj), false);

// how many times have you seen this later on?
generic.removeEventListener("stuff", stuff.bind(obj), false);

Above example won't work as expected ... of course it won't work as expected ... developers expect the same function/object, instead they have a new one.
This approach forces developers to store temporarily the bloody bound function to some private, global, variable or property.

obj._boundStuff = stuff.bind(obj);
generic.addEventListener("stuff", obj._boundStuff, false);

// ... later on ...
if (obj._boundStuff) {
generic.removeEventListener("stuff", obj._boundStuff, false);
}

Remember how lazy we are so that parentheses became one of the good parts of JavaScript since a line of comment was too boring? Now look again at latest example and think how many times you have done something similar ...

A Clever Object.prototype.boundTo

With ES5 we are so lucky to be able to pollute global constructors without influencing for/in and as long as our implementation is not obtrusive and, most important, makes sense.
I came up with this proposal in order to solve at least latest problems described before: a lazy boundTo method

!function (Object) {

// (C) WebReflection - Mit Style License

var // private scope shortcuts
BOUND_TO = "boundTo", // or maybe "asContextOf" ?
defineProperty = Object.defineProperty,
bind = defineProperty.bind || function (self) {
// simple partial shim for "not there yet" ES5 browsers
var callback = this;
return function bound() {
return callback.apply(self, arguments);
};
}
;

defineProperty(
Object.prototype,
BOUND_TO, {
value: function (callback, remove) {
// only the very first time
// two private stacks are created
// and related to the current object
var
cbStack = [],
boundStack = [],
self = this
;
// overwrite the inherited BOUND_TO method
// with the one we actually need
defineProperty(
self,
BOUND_TO, {
value: function boundTo(callback, remove) {
var
i = cbStack.indexOf(callback),
callback = i < 0 ?
boundStack[
i = cbStack.push(callback) - 1
] = bind.call(callback, self)
:
boundStack[i]
;
// falsy values accepted
// except null or undefined
// so it's true by default
if (remove == false) {
cbStack.splice(i, 1);
boundStack.splice(i, 1);
}
// returns bound callback in any case
// handy to remove listeners and clean stacks
// in one single operation
return callback;
}
}
);
// only the first time, invoe the overwritten method
// use directly latter one every other time
return self[BOUND_TO](callback, remove);
}
}
);
}(Object);

How above snippet is supposed to be used? Here a basic example:

generic.addEventListener("stuff", obj.boundTo(stuff), false);

// ... later on ...
generic.removeEventListener("stuff", obj.boundTo(stuff, 0), false);

// bear in mind that ...
obj.boundTo(stuff) === obj.boundTo(stuff);
// always ... unless we release explicitly the bound function/object
obj.boundTo(stuff, false) !== obj.boundTo(stuff);
// since once removed, the new obj.boundTo call will create a new one

Pros

No need to check, no need to store the bound version, memory leaks safe, no need to do anything extra except calling the method through, and this is needed, the same function.
The semantic is straight forward and rather than a yoda condition we have a clear operation that means: return the function created to bind this object as context.
Last, but not least, even if the function was not bound, everything should work as expected, as long as the removeListener generic method has been implemented properly ( checking if the callback/object was attached already )

Cons

Not really, but the function has to be the same. It must be said that two apparently identical functions could be just a copy and paste in two completely different outer scopes. This means that there is no bullet proof way to understand if a function written twice is similar to another one since it is not possible to understand surrounding scopes and it would be silly to do this even on the JS engine level. I am talking about another, unfortunately, common mistake:

// wrong examples ... does not work as expected

generic.addListener("whatever", function () {
return this.whatever;
}.bind(object), false);

// followed by ...
generic.removeListener("whatever", function () {
return this.whatever;
}.bind(object), false);

// or in this proposal case ...

generic.addListener("whatever", object.boundTo(function () {
return this.whatever;
}), false);

// followed by ...
generic.removeListener("whatever", object.boundTo(function () {
return this.whatever;
}), false);

// ... but this is not how JavaScript works ...

Memory speaking, the very first time we use this strategy we create two extra arrays able to speed up operations through indexed function and and bound version per each object. This is inevitable in any case and it's almost exactly the same we do when we address once the bound function.
Once the object has been Garbage Collected, related private arrays will have a reference count equal to zero so the memory should clean up automatically without problems and including all functions bound to that object.

As explained in the example, it is possible in any case to release explicitly bound functions so we can feel like the memory usage is under control.

Why No Arguments

The combination of arguments could be such big number that this technique won't be interesting anymore, specially regarding performances.
It does not really make sense to over complicate such basic, most needed, scenario but if you think this is the biggest impediment, then the name should simply be asContextOf so that no ambiguity would be shared with bind native signature.

Update - Preserving Private Methods

Another reason to chose my proposal is the ability to bind proper private methods without using the current instance to store the bound method anywhere ... follow the es-discuss ML to know more but here the stupid, basic, proof of concept:

// stupid useless example ... just as concept
var Counter = (function () {
// private
function increase() {
this.clicks++;
}

function Counter() {
// none out there should be able to retrieve the bound function
document.addEventListener("click", this.boundTo(increase), false);
};
Counter.prototype.clicks = 0;
Counter.prototype.destroy = function () {
// so that only this class scope can control things and nobody else
document.removeEventListener("click", this.boundTo(increase), false);
};
return Counter;
}());


As Summary

I am pretty sure this simple lazy created proposal would be ideal for many frameworks and projects but if I am missing something or if you have any improvement to suggest, I will be more than happy to listen to you.
Enjoy simplicity over semantic, this is yet another KISS and YAGNI proposal from this blog.

Wednesday, October 05, 2011

bind, apply, and call trap

quick one out of ECMAScript ml

var
// used to trap function calls via bind
invoke = Function.call,
// normal use cases
bind = invoke.bind(invoke.bind),
apply = bind(invoke, invoke.apply),
call = bind(invoke, invoke)
;


What Is It

This is a way to trap native functions method in a handy way. Used in a private scope, it can address these methods once so that we can rely nobody can possibly change them out there for some script injection and only if we are sure the script has been loaded at the very beginning.

How To Use Them

Here few examples:

// secure hasOwnProperty
var hasOwnProperty = bind(invoke, {}.hasOwnProperty);
// later on
hasOwnProperty({key:1}, "key"); // true
hasOwnProperty({}, "key"); // false

// direct slice
var slice = bind(invoke, [].slice);
slice([1,2,3], 1); // 2,3
slice(arguments); // array

// direct call
call([].slice, [1,2,3], 1); // 2,3
// direct apply
apply([].slice, [1,2,3], [1]); // 2,3

// bound method
var o = {name:"WebReflection"};
o.getName = bind(
// the generic method
function () {
return this.name;
},
// the object
o
);
o.getName(); // WebReflection
That's pretty much it, except if we don't trust native Function.prototype, we should not trust anything else as well so maybe it's good to use these shortcuts just because they are handy ;)

Saturday, February 20, 2010

Function.prototype.bind

Quick post about a fast Function.prototype.bind implementation.

Function.prototype.bind


function bind(context:Object[, arg1, ..., argN]):Function {
return a callback able to execute this function
passing context as reference via this
}

In few words, if we have a generic object, we don't necessary need to attach a function to create a method:

// a generic function
function name(name) {
if (name == null) return this.name;
this.name = name;
return this;
}

// a generic object
var wr = {name:"WebReflection"};

// a callback with a "trapped" object
var fn = name.bind(wr);

alert([

// wr has not been affected
wr.name, // WebReflection

// fn can always be called
fn(), // WebReflection

fn("test") === wr, // true
fn(), // test
wr.name // test

].join("\n"));

Designed to ensure the same context whatever way we decide to use the callback, included call, apply, setTimeout, DOM events, etc, Function.prototype.bind is one of the most useful/powerful JavaScript concept.
Unfortunately, this will be standard only with newer browser ...

Optimized bind for every browser


Update: as I have said I code what I need, I rarely google for simple tasks like this. Most of this code, in any case, has been readapted and tested to reach best performances, based on this proposal.

if (Function.prototype.bind == null) {

Function.prototype.bind = (function (slice){

// (C) WebReflection - Mit Style License
function bind(context) {

var self = this; // "trapped" function reference

// only if there is more than an argument
// we are interested into more complex operations
// this will speed up common bind creation
// avoiding useless slices over arguments
if (1 < arguments.length) {
// extra arguments to send by default
var $arguments = slice.call(arguments, 1);
return function () {
return self.apply(
context,
// thanks @kangax for this suggestion
arguments.length ?
// concat arguments with those received
$arguments.concat(slice.call(arguments)) :
// send just arguments, no concat, no slice
$arguments
);
};
}
// optimized callback
return function () {
// speed up when function is called without arguments
return arguments.length ? self.apply(context, arguments) : self.call(context);
};
}

// the named function
return bind;

}(Array.prototype.slice));
}


Why Bother

The concatenation optimization is something rarely present in whatever framework/library I have seen. While it makes the code a bit bigger than usual, performances will be the best for most common cases, those where optional arguments are not passed at all.
A simple test case, one of my favorites, able to solve the classic IE problem with extra arguments passed to setInterval/Timeout:

(function(){

var callback = function(time){
if (1000 < new Date - time)
return alert("1 second with a default argument");
setTimeout(callback, 15);
}.bind(null, new Date);

setTimeout(callback, 15);

}());