Nesting Iterator Functions
Example of functional programming in JavaScript
by Patrick Hund
CSS
body {
background-color: #000000;
padding: 10px;
font-family: monospace;
}
p {
margin: 0;
color: green;
}
p.new {
color: lime;
}
JavaScript
var roman,
arabic,
alpha;
function log() {
var $body = $("body"),
$doc = $(document),
msg = "", i;
for (i = 0; i < arguments.length; i++) {
msg += (arguments[i] + (i === arguments.length - 1 ? "" : " "));
}
$body.find("p").last().removeClass("new");
$body.append("<p class=\"new\">" + msg + "</p>");
$doc.scrollTop($body.prop("scrollHeight"));
}
function nest() {
var functions = arguments,
findex = functions.length - 1,
f = functions[findex];
while (--findex >= 0) {
f = functions[findex](f);
}
f();
}
function iterate() {
var slice = Array.prototype.slice,
items = [],
i;
for (i = 0; i < arguments.length; i++) {
items = items.concat(arguments[i]);
}
return function (callback) {
return function() {
var prev = slice.apply(arguments),
i;
for (i = 0; i < items.length; i++) {
if (typeof callback === "function") {
callback.apply(null, prev.concat(items[i]));
}
}
};
};
}
roman = iterate("I", "II", "III"); // you can pass items as variable number of arguments
arabic = iterate(["1.", "2.", "3."]); // you can also pass items as array
alpha = iterate(["a)", "b)"], "c)", ["d)"]); // you can mix both methods of passing items
nest(roman, arabic, alpha, log); // same result as: roman(arabic(alpha(log)))();