2

Consider the following code:

function foo({
    item1 = 'a',
    item2 = 'b',
    item3 = {x: 1, y: 2}
} = {}) {
    console.log(item1,item2,item3.x,item3.y)
}

If you call foo() you will get an object with the defaults for item1, item2, and item3. You can also call foo({item1: 'm', item2: 'n'}) and your result will include the default item3 of {x: 1, y: 2}. However, if you call:

foo({item1: 'm', item2: 'n', item3: {x: 99}})

you'll get undefined for item3.y in the scope of the function foo.

So:

Is there a way to get individual defaults for the nested properties of item3 in a scenario such as this?

1
  • In exactly the same way that you did define individual defaults for the item1, item2 and item3 properties of your argument object, to which you assigned the default {}. Commented Oct 17, 2019 at 22:33

3 Answers 3

1

This is not possible.

In the parameters, you're trying to extract 3 variables: an item1 object, an item2 object, and an item3 object.

On top of that, you're also trying to mutate the item3 object in case it doesn't contain a certain property.

But all destructuring can do is extract properties from an object into variables - it cannot mutate any existing objects (without some really ugly wacky code that shouldn't be used).

If you're OK extracting the individual properties of item3 into new variables, it would be quite possible, though:

function foo({
  item1 = 'a',
  item2 = 'b',
  item3: {
    x = 1,
    y = 2
  } = {}
} = {}) {
  console.log(item1, item2, x, y)
}


foo({item1: 'm', item2: 'n'})
foo({item1: 'm', item2: 'n', item3: {x: 99}})

Sign up to request clarification or add additional context in comments.

Comments

1

Yes. The solution is to destruct more. From:

function foo({
    item1 = 'a',
    item2 = 'b',
    item3 = {x: 1, y: 2}
} = {}) {
    console.log(item1,item2,item3.x,item3.y)
}

to

function foo({
    item1 = 'a',
    item2 = 'b',
    item3: {x = 1, y = 2} = {},
} = {}) {
    console.log(item1,item2,x,y)
}

Sadly existence of item3 must be removed and only x and y can be used.

The another solution can be only item3 = Object.assign({x: 1, y: 2}, item3) as the first line of foo's body.

Comments

1

There is a hackish way to achieve something very close. You can declare a property that won't appear it the original object (item3ex), and then use the original property (item3) to override the defaults with object spread.

function foo({
  item1 = 'a',
  item2 = 'b',
  item3,
  item3ex = { x: 1, y: 2, ...item3 } 
} = {}) {
  console.log(item1, item2, item3ex)
}

foo({item1: 'm', item2: 'n'})
foo({item1: 'm', item2: 'n', item3: {x: 99}})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.