Reputation: 3632
I have a function like this:
let showNotification = function(a,b,c,d,e,f){
console.log(a,b,c,d,e,f);
}
While calling this function, I know I need to follow order, something like this (if I dont want to pass param for c,d,e):
showNotification(1,2,,,,6);
But this forces me to make sure I pass all parameter and it should be in order..
I am looking for a better way to pass param in this case.
I know that I can create an object of param instead where instead of passing the values. something like this:
let showNotification = function(objectParam){
console.log(objectParam.a, objectParam.b, objectParam.c, objectParam.d, objectParam.e, objectParam.f)
}
then call it:
showNotification({a: 1, b: 2, e:6});
I can pass whole object but this is not what I am looking. I do not want to create object every time for this.
Thinking loud, if there is a way to pass the string values, without taking care of the order.
I see some dead SO posts regarding this, but no one has solution.
Upvotes: 4
Views: 2831
Reputation: 1075009
TL;DR I know you didn't want to use an object, but modern JavaScript engines are really fast at creating and disposing of objects, and with parameter defaults and parameter destructuring, I think an options object is your best option. See "Notes on passing in an object (defaults, destructuring)" below for details.
You've covered two of the main options (I'm going to make some notes on the passing-in-an-object version below). A third option is to adopt the a variant of builder pattern, but it involves using an object too. You've said you don't want to do that, but haven't said why not. Note that modern JavaScript engines create and dispose of objects really, really fast if that's your concern.
A fourth option occurred to me when reading Bhushan Babar's append/prepend idea: Instead of doing that, you could use marker strings in the arguments list to indicate what the next argument is, e.g.:
showNotification("the required parameter", "a", value_for_a, "c", value_for_c);
On first glance, that doesn't involve creating an object, but on modern JavaScript engines, processing it will create an object that isn't otherwise created: arguments
, the pseudo-array of passed-in arguments. Because that (or a rest parameter, which also creates an object) is the only reasonable way you could consume such a thing.
In this approach, the main function returns a builder object with setters for the various options, and then a final "Yep, we're ready" call that starts the process (where in the builder pattern that final call usually builds the final object). Using it would look something like this:
showNotification("the required param")
.withA(value_for_a)
.withC(value_for_c)
.go();
Implementing this is complicated relative to other approaches, but not difficult.
If you do use an object (despite not wanting to), you can use default parameters and destructuring to make the object more convenient to work with:
let showNotification = function({a = 1, b = 2, c = 3, d = 4, e = 5, f = 6} = {/*default if no object at all*/a: "foo"}){
console.log(a,b,c,d,e,f);
};
showNotification();
showNotification({});
showNotification({a:42});
In a comment you've said:
the thing is here all are optional, except the first param
That sounds like you probably want the first param and then an options object:
let showNotification = function(firstThing, {a = "default_a", b = "default_b"/*etc.*/} = {}) {
console.log(firstThing, a, b);
};
Upvotes: 1
Reputation: 1075009
Bhushan Babar hasn't posted his suggestion as a an answer, so I'll post it as a community wiki:
You can prepend or append(concat) tokens for respective parameter into your strings , e.g if you want to send parameter which represents parameter d , and string you want to pass is "myString", then you can decide format of your token like $&d&$ , so your parameter will look like "myString$&d&$"
Upvotes: 1
Reputation: 38683
@T,J. Crowder
answer said better than this. In other way, you can do this by using spread Operators. As you said the thing is here all are optional, except the first param
. So you should pass first parameter value. then you don't need to pass other value unless you want.But you should mention the position of parameter value as empty with ,
in an array. In my case you should create an object or array.
For example . If you have a dynamic array with values(whatever but position should be mandatory )and position
[1,,,3]
. then spread operator helps to merge that dynamic array with your function parameters.
let showNotification = function(a,b,c,d,e,f){
console.log(a,b,c,d,e,f);
};
let parts = [2,3,,,6];//Think it is a dynamic array on run time or compile time
showNotification(1,...parts);
And here the @Felix Kling
answers could help by using Named Parameters
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);
};
};
}());
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
More examples:
Pass a value to a specific parameter without caring about the position of the parameter
Passing the argument name while calling function in javascript
JavaScript: Get Argument Value and NAME of Passed Variable
Upvotes: 1