Search code examples
javascriptecmascript-6babeljsecmascript-2016

Does this JS function param syntax (object initializer with property defaults, similar to rest/spread params) have a name and effect?


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

Solution

  • 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)