Skip to content

Instantly share code, notes, and snippets.

@XoseLluis
Last active December 17, 2015 17:59
Show Gist options
  • Save XoseLluis/5649499 to your computer and use it in GitHub Desktop.
Save XoseLluis/5649499 to your computer and use it in GitHub Desktop.
Enabling a simple form of Named Parameters in JavaScript A function that receives another function and returns a new function where Named Parameters have been enabled. It has been updated so that a function accepts both unnamed and named parameters. Notice the Named parameters must be passed as the last ones.
//gets an array with the names of the parameters to a function
//taken from:
//http://stackoverflow.com/questions/9091838/get-function-parameter-names-for-interface-purposes/9092085#9092085
function getFnParamNames(fn){
var fstr = fn.toString();
return fstr.match(/\(.*?\)/)[0].replace(/[()]/gi,'').replace(/\s/gi,'').split(',');
}
//used to mark as such the support objects used to pass named parameters
function NamedParameters(obj){
obj._isNamedParams = true;
return obj;
}
//returns a new function that enables a form of Named Parameters in the function passed as parameter
//based on how named parameters work in C#, we can pass a mix of named and unnamed parameters, but the Named ones must be passed over as the last ones
function enableNamedParameters(fn){
if(typeof fn != "function")
throw new Error("fn is not a function");
if(fn._isNamedParamsEnabled || fn.length === 0){
console.log(fn.name + " is already NamedParamsEnabled");
return fn;
}
var paramNames = getFnParamNames(fn);
var namedParamsEnabledFn = function(){
var params = [];
//traverse the parameters that we've received, cheking if it's a normal one or a NamedParameter object. if present, the NamedParameter should be the last parameter provided, so other parameters after it are ignored
for(var i=0; i<arguments.length; i++){
if(!(arguments[i]._isNamedParams)){
params.push(arguments[i]);
}
else{
var paramsObj = arguments[i];
for(;i<paramNames.length;i++){
params.push(paramsObj[paramNames[i]]);
}
break;
}
}
return fn.apply(this, params);
};
namedParamsEnabledFn._isNamedParamsEnabled = true; //metadata to avoid further applying of enableNamedParams
return namedParamsEnabledFn;
}
if (typeof module !== "undefined" && module.exports){
exports.enableNamedParameters = enableNamedParameters;
exports.NamedParameters = NamedParameters;
}
var np = require("./namedParameters2");
var enableNamedParameters = np.enableNamedParameters;
var NamedParameters = np.NamedParameters;
function sayHi(name, age, city, language){
console.log("hi, my name is: " + name
+ " my age is: " + age
+ " I live in: " + city
+ " and my native language is: " + language);
}
var sayHi2 = enableNamedParameters(sayHi);
console.log("\n- using named parameters: ");
sayHi2(NamedParameters({
city: "Prague",
age: 20,
name: "Iyan"
}
));
console.log("\n- using unnamed parameters: ");
sayHi2("Iyan", 20, "Prague", "English");
sayHi2("Iyan");
console.log("\n- using both unnamed and named parameters:");
sayHi2("Iyan", NamedParameters({
language: "English",
age: 20,
city: "Prague"
}));
//notice the unnamed parameter "Prague" is being passed after the named ones, so it's being ignored
sayHi2("Iyan", NamedParameters({
language: "English",
age: 20}),
"Prague"
);
//try to enable named params in a function where it's already enabled
var sayHi3 = enableNamedParameters(sayHi2);
console.log("just the same function was returned? " + (sayHi3 === sayHi2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment