You can pass all your optional arguments in an object as the first argument. The second argument is your callback. Now you can accept as many arguments as you want in your first argument object, and make it optional like so:
function my_func(op, cb) {
var options = (typeof arguments[0] !== "function")? arguments[0] : {},
callback = (typeof arguments[0] !== "function")? arguments[1] : arguments[0];
console.log(options);
console.log(callback);
}
If you call it without passing the options argument, it will default to an empty object:
my_func(function () {});
=> options: {}
=> callback: function() {}
If you call it with the options argument you get all your params:
my_func({param1: 'param1', param2: 'param2'}, function () {});
=> options: {param1: "param1", param2: "param2"}
=> callback: function() {}
This could obviously be tweaked to work with more arguments than two, but it get's more confusing. If you can just use an object as your first argument then you can pass an unlimited amount of arguments using that object. If you absolutely need more optional arguments (e.g. my_func(arg1, arg2, arg3, ..., arg10, fn)), then I would suggest using a library like ArgueJS. I have not personally used it, but it looks promising.