Created
February 16, 2011 07:43
-
-
Save bga/829004 to your computer and use it in GitHub Desktop.
Function bind.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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