Skip to content

Instantly share code, notes, and snippets.

@dherman
Created July 27, 2012 21:39
Show Gist options
  • Save dherman/3190598 to your computer and use it in GitHub Desktop.
Save dherman/3190598 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
@fitzgen
Copy link

fitzgen commented Jul 28, 2012

Cool, thanks for the replies, guys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment