ES6 of the Week

This Week's Episode:

rest, spread, and function defaults

Writing Readable Code

  • A goal for all developers!
  • We like to be able to tell what a function does at a glance, without having to read through all of the logic
  • Naming things effectively is kind of our main tool here
  • ES6 offers some language features that also help

Parameter defaults

  • With ES6, you can default values for function parameters more easily 
  • Replaces the need make default values a part of your function logic, which makes your function declarations more...well, declarative

Defaults

// the old way
function foo (a, b) {
    b = b || 'bar';
    return a + b;
}


// the ES6 way!
function foo (a, b='bar') {
    return a + b
}

foo('baz')             // => 'bazbar'
foo('baz', 'quux')    // => 'bazquuz'

Rest Parameter

  • ES6 also introduces the the spread operator: ...
  • If you use the spread operator with a parameter in a function declaration, it will aggregate the remaining arguments (the rest of the arguments) into that parameter within the function's scope
    • Very useful for describing variadic functions
    • Replaces the need to use the 'arguments' object
    • Necessary for variadic function expressions declared using arrow functions

Rest parameter

function foo (a, ...args) {
    // much easier and more descriptive than Array.prototype.slice.call!
    args.forEach(arg => {
        console.log(a + arg);
    });
}

foo(1, 2)        // => 3
foo(1, 2, 3)    // => 3 4


// maybe more realistic example
function createMiddleware (...middlewares) {

  return function (action) {
    middlewares.forEach(middleware => middleware(action));
  };
}

Using the Spread Operator

  • You can also use the spread operator with arrays and strings
  • With arrays, the spread operator can flatten the array's components into another array (similar to Array.prototype.concat), or into the individual parameters of a function (similar to using Function.prototype.apply)
  • With strings, applying the spread operator to a string within an array will have the same effect as using String.prototype.split

Spreading the love

// cleaner than Function.prototype.apply
function foo (a, b, c) {
    console.log(a);
    console.log(b);
    console.log(c);
}

let arr = [1, 2, 3];
foo(...arr); // same as foo.apply(foo, arr);

// declaratively flatten arrays
let numbers = [1, 2, 3];
let letters = ['a', 'b', 'c'];
let both = [...numbers, ...letters];
console.log(both); // => [ 1, 2, 3, 'a', 'b', 'c' ]


// for strings, the spread operator is an alternative to String.prototype.split
let string = "Hello";
console.log([...string]); // => [ 'H', 'e', 'l', 'l', 'o' ]

Don't get confused!


// here we're using ... in a function definition - so this is the rest parameter
function createMiddleware (...middlewares) {

  // this is also a function definition - rest parameter
  return function (...args) {

    // now we're using it with a function invocation - this is the same as 
    // middleware.apply(null, args)
    middlewares.forEach(middleware => middleware(...args));
  };
}

Why use the spread operator?

  • Intuitive and descriptive for writing variadic functions
  • Can be a clean replacement for some cumbersome boilerplate, like Array.prototype.slice.call(arguments) with and Function.prototype.apply
  • Can be a less verbose alternative to Array.prototype.concat if you have multiple arrays that you want to flatten into one 

Resources

  • ES6: http://es6-features.org/
  • Mozilla docs:
    • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

ES6 of the Week - 3

By Tom Kelly

ES6 of the Week - 3

Rest and Spread

  • 1,317