Answer by @Badacadabra is nearly correct but missing the other top level parameter specified in the question.
function f({a = 1, callback: {name = "qwe", params = "123"} = {}} = {}) {
console.log(a);
console.log(name);
console.log(params);
}
However note that within the function body the properties of callback
are addressed without the containing object. You could reconstitute them into such an object if you wanted with the line:
const callback = { name, params }
Either way, from the invocation point this works to fill in all missing values from all levels such as:
f({a: 2})
f({a: 2, callback: { name: "abc"}})
f({a: 2, callback: { params: "456" }})
etc.
EDIT
In response to Joakim's comment:
TotalAMD also said in a comment that "I want to use several nested objects with same fields name". So if he tries that approach with callback1 and callback2 as arguments then he would have to use different field names in them.
I missed that original requirement. One way to maintain the desired, duplicated nested names within the function interface would be to alias them within the scope of the function, as follows:
function f({
a = 1,
callback1: {name: name1 = "abc", params: params1 = "123"} = {},
callback2: {name: name2 = "def", params: params2 = "456"} = {},
} = {}) {
console.log(a);
console.log(name1);
console.log(params1);
console.log(name2);
console.log(params2);
}
You can then call the function with the designed interface and expected results:
f ({ callback1: { name: "One" }, callback2: { name: "Two" } })
Caveat: Whilst technically possible and potentially useful, this could get messy at deeper nesting levels. It might then be worth looking for an alternative interface design with less indirection.