//
// var
// base_fn = function(){},
// tracer_fn = tracer( base_fn );
//
function tracer( fn ) {
return ( function( argsCache, F, _s ){
// define new fn that will have that capability
// it's a wrapper for original fn
var
fn2 = function(/*...params*/) {
var
// temporary stores original fn's result
out,
// capture passed arguments
theArgs = _s.call( arguments ),
//
// you can implement 'memo' functionality here
// if that's your goal,
// by 'scaning' already processed inputs
// in argsCache array
// and optionaly runing original fn,
// if no match is found
//
// save input and output of fn as h-map
argsIO = {
input : theArgs,
output : null
};
// execute original fn
// pass it captured arguments
// 'remember' it's result
out = F.apply( this, theArgs );
// save calculated value
argsIO.output = out;
// 'push' fn input-output record on the cache
argsCache.push( argsIO );
// return whatever original fn returned
return out;
};
// provide 'static' access to 'closured' cache
// use the array to inspect 'arguments history'
fn2.args = argsCache;
// provide a way to empty cache
fn2.clear = function () {
fn2.args.splice( 0, fn2.args.length );
return fn2.args;
};
// return fn 'upgrade'
return fn2;
} )( [], fn, Array.prototype.slice );
}
function basefn() {
// doStuff( arguments );
// returning value, as well as arguments,
// are recorded by tracer fn
return arguments.length;
}
// get the 'tracer' fn
var
fn = tracer( basefn );
// run it couple of times
// passing arbitrary arguments
fn( 12345, new XMLHttpRequest() );
fn('a', 'z', /^[a-z]+$/ );
fn( {}, [1,2,3] );
fn( location, document );
fn( Math );
//
// access 'args history' through fn.args ( array ) property
//
// var
// lastCallIO = fn.args[ fn.args.length - 1 ];
//
console.log( fn.args );
//
// empty cache, free some memory
//
// fn.clear();
//
//