I am trying to figure out if it is possible to handle multiple levels of default parameters with destructuring. Since it is not easy to explain with words, here is a step-by-step example...
1 - Flat object destructuring with default parameters
Destructuring this object is easy:
let obj = {
foo: 'Foo',
bar: 'Bar'
};
With {foo = 'Foo', bar = 'Bar'} = {}
in a function signature, an object will be created if there is no argument passed when the function is called. If an object is passed but some referenced properties are undefined
, they will be replaced by their default values. This code works fine:
function fn1({foo = 'Foo', bar = 'Bar'} = {}) {
console.log(foo, bar);
}
// OK
fn1(); // Foo Bar
fn1({foo: 'Quux'}); // Quux Bar
fn1({bar: 'Quux'}); // Foo Quux
fn1({foo: 'Quux', bar: 'Quux'}); // Quux Quux
2 - Nested object destructuring with shallow default parameters
Destructuring this object is harder:
let obj = {
foo: 'Foo',
bar: {
quux: 'Quux',
corge: 'Corge'
}
};
{foo = 'Foo', bar = 'Bar'} = {}
is not a viable option anymore, but now we can use {foo = 'Foo', bar = {quux: 'Quux', corge: 'Corge'}} = {}
in a function signature. Again, if no argument is given when the function is called, an object is created and the core properties (foo
and bar
) are extracted. If an object is passed, only undefined properties (foo
or bar
) will be destructured with their default values.
The problem is that the object properties of bar
(quux
and corge
) are not part of the "top-level destructuring". This means quux
or corge
will be undefined
if they are not explicitly set when bar
is passed as an argument:
function fn2({foo = 'Foo', bar = {quux: 'Quux', corge: 'Corge'}} = {}) {
console.log(foo, bar.quux, bar.corge);
}
// OK
fn2(); // Foo Quux Corge
fn2({foo: 'Quux'}); // Quux Quux Corge
// Oops!
fn2({bar: {quux: 'Baz'}}); // Foo Baz undefined
fn2({foo: 'Quux', bar: {corge: 'Baz'}}); // Quux undefined Baz
3 - Nested object destructuring with deep default parameters
I would like to set default parameters at all levels of the object hierarchy to use a sort of "cascading destructuring". I tried this, but it does not work:
function fn3({foo = 'Foo', bar = ({quux = 'Quux', corge = 'Corge'} = {})} = {}) {
console.log(foo, bar.quux, bar.corge);
}
// Oops!
fn3(); // Foo undefined undefined
fn3({foo: 'Quux'}); // Quux undefined undefined
fn3({bar: {quux: 'Baz'}}); // Foo Baz undefined
fn3({foo: 'Quux', bar: {corge: 'Baz'}}); // Quux undefined Baz
Do you know if such a feature is allowed in ES6. If yes, how can I implement it?