Skip to content

Instantly share code, notes, and snippets.

@rwaldron
Forked from dherman/closure.js
Created July 27, 2012 23:36
Show Gist options
  • Save rwaldron/3191053 to your computer and use it in GitHub Desktop.
Save rwaldron/3191053 to your computer and use it in GitHub Desktop.
Analog to Function constructor for building closures
(function() {
var hasOwnProperty = Object.prototype.hasOwnProperty;
var Function = hasOwnProperty.constructor;
function isIdentifier(s) {
return /[a-zA-Z_$][a-zA-Z_$0-9]*/.test(s);
}
Closure = function Closure(args, body, env) {
var closedVars = [], closedVals = [];
for (var key in env) {
if (!hasOwnProperty.call(env, key))
continue;
if (!isIdentifier(key))
throw new Error("invalid variable name: " + key);
closedVars.push(key);
closedVals.push(env[key]);
}
// validate the syntax of the body as a FunctionBody
(new Function(body));
// validate the syntax of the formal parameters as FormalParameters
Function.apply(null, args);
// declare closed variables initialized from an array bound to `this`
var closeVars = "var " + closedVars.map(function(x, i) {
return x + " = this[" + i + "]";
}).join(",") + ";";
// return the function that closes over the variables
var returnClosure = "return function(" + args.join(",") + "){" + body + "};";
closedVals.maker = new Function(closeVars + returnClosure);
return closedVals.maker();
};
Closure.prototype = Function.prototype;
})();
var f = new Closure([], "return x + y", { x: 1, y: 77 });
console.log(f()); // 78
var g = new Closure(["z"], "return x + y + z", { x: 1, y: 77 });
console.log(g(13)); // 91
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment