How to Provide Named Parameters in a Function Call in JavaScript

Is there a way to provide named parameters in a function call in JavaScript?

ES2015 and later

In ES2015, parameter destructuring can be used to simulate named parameters. It would require the caller to pass an object, but you can avoid all of the checks inside the function if you also use default parameters:

myFunction({ param1 : 70, param2 : 175});

function myFunction({param1, param2}={}){
// ...function body...
}

// Or with defaults,
function myFunc({
name = 'Default user',
age = 'N/A'
}={}) {
// ...function body...
}

ES5

There is a way to come close to what you want, but it is based on the output of Function.prototype.toString [ES5], which is implementation dependent to some degree, so it might not be cross-browser compatible.

The idea is to parse the parameter names from the string representation of the function so that you can associate the properties of an object with the corresponding parameter.

A function call could then look like

func(a, b, {someArg: ..., someOtherArg: ...});

where a and b are positional arguments and the last argument is an object with named arguments.

For example:

var parameterfy = (function() {
var pattern = /function[^(]*\(([^)]*)\)/;

return function(func) {
// fails horribly for parameterless functions ;)
var args = func.toString().match(pattern)[1].split(/,\s*/);

return function() {
var named_params = arguments[arguments.length - 1];
if (typeof named_params === 'object') {
var params = [].slice.call(arguments, 0, -1);
if (params.length < args.length) {
for (var i = params.length, l = args.length; i < l; i++) {
params.push(named_params[args[i]]);
}
return func.apply(this, params);
}
}
return func.apply(null, arguments);
};
};
}());

Which you would use as:

var foo = parameterfy(function(a, b, c) {
console.log('a is ' + a, ' | b is ' + b, ' | c is ' + c);
});

foo(1, 2, 3); // a is 1 | b is 2 | c is 3
foo(1, {b:2, c:3}); // a is 1 | b is 2 | c is 3
foo(1, {c:3}); // a is 1 | b is undefined | c is 3
foo({a: 1, c:3}); // a is 1 | b is undefined | c is 3

DEMO

There are some drawbacks to this approach (you have been warned!):

  • If the last argument is an object, it is treated as a "named argument objects"
  • You will always get as many arguments as you defined in the function, but some of them might have the value undefined (that's different from having no value at all). That means you cannot use arguments.length to test how many arguments have been passed.

Instead of having a function creating the wrapper, you could also have a function which accepts a function and various values as arguments, such as

call(func, a, b, {posArg: ... });

or even extend Function.prototype so that you could do:

foo.execute(a, b, {posArg: ...});

How to use a default value for named parameter in Javascript

I think you're looking for default parameters

const someFunc = ({ a = "foo" }) => {

console.log(a);

}

someFunc({}); // "foo"

someFunc({a: "bar"}); // "bar"

Using named parameters in node.js

The standard Javascript way is to pass an "options" object like

info({spacing:15, width:46});

used in the code with

function info(options) {
var spacing = options.spacing || 0;
var width = options.width || "50%";
...
}

as missing keys in objects return undefined that is "falsy".

Note that passing values that are "falsy" can be problematic with this kind of code... so if this is needed you have to write more sophisticated code like

var width = options.hasOwnProperty("width") ? options.width : "50%";

or

var width = "width" in options ? options.width : "50%";

depending on if you want to support inherited options or not.

Pay also attention that every "standard" object in Javascript inherits a constructor property, so don't name an option that way.

Calling a function without reassigning named argument

You could store the values as property of the function.

function mainFun({ val1 = mainFun.val1, val2 = mainFun.val2, val3 = mainFun.val3 }) {

mainFun.val1 = val1;

mainFun.val2 = val2;

mainFun.val3 = val3;

console.log(val1, val2, val3);

}
<button onclick="mainFun({ val1: 'Caller 1' })">First Event</button>

<button onclick="mainFun({ val2: 'Caller 2' })">Second Event</button>

<button onclick="mainFun({ val3: 'Caller 3' })">Third Event</button>

JavaScript (ES6): Named parameters and default values

You need a default object.

var fun = ({ first = 1, last = 1 } = {}) => 1 * first + 2 * last;

// ^^^^

console.log(fun({ first: 1, last: 2 }));

console.log(fun({ last: 1, first: 2 }));

console.log(fun());

Using named parameters JavaScript (based on typescript)

True named parameters don't exist in JavaScript nor in TypeScript but you can use destructuring to simulate named parameters:

interface Names {
name1: boolean
name2: boolean
name3: boolean
name4: boolean
}

function myFunction({name1, name2, name3, name4}: Names) {
// name1, etc. are boolean
}

Notice: The type Names is actually optional. The following JavaScript code (without typing) is valid in TS:

function myFunction({name1, name2, name3, name4}) {
// name1, etc. are of type any
}

React pass parameters by names when calling a function

When you call the function, you just call it normally like any other function. There's nothing special about calling functions with default params set. However, it usually doesn't make sense to have too many default params, especially if you need to often specify one after the first one, since then you end up having to specify the value of the first "optional" param every time anyways.

onChange={(e) => this.handleChange(false, true, e)}

Non-default parameters should always go first by the way, so that you don't need to specify every default param:

handleChange(event, required = false, test = false)

Then you could call any of:

handleChange(event) // required=false, test=false
handleChange(event, true) // required=true, test=false
handleChange(event, true, true) // required=true, test=true
...

Maybe instead you want to create a callback that takes an options object, and set some of the values based on defaults:

handleChange(event, options = {}) {
const required = options.required ? options.required : false;
const test = options.test ? options.test : false;

...
}

Then you would call it like:

handleChange(event) // required=false, test=false
handleChange(event, { required: true }) // required=true, test=false
handleChange(event, { test: true }) // required=false, test=true
handleChange(event, { required: true, test: true }) // required=true, test=true


Related Topics



Leave a reply



Submit