2

I would like to create a function that takes one optional property called verbose, and if it's not specified it defaults to true. Here is an example:

function Counter(n=0, {verbose=false}) {
    return function() {
        n++;
        if (verbose) console.log(n);
        return n;
    }
}
let c1 = Counter(0, {verbose: true});
c1(), c1(), c1();

Everything works fine. However, as soon as I call it without the object param, I get an error:

function Counter(n=0, {verbose=false}) {
    return function() {
        n++;
        if (verbose) console.log(n);
        return n;
    }
}
let c1 = Counter(0);
// TypeError: Cannot read property 'verbose' of undefined

Why does this occur, as I thought the whole point of having an object that can be destructured in the argument list is the suggested way to have a bunch of optional arguments that can be called. What am I doing wrong here?

David542
  • 104,438
  • 178
  • 489
  • 842
  • 1
    The problem is that if you don't supply *any* object, it's not defaulting the second parameter to an object. – VLAZ Mar 29 '22 at 17:34
  • @VLAZ so the correct way to call it would be with an empty object? Such as: `let c1 = Counter(0, {});` ? Or what would be the proper way to handle the above? – David542 Mar 29 '22 at 17:35
  • 2
    Does it need to be an object? Could the [default parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters) simply be `verbose=false`? – jarmod Mar 29 '22 at 17:36
  • 3
    `function Counter(n=0, {verbose=false} = {})` you need a default parameter. – VLAZ Mar 29 '22 at 17:36
  • 1
    @jarmod This is probably a simplification and the real application will have multiple options in the object. – Barmar Mar 29 '22 at 17:38
  • @VLAZ That's a better solution than mine, since it doesn't require repeating all the property names. – Barmar Mar 29 '22 at 17:38
  • 1
    @AlexanderNied Why did you delete your answer? It's the best solution. – Barmar Mar 29 '22 at 18:00

1 Answers1

2

Don't put the default in the destructuring pattern, put it in a default value that's assigned to the whole object.

function Counter(n=0, {verbose} = {verbose: false}) {
    console.log(verbose);
    return function() {
        n++;
        if (verbose) console.log(n);
        return n;
    }
}
let c1 = Counter(0);
let c2 = Counter(0, {verbose: true});
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Now it doesn't work if you call `Counter(0, {})`. You *should* put the default in the destructuring pattern. – Bergi Mar 30 '22 at 20:44
  • Somone else posted a solution like that, but for some reason they deleted it. – Barmar Mar 30 '22 at 21:21