Created
June 19, 2009 18:43
-
-
Save silentmatt/132782 to your computer and use it in GitHub Desktop.
Functions for dealing with function parameters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Get an array of parameter names for a function. | |
Example: | |
js> function f(a, b, c) { return a + b * c; } | |
js> JSON.stringify(Function.parameters(f)); | |
["a","b","c"] | |
*/ | |
Function.parameters = function(f) { | |
var m = /function[^\(]*\(([^\)]*)\)/.exec(f.toString()); | |
if (!m) { | |
throw new TypeError("Invalid function in parameters"); | |
} | |
var params = m[1].split(','); | |
for (var i = 0; i < params.length; i++) { | |
// trim any spaces | |
params[i] = params[i].replace(/^\s*|\s*$/g, ''); | |
} | |
return params; | |
}; | |
/* | |
Create a new function that accepts its parameters in an object instead of | |
its positional parameters. An optional array of names can be provided | |
instead of using the parameters defined in the function (to rename | |
parameters, or since some functions might use parameters that aren't named). | |
Examples: | |
js> function f(a, b, c) { return a + b * c; } | |
js> f(1, 2, 3); | |
7 | |
js> var f1 = Function.withNamedParameters(f); | |
js> f1({ a:1, b:2, c:3 }); | |
7 | |
js> // Call with an array (like f.apply) | |
js> var f2 = Function.withNamedParameters(f, [0, 1, 2]); | |
js> f2([1, 2, 3]); | |
7 | |
*/ | |
Function.withNamedParameters = function(f, params) { | |
// XXX: should this force f to be a function, or should anything that passes | |
// the parameters RegExp with an apply function work? | |
params = params || Function.parameters(f); | |
return function(args) { | |
var argsArray = new Array(params.length); | |
for (var i = 0; i < params.length; i++) { | |
argsArray[i] = args[params[i]]; | |
} | |
return f.apply(this, argsArray); | |
}; | |
}; | |
/* | |
Create a new function that accepts its positional parameters as objects | |
mapping parameter names to values. Each parameter array maps ascending | |
arguments to properties in an object. With a single parameter array, this is | |
the opposite of Function.withNamedParameters. | |
Examples: | |
js> function f(p1, p2) { return { x: p1.x + p2.x, y: p1.y + p2.y }; } | |
js> var f1 = Function.withPositionalParameters(f, ["x","y"], ["x","y"]); | |
js> JSON.stringify(f1(1, 2, 3, 4)); | |
{"x":4,"y":6} | |
js> function f(a, b, c) { return a + b * c; } | |
js> var f1 = Function.withNamedParameters(f); | |
js> var f2 = Function.withPositionalParameters(f1, ["a", "b", "c"]); | |
js> f2(1, 2, 3); // f2 is equivalent to (but slower than) f | |
7 | |
js> // Reorder parameters | |
js> var f3 = Function.withPositionalParameters(f1, ["c", "b", "a"]); | |
js> f3(3, 2, 1); | |
7 | |
*/ | |
Function.withPositionalParameters = function(f, params /*, ... */) { | |
params = Array.prototype.slice.call(arguments, 1); | |
return function() { | |
var args = []; | |
var argumentsIndex = 0; | |
for (var i = 0; i < params.length; i++) { | |
var arg = {}; | |
var paramList = params[i]; | |
args.push(arg); | |
for (var p = 0; p < paramList.length; p++) { | |
arg[paramList[p]] = arguments[argumentsIndex]; | |
++argumentsIndex; | |
} | |
} | |
return f.apply(this, args); | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment