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.
Marker strings
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.
Variant on Builder
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.
Notes on passing in an object (defaults, destructuring)
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);
};