1

I was reading the logging library source code when I found syntax I had never seen before, and which didn't seem to have any effect when evaluated via an interpreter:

const createLogger = (title,
                     {
                         debugFunction = createDebug(title),
                         logFunction = console.log
                     } = {}) => { /* ... */ }
  1. What is this syntax called?
  2. What effect does this syntax have?
  3. Can the object be referenced from within the function body?

Output of ts-node attempt to recreate:

> const testFn2 = (arg1, {dFn = console.debug, lFn = console.log} = {}) => { console.log(arguments) }
undefined

> testFn2(1)
{ '0': 1 }
undefined

> testFn2(1, 2)
{ '0': 1, '1': 2 }
undefined

> testFn2(1, {})
{ '0': 1, '1': {} }
undefined
Michael Ward
  • 496
  • 5
  • 13
  • 1
    It is the [destructuring syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment). – Hassan Imam Jan 15 '18 at 06:27

3 Answers3

1

It's a combination of

along with

...all of which were added in ES2015.

It creates a constant, createLogger, and sets its value to a function named createLogger, which accepts two parameters: A title (title), and an object. The object is destructured into debugFunction and logFunction parameters, and is defaulted to {} if not present.

Here's a simpler example of a destructured parameter:

function foo({a, b}) {
// Note -----^----^
  console.log(a, ",", b);
}

const o = {a: 1, b: 2};
foo(o); // 1 , 2

Note how we're calling foo with an object, but foo's code works with two parameters whose values were destructured from that object's properties.

If we were to call foo with no argument, we'd get an error because the destructuring tries to access the properties on the parameter, and accessing properties on undefined fails:

function foo({a, b}) {
  console.log(a, ",", b);
}

foo(); // Fails

If we add in a default value for the parameter, it works:

function foo({a, b} = {a: "default a"}) {
// ----------------^^^^^^^^^^^^^^^^^^^
  console.log(a, ",", b);
}

foo(); // default a , undefined (since there's no `b` in the default)
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

It is called argument destructuring coupled with default values:

let default1 = 1;
let default2 = 2;

const func = ({a = default1, b = default2} = {}) => {
  console.log(a);
  console.log(b);
}

// Here since no value is specified, the default argument will be {a: 1, b: 2}
func();
klugjo
  • 19,422
  • 8
  • 57
  • 75
0

You are looking at an object destructring assignment, in this case used to initialize local variables and assign them default values without having to declare them in the function body. It's a pattern to avoid writing extra code; if you didn't have the destructing syntax, you would basically write:

const createLogger = (name, params = {}) => {
    let debugFunction = params.debugFunction || createDebug(name);
    let logFunction = params.logFunction || console.log;

     // do stuff
}

At this point it may create more problems than is worth it for small amount of code it eliminates; better to be clear than concise, especially on a large project. You could combine multiple ternary assignments instead of writing an if-else block, but that would be terrible to read. On the other hand, this style may gain more prevalence.

Greg Rozmarynowycz
  • 2,037
  • 17
  • 20