Two of the most important parts of JavaScript, Objects and Promises, have new features in ES2018. Let’s see how they work.
In January, the TC39 met and decided which proposals would reach stage 4 and therefore be included in ECMAScript 2018.
This post is part of a series where we cover those new features.
Part 1: RegExp Improvements
Part 2: Rest/Spread Object and Promise.finally
Part 3: Async Iteration
If you’re interested in seeing all current proposals and their stages, you can check them out here.
Rest Object
Since ES6, we’ve had the ability to use the rest operator with Arrays. Starting with ES2018, we can also use it with object literals.
The rest operator lets us assign the properties of an object to variables, and any properties we don’t explicitly assign (the rest) get grouped into a new object.
Keep in mind that this works with enumerable properties, and the rest operator will capture the properties that haven’t been named before it.
const colors = {
red: '...',
green: '...',
blue: '...',
black: '...',
white: '...'
}
const { red, green, blue, ...rest} = colors
console.log(rest) // {black: '', white: ''}
The main restriction to keep in mind is that the rest operator must go at the end of the declaration.
const { ...rest, red, green } = colors // error
Spread Object
This is a great feature (maybe my favorite). It lets you copy the values of one object into another. Before ES2018, you were probably using Object.assign to achieve the same result.
const colors = {
red: '...',
blue: '...'
}
const newColors = {...colors}
console.log(newColors) // {red: '...', blue: '...'}
Something important to keep in mind is that the Spread operator creates a shallow copy of the object. This means that if the object has nested objects, they’ll still share the same reference.
const colors = {
red: {
light: '...',
dark: '...'
},
blue: '...'
}
const newColors = {...colors}
newColors.red.ligth = 'rosa'
console.log(colors.red.ligth) // 'rosa'
Another very handy use case is merging multiple objects into a new one. Just remember that if they have properties with the same name, the result will depend on the order you use them.
const colorfull = {
red: '',
green: '',
white: '',
}
const blackAndWhite = {
black: '',
white: ''
}
const colors = { ...colorfull, ...blackAndWhite }
In this case, the white property from blackAndWhite will be the one used in the new object.
The third most common use case is having default values.
const DEFAULTS = {
user: 'lala',
age: 18,
}
const juan = { ...DEFAULTS, user: 'juan' }
console.log(juan) // {user: 'juan', age: 18}
The spread operator is incredible and lets you do really useful things with objects. There are a couple of implementation details I’d like to mention:
- All created objects will be linked to
Object.prototype - Property getters are used to obtain values from the source objects
- Only values are used to define properties on the new object, not setters
- The spread operator does not copy the attributes of each object property
Promise.finally
When executing a promise, we can assign callbacks that run when the promise is fulfilled with .then or rejected with .catch. Now, .finally gives us the ability to run another callback regardless of whether it completed or not.
Imagine you’re making a request and you need to use a loading state while the query happens. Before, you’d have to set the new state in both .then and .catch. Now with finally, you just do it in one place.
The finally callback will run regardless of whether the promise had an error.
this.setState({loading: true})
fetch('...')
.then(response => response.json())
.then(data => this.setState({data}))
.catch(e => this.setState({error: true, message: e}))
.finally(() => this.setState({loading: false}))
Its functionality is basically the same as the finally used in synchronous code.
Final Thoughts
These are the features you’ll probably use most frequently in your day-to-day work, for a ton of different things and situations. It’s important that you learn them well. If you have any questions, don’t hesitate to reach out.
In the next post, we’ll talk about async iteration.