Functions are powerful construct in JavaScript. In this tutorial, we are going to do some advanced function manipulations with. Do you like Reflection? Then you’ll love this tutorial ![]()
You can click here, to get the source code of this tutorial (12Kb zipped archive) »»
You can also visit the API documentation for o2.MethodHelper.
A Big Caveat!
Don’t use a pattern just for the sake of using it
![]()
memento, partial, and curry, which we’ll se in this tutorial, are powerful JavaScript constructs.
What they do is similar to the Reflection operation in strong-typed languages like C#. That is to say, they change and augment the runtime behaviors of methods.
Just like Reflection, when used wisely, they are great helpers. When over-used, though, they’ll damage your code’s readability and maintainability.
Memoization
It’s possible that some of your JavaScript functions may be doing resource-intensive calculations that may take too long time to complete, or may consume too much of CPU power.
If constantly need to call these kinds of functions over and over again, it will be bad in terms of performance.
Luckily, there are several things you can do:
- Leave the complex calculation burden to the Server, and call the Server’s corresponding web method, using AJAX and use the already-calculated output,
- Cache the output for some time, and use the cached results,
- If you know that you’ll need some of the results, pre-cache them before even using the function,
- Or a mixture of both.
If you prefer a client-side, or server-side caching, you need to take into account when the cache will be out of date. Will it have an expiry time, so that when that interval is reached, the cache value is discarded and the function recalculates its output by doing its resource-extensive operation — or will the data always remain cached during the application’s life-cycle. — Though these are points to be mentioned in a further article.
For this section we’ll be observing a pattern called “memoization” only:
memoize: function() {
var pad = {};
var args = Array.prototype.slice.call(arguments);
var self = args.shift();
var obj = args.length > 0 ? args[0] : null;
var memoizedFn = function() {
// Copy the arguments object into an array:
// this allows it to be used as a cache key.
var args = [];
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
// Evaluate the memoized function if it hasn't been evaluated with
// these arguments before.
if (!(args in pad)) {
pad[args] = self.apply(obj, arguments);
}
return pad[args];
};
return memoizedFn;
},
The comments are self-explanatory.
Let’s see how the method behaves:
function resourceConsumingOperation(a,b){
//just for the sake of the demo.
return a+b;
}
var memoized = o2.MethodHelper.memoize(resourceConsumingOperation);
out ( memoized(3,2) );//returns 5, fresh calculation
out ( memoized(4,5) );//returns 9, fresh calculation
out ( memoized(3,2) );//returns 5, from cache
For repeated resource-extensive calculations, memoization pattern is a life-saver
![]()
Do You Like Your Chicken With, or Without Curry?
Let’s look at another useful construct:
//See http://www.dustindiaz.com/javascript-curry/ for a discussion.
curry: function() {
var args = [].slice.call(arguments);
var context = args.shift();
var fn = args.shift();
return function() {
return fn.apply(context, args.concat(Array.prototype.slice.call(arguments)));
};
},
The curry function simply returns a closure, filling given arguments of the passed function, and remaining the rest to be applied later on.
This can be best demonstrated with an example:
function chicken(a, b, c){
return 'To cook a "curry-sauced chicken" you need <b>' + a + '</b>, <b>' + b +
'</b>, and <b>' + c + '</b>.';
}
var curriedChicken = o2.MethodHelper.curry(this, chicken, 'a chicken', 'potato chips');
out( curriedChicken('curry sauce') );
//will output: To cook a "curry-sauced chicken" you need a chicken, potato chips, and curry sauce.
Neat, isn’t it?
Partial Methods
But, what if we want to prefill an arbitrary set of arguments, not the first few ones.
Then Partial Methods will be helpful:
// See http://ejohn.org/blog/partial-functions-in-javascript/ for a detailed discussion.
partial: function() {
var args = Array.prototype.slice.call(arguments);
var context = args.shift();
var fn = args.shift();
return function() {
var arg = 0;
for (var i = 0; i < args.length && arg < arguments.length; i++) {
if (args[i] === undefined) {
args[i] = arguments[arg++];
}
}
return fn.apply(context, args);
};
}
The code above acts just like curry. With one major difference: when you leave any argument undefined it’s marked as a placeholder.
Let’s see with an example:
var partialChicken = o2.MethodHelper.partial(this, chicken, undefined, 'pepper', undefined);
out( partialChicken('a mule', 'garlic'));
//will output: To cook a "curry-sauced chicken" you need a mule, pepper, and garlic.
Require All Arguments
Here’s another useful method:
me.requireAllArguments = function(fn) {
return function() {
// throw an error if the arguments' length do not match.
if (arguments.length < fn.length) {
throw format(config.constants.error.ARGUMENT_COUNT_MISMATCH, fn.length,
arguments.length);
}
return fn.apply(this, arguments);
};
};
And an example usage:
function lnx(x, lnx, c){
return x * lnx - x + c;
}
var requireAll = o2.MethodHelper.requireAllArguments(lnx);
try {
requireAll(42, 42);
} catch(e){
out( e );//Expected 3 arguments but found 2
}
out( requireAll(42, 42, 42) );
//outputs: 1764
Method Overloading
What if we want to overload a method depending on the number of arguments it has.
o2.MethodHelper.overload is exactly meant for this:
me.overload = function(object, name, fn) {
var old = object[name];
object[name] = function() {
// If both function have identical # of arguments,
// then call the cached function.
if(fn.length == arguments.length) {
return fn.apply(this, arguments);
}
// Otherwise try to call the old function, if any.
if(typeof old == 'function') {
return old.apply(this, arguments);
}
};
};
And here’s a usage example:
var base = {};
o2.MethodHelper.overload(base, 'calculate', function(a){
return a;
});
o2.MethodHelper.overload(base, 'calculate', function(a, b){
return a * b;
});
o2.MethodHelper.overload(base, 'calculate', function(a, b, c){
return Math.pow(c, a * b);
});
out( base.calculate(2) );//2
out( base.calculate(2, 3) );//6
out( base.calculate(2, 3, 4) );//4096
Delayed Execution
Let’s assume we wish to delay the execution of a function for a certain amount of time. Then this code will help:
me.defer = function(fn, interval, context, args) {
setTimeout( function() {
return fn.apply(context,args);
},interval);
};
And a usage example:
o2.MethodHelper.defer(function(){
out('I will print after at least 2 seconds');
}, 2000);
…
That’s all for now. Hope you enjoyed it.
Do you have any magic tricks in your pocket?
Feel free to share them in your comments

