Function that takes an object with optional/default properties as a parameter?
Asked Answered
P

3

16

I understand that, using ES6 syntax, a function can be made that takes an object as a parameter and that parameter can have a default value, like so:

function exampleFunction(objParam = {val1: 1, val2: 2}) {
    //...
}

If I call exampleFunction(),objParam is given the default value. However, if I call exampleFunction({val1: 3}), objParam.val2 is undefined. This makes sense, because the default isn't being applied. Is there any way I can make sure that objParam.val2 does have a value, using the ES6 notation? I know I can add checks within the function, but that introduces inconsistency in the code and I'd rather not.

Edit: To clarify, here is a better example:

function exampleFunction(param = 0, objParam = {val1: 1, val2: 2}) {
    return objParam.val1;
}
exampleFunction(); // Returns 1 (this is good)
exampleFunction(1, {val1: 2}); // Returns 2 (this is good)
exampleFunction(1, {val2: 3}); // Returns undefined (I want it to return 1)

And here's what I currently have, which does work but is somewhat inelegant:

function exampleFunction(param = 0, objParam = {val1: 1, val2: 2}) {
    if(objParam.val1 === undefined) objParam.val1 = 1
    if(objParam.val2 === undefined) objParam.val2 = 2
    ...
}
Protonema answered 8/5, 2018 at 15:28 Comment(1)
No, that's not really possible. The default value for a parameter is just that - a default value. It doesn't handle merging properties of objects that are passed in. You should do that yourself using Object.assignBlinny
W
25

You can use destructuring in parameters to provide default values:

function exampleFunction({val1 = 1, val2 = 2} = {}) {
  console.log(val1, val2);
}
exampleFunction({val1: 5});
exampleFunction();

If you want to keep the parameter as an object, you can use Object.assign:

function exampleFunction(origParams = {}) {
  const objParam = Object.assign({ val1: 1, val2: 2 }, origParams);
  console.log(objParam.val1, objParam.val2);
}
exampleFunction({val1: 5});
exampleFunction();
Workshop answered 8/5, 2018 at 15:35 Comment(3)
+1 to @ElAoutarHamza's question, and I'd also like to see a way to keep the parameter as an object if possible. For example, instead of accessing it as val1, access it as param.val1.Protonema
@Protonema After my edit it handles undefined values too. If you want to keep the parameter as an object, you have to use Object.assign or object spread syntax, like in Sam's answer.Nonjuror
This article simonsmith.io/… goes into a but more detail.Zoller
M
10

Probably not as clean as you're looking for, but you can do this instead

function exampleFunction(objParams) {
  const defParams = { val1: 1, val2: 2 };

  const finalParams = { ...defParams, ...objParams }
  // final params takes the default params and overwrites any common properties with incoming params

  // ...
}
Midlothian answered 8/5, 2018 at 15:35 Comment(1)
This works for me and it is cleaner than the accepted answer IMODirty
P
5

No need to use Object.assign, no need to define separate variables.

You can reassign the parameter itself. First, provide the default values, then the object destructuring of the parameter. This will use the default values if not provided via the parameter, and it will keep additional properties that are part of the parameter but not given as a default.

function demo(sizes) {
  sizes = {
    width: 200,
    height: 100,
    ...sizes // this is where the magic (called object destructuring) happens
  }
  console.log(sizes)
}

demo({width: 400, depth: 20})  // Prints "Object { width: 400, height: 100, depth: 20 }"

Alternatively, you can put the defaults in a separate object:

const DEFAULT_SIZES = {
    width: 200,
    height: 100
}

function demo(sizes) {
  sizes = {
    ...DEFAULT_SIZES
    ...sizes
  }
  console.log(sizes)
}

demo({width: 400, depth: 20})  // Prints "Object { width: 400, height: 100, depth: 20 }"
Precatory answered 8/10, 2022 at 18:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.