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,411