Skip to content

Instantly share code, notes, and snippets.

@bga
Created February 16, 2011 07:43
Show Gist options
  • Save bga/829004 to your computer and use it in GitHub Desktop.
Save bga/829004 to your computer and use it in GitHub Desktop.
Function bind.js
/*
uses compilation to optimize `Function#bind`, but not real `bind` which in fact - `carry`
inlines consts.
*/
var defaultThis = (function(){ return this })();
this._fastBind = (function()
{
var _quoteString = function(s)
{
return s.replace(
/\n|\r|\\|\"/g, function(c)
{
switch(c)
{
case '\n': return '\\n';
case '\r': return '\\r';
case '\\': return '\\\\';
case '\"': return '\\\"';
}
}
);
};
return function(_fn, that, args)
{
var _ret;
if(args == null)
{
_ret = (that === defaultThis)
? function(){ return (arguments.length > 0) ? _fn.apply(this, arguments) : _fn.call(this) }
: function(){ return (arguments.length > 0) ? _fn.apply(that, arguments) : _fn.call(that) }
;
}
else
{
var argsStr = '_fn,', callStr = '', nonConstArgs = [_fn], j = 1;
if(that !== defaultThis)
{
callStr = '.call(that,';
argsStr += 'that,';
nonConstArgs[j++] = that;
}
else
{
callStr = '(';
}
var i = -1; while(++i < args.length)
{
var a = args[i];
if(a === null)
{
callStr += 'null,';
}
else
{
switch(typeof(a))
{
case 'string':
callStr += '"' + _quoteString(a) + '",';
break;
case 'number':
case 'boolean':
case 'undefined':
callStr += '' + a + ',';
break;
default:
callStr += 'a' + i + ',';
nonConstArgs[j++] = a[i];
argsStr += 'a' + i + ','
}
}
}
callStr = callStr.slice(0, -1);
argsStr = argsStr.slice(0, -1);
_ret = Function(argsStr, 'return function(){ return _fn' + callStr + ') }').apply(null, nonConstArgs);
}
_ret.prototype = _fn.prototype;
return _ret;
};
})();
this._basicBind = function(_fn, that, args)
{
var _ret;
if(that !== defaultThis)
{
_ret = (args != null)
? function(){ return _fn.apply(that, args); }
: function(){ return (arguments.length > 0) ? _fn.apply(that, arguments) : _fn.call(that); }
;
}
else
{
_ret = (args != null)
? function(){ return _fn.apply(this, args); }
: function(){ return (arguments.length > 0) ? _fn.apply(this, arguments) : _fn.call(this); }
;
}
_ret.prototype = _fn.prototype;
return _ret;
};
var _fn = function(a, b, c)
{
return a + b + c;
};
var args = [1, '', {}, null, function(){}];
_speedTest({
'native bind': Function.prototype.bind && function(n)
{
var _fnB = _fn.bind.apply(_fn, [window].concat(args)), a;
while(n--)
a += _fnB();
},
'_basicBind': function(n)
{
var _fnB = _basicBind(_fn, window, args), a;
while(n--)
a += _fnB();
},
'_fastBind': function(n)
{
var _fnB = _fastBind(_fn, window, args), a;
while(n--)
a += _fnB();
}
}, 100000);
/*
chrome11 1000000
_basicBind: 3397 ms
_fastBind: 1095 ms
native bind: 5991 ms
ie8 60000
_basicBind: 721 ms
_fastBind: 581 ms
native bind: skipped
opera 10.62 400000
_basicBind: 1329 ms
_fastBind: 527 ms
native bind: skipped
ff3.6 100000
_basicBind: 927 ms
_fastBind: 384 ms
native bind: skipped
ff4 800000
_basicBind: 893 ms
_fastBind: 922 ms
native bind: 2617 ms
safari5 500000
_basicBind: 1588 ms
_fastBind: 887 ms
native bind: skipped
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment