You are on page 1of 24

ITNEXT

Modern JavaScript, 10 things you


should be using, starting today
#javascript #beginners #showdev #tutorial

Chris Noring 3 juil. 2019 Updated on Oct 01, 2019 ・7 min read

Follow me on Twitter, happy to take your suggestions on topics or


improvements /Chris
You may be completely new to JavaScript or you may have only
used it sporadically over the years. One thing is clear though - a lot
has changed and there are some features YOU should be using.
This article describes the features I think you should be using on a
daily basis,
200
if you are serious40about JavaScript 302
Here is the video version:

Learn modern JavaScript from es6-es8 - Great features I thi…


thi…

Resources
These are my favorite resources for anything ES6+:
ES6 Features
MDN

-1- Spread operator


This is denoted as a ... before an object or an array and accomplishes
just what the name is saying, it's turning something from being a
structure into a comma-separated list. Let's demonstrate this:
Spread array

let firstHalf = [ 'one', 'two'];


let secondHalf
200 = ['three', 'four',
40 ...firstHalf];
302
This is such a nice and compact way of writing it. Doing the same
without this would mean doing something like this:
NO Array spread

let firstHalf = [ 'one', 'two'];

let secondHalf = ['three', 'four'];


for(var i=0, i <firstHalf.length; i++ ) {
secondHalf.push(firstHalf[i]);
}

This can also be used on objects as a way of merging their properties:


Spread object

const hero = {
name: 'Xena - Warrior Princess',
realName: 'Lucy Lawless'
}

const heroWithSword = {
...hero,
weapon: 'sword'
}

Doing this the hard way would be us looping through all the properties
on the object:
NO Object spread

let keys =200


Object.keys(hero);40 302
let obj = {};
for(var i=0; i< keys.length; i++) {
obj[keys[i]] = keys[props[i]];
}

-2- Rest parameter


Rest parameters are about collecting the remaining parameters into an
array. JavaScript has the ability to be flexible on the number of input
parameters you give it. Normally there is an arguments variable that
collects these. Let's look at what we mean:

function add(first, second, ...remaining) {


return first + second;
}

Now, this above only summarize the parameters first and second .
Which means invoking it with add(1,2) or add(1,2,3, 4) would yield
the same results. To fix this we would type:

function add(first, second, ...remaining) {


return first + second + remaining.reduce((acc, curr) => acc + curr, 0
}

The above means we are fixing the problem and use all input
parameters.
As stated earlier using the rest parameter, i.e adding a preceding ...
as a way to collect the remaining parameters, is a way for us to name
them and make it more explicit that we want to work with them.
arguments have been around since at least ES5 but is less known I think.

-3- String
200
interpolation
40 302
Have you ever seen a statement like this?

class Product {
constructor(name, description, price) {
this.name = name;
this.description = description;
this.price = price;
}

getDescription() {
return " Full description \n" +
" name: " + this.name +
" description: " + this.description

}
}

I'm of course talking about the getDescription() method, a long,


multiline, hard-to-read statement. This is a reality in most
programming languages. There is also string interpolation available in
some languages and JavaScript is no different, fortunately. We can turn
our getDescription() method into the following:

getDescription() {
return `Full description \n:
name: ${this.name}
description ${this.description}
`;

So double backticks ` is what we use to define a multi-line string. We


also use ${} to interpolate. There your world is hopefully a lot better
now :)
200 40 302
-4- Shorthand properties
You might be using this one without already knowing about it. In ES5
you had to write the following:

function createCoord(x, y) {
return {
x: x,
y: y
}
}

In ES6 and onwards you can omit the what's to the right of : if it has
the same name, like so:

function createCoord(x, y) {
return {
x,
y
}
}

Looks less cluttered right?

-5- Method properties


This is how you define properties that point to methods in an object.
Consider the following ES5 example:

const math = {
add: function(a,b) { return a + b; },
sub: function(a,b) { return a - b; },
multiply: function(a,b) { return a * b; }
}
200 40 302
You don't actually need to have the whole add: business from ES6 and
forwards. You can just type it like so:

const math = {
add(a,b) { return a + b; },
sub(a,b) { return a - b; },
multiply(a,b) { return a * b; }
}

-6- Destructuring
Destructuring is about your own mental sanity as a developer.
Object destructuring
Consider the following code:

function handle(req, res) {


const name = req.body.name;
const description = req.body.description;
const url = req.url;

log('url endpoint', url);

// lots of logic happening


dbService.createPerson( name, description )
}

The code above is not perfect, in any way, but it does represent a case
where we want to dig out data from an object at different levels.
What's the problem you ask? Well, what if I didn't have to declare all
those variables and save a few keystrokes? You can do just that:

function handle(req, res) {


const { body: { name, description }, url }, = req;
200 40 302
log('url endpoint', url);

// lots of logic happening


dbService.createPerson( name, description )

Above you see how three rows become one.


Array destructuring
This is not limited to objects. It can be done on arrays as well. Consider
the following code:

const array = [1,2,3,4,5,6];

const a = array[0];

const c = array[2];

This can be done in a much more elegant way, like so:

const array = [1,2,3,4,5,6];


const [a, ,c, ...remaining] = arr;

// remaining = [4,5,6]

We can just break out the values from the array by the above pattern
matching. If we want to skip something we type , , and as a bonus, I
threw in a REST statement to grab the remaining items.
Parameter matching
We can also do this on a function and its parameters. It has become the
de-facto standard to collect all parameters in an object when you have
more than 2-3 parameters in a function so you get a function looking
like this:
200 40 302
function doSomething(config) {
if(config.a) { ... }
if(config.b) { ... }
if(config.c) { ... }
}

The better way to do this is:

function doSomething({ a, b, c }) {
if(a) { ... }
if(b) { ... }
if(c) { ... }
}

-7- Array methods


ES6 brought a whole slew of usable array methods like:
find() , finds an item in list else null
findIndex() , find the index of the item
some() , is the predicate true for at least one item in the list
includes() , is an item part of a list
Consider the following code to understand the usage:

const array = [{ id: 1, checked: true }, { id: 2 }];


arr.find(item => item.id === 2) // { id: 2 }
arr.findIndex(item => item.id === 2) // 1
arr.some(item => item.checked) // true

const numberArray = [1,2,3,4];


numberArray.includes(2) // true

-8- Promises
200
+ Async/Await
40 302
If you have been around the block a while you might remember a time
when callbacks were all we had, like this:

function doSomething(cb) {
setTimeout(() => {
cb('done')
}, 3000)
}

doSomething((arg) => {
console.log('done here', arg);
})

We used this to handle the fact that some operations were


asynchronous and simply took time to finish. Then we got promise
libraries that people started using and eventually, we got native
support in the language. So now we can do things like:

function doSomething() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('done')
}, 3000)
})
}

doSomething().then(arg => {
console.log('done here', arg);
})

We can even chain the whole experience so we can do calls like this:

getUser()
.then(getOrderByUser)
.then(getOrderItemsByOrder)
200
.then(orderItems => { 40 302
// do something with order items
})

Async/await
Then we got async/await and life became even more glorious. Consider
the above example with Promises now becoming this:

async function getItems() {


try {
const user = await getUser();
const order = await getOrderByUser(user);
const items = await getOrderItemsByOrder(order);
return items;
} catch(err) {
// handle error here, the suggestion to return something or rethrow
}
}

getItems().then(items => {
// do something with order items
})

We get a synchronous-looking asynchronous code. :)

 -9- Modules
Pretty much any coding language supports the concept of modules.
The ability to divide up your code in many different files, files that are
also self-contained units, so-called modules. Consider the following
code:

// math.js
200 40 302
export function add(a,b) { return a + b; }
export function sub(a,b) { return a - b; }

export default (a,b) => a * b;

// main.js
import mult, { add, sub } from './math';

mult(2, 4) // 8
add(1,1) // 2
sub(1,2) // -1

Above we are using the export keyword to signal that these constructs
addand sub is publically available for any module importing this
module. The export default keyword is what we get if we just import it.
In main.js we import the default as having name mult and we also
specifically pick out methods add() and sub()

-10- Arrow functions + Lexical this


I've been using Arrow functions throughout this article and it's simply
another function notation. In the past we could only write functions like
this:

function printArray(arr) {
// do something
}

Now we can define that as:

const printArray = (arr) => {


// do something
}
200 40 302
One line functions
We can also define functions as one-liners:

const add = (a,b) => a + b

This automatically means we do the operation and return the result. We


can do the same and return an object, our syntax then becomes:

const create = (a,b) = > ({ x: a, y: b })

Lexical this
The problem we used to face was no knowing what this is. Consider
the following problem:

let array = [1,2,3];

function sum() {
this.total = 0;

arr.forEach(function(item) {
this.total+= item; // `this` is the inner functions `this`, BAD
})
return total;
}

this in the above case points wrong inside of the forEach . The way we
used to solve this was by doing:

function sum() {
this.total = 0;
var self = this;

arr.forEach(function(item) {
self.total+= item; // now we are using `self`, it solves it but fe
}) 200 40 302
return total;
}

Arrow functions fix this, no more self , so now the code looks like this:

function sum() {
this.total = 0;

arr.forEach((item) => {
this.total+= item; // all is well `this` points to outer function
})
return total;
}

WINNING!

Summary
There are more things I could mention about ES6 and forward but I just
wanted to show you my favorites that I think you should adopt today :)

Posted on 3 juil. 2019 by:

Chris Noring
@softchris
https://twitter.com/chris_noring Cloud Developer Advocate at
Microsoft, Google Developer Expert

Follow

ITNEXT
200 40 302
ITNEXT is a platform for software developers, engineers, IT architects,
system engineers and IT enthousiasts to share knowledge, connect
and connect.

Discussion Subscribe

Add to the discussion

Jul 3 '19
Seanmclem

My problem with async await is it seems to reduce options for error


handling. Any way to mitigate that?

3 Reply

 
Jul 3 '19
Chris Noring

hi. Yes you can have a try/catch inside of your async function, you can
also have an error callback on the promise that invoking the async
method will result in. I'll update the example, appreciate you raising
this issue :)

3 Reply

 
200 40 302
Jul 3 '19
Seanmclem

Thanks. I'd love to see how handling async/await errors can be done
in a way that isn't just as complicated as then/catch

2 Thread

Jul 4 '19
Nathan Tamez

you can do

shop.getFreeKittens().then(kittens=>console.log(kittens), err=>{
// do your thing
console.error(err);
});

2
Thread

Jul 4 '19
Chris Noring

yes, definitely that too. In my example that would be a catch-all


handler. question I think was how to handle per call . So in
promises it would be:

getUser()
.then(getOrderByUser, errorHandler)
.then(getOrderItemsByOrder, errorHandler)

The above scenario is what I think we are discussing.

For an error handling approach for async/await, we could do this:

async function get() {


let user, order;
try {
200 40 302
user = await getUser();
} catch(err) {}

try {
order = await getOrderByUser(user);
} catch(err) {

}
...
}

get()
.then(successHandler, errorHandler)

2
Thread

Jul 4 '19
Nathan Tamez

I get the feeling that people can feel a bit intimidated when they
first see a longer promise chain. this is were I believe async/await
come in to their own, When used properly async functions can
look pretty simple and straight forward. I still prefer promise style
functions for most async tasks tho. Especially task like my example
above.

1
Reply

 
Jul 4 '19
Seanmclem

Can you return the items variable from outside the try{} block? Or
would it be scoped inside the try block.

2 Thread

Jul 4 '19
200Nathan Tamez 40 302
Yes you can, but if you return any value from a async function, the
the promise that function returns will resolve, successfully.even if in
the catch block of a try/catch block. This behavior can be vary
useful. If you want the promise to throw an error you need to call

throw expression

1
Thread

Jul 4 '19
Seanmclem

Okay, are you saying that a try catch block is not even necessary?
Because the results of the error will get shoved into whatever is
returned by the async function either way?

1
Reply

 
Jul 4 '19
Charlie Fuentes

When you work with async/await you have the option to use catch as
well.

For example:

await someAsync().catch(console.error);

1 Reply

 
Jul 4 '19
Ankur Loriya

Use try catch


200 40 302
try {
await UserService.create(name, email);
} catch(error) {
// Handle error
}

1 Reply

Jul 4 '19
Fredrik Fall

Nice rundown of our new ES6 sugar :)


On the array remainder example I'm guessing there is a little typo:

const array = [1,2,3,4,5,6];


const [a, ,c, ...remaining];

I'm guessing should be

const array = [1,2,3,4,5,6];


const [a, ,c, ...remaining] = array;

Tack och hej :)

3 Reply

Jul 4 '19
guico33

export default (a,b) => return a *b;

You'd need curly braces to be able to use return here, or just get rid of it.

const math = {
add(a,b) => a + b
200 40 302
sub(a,b) => a - b
multiply(a,b) => a *b
}

This syntax isn't valid. You cannot use arrow functions with the shorthand
notation.

2 Reply

 
Jul 5 '19
Chris Noring

Thanks, should be updated

2 Reply

Aug 2 '19
Jang Rush

Hi, I'd like to translate this nice article to Chinese. Can you give me the
permission? The translated text will be published at nextfe.com and there
will be backlink to this original post at the beginning. Thanks.

1 Reply

 
Aug 2 '19
Chris Noring

hi Jang sure. Please post here with a link to the chinese version once
done, thanks :)

2 Reply

 
200 40 302
Aug 19 '19
Jang Rush

Translated text has been published: nextfe.com/morden-js/

2 Reply

Jul 3 '19
Pedro Filho

Hey, there's a typo on the first example of destructuring, I think you


meant:

const name = req.body.name

Btw, nice article!!!

3 Reply

 
Jul 3 '19
Chris Noring

Thanks Pedro :)

1 Reply

Jul 4 '19
Vaibhav Namburi

Clean and to the point! Good work mate!

3 Reply

  200 40 302
Jul 3 '19
Mario

Very nice article, thank you. In 10. Arrow functions, the first example for
printArray : can you really omit the parameter arr ?

1 Reply

 
Jul 3 '19
Chris Noring

hi Mario, no that's my mistake, I'll fix it, thanks :)

2 Reply

Jul 3 '19
Mike S

Two typos I found randomly:

Section 8: So know we can do things...

Section 9: this is publically available

1 Reply

 
Jul 3 '19
Chris Noring

actually publically and publicly is too correct spellings.. appreciate you


pointing it out Mike :)

1 Reply
200 40 302
 
Jul 4 '19
Yuhi Jackman

This is very useful and a great refresher on ES6. I really like this post!

2 Reply

Jul 4 '19
Charlie Fuentes

I think this features should be mandatory in any JavaScript project. With


the exception of some projects in Node.js where there's no ES6 modules.

1 Reply

 
Jul 4 '19
Chris Noring

agree.. they make the code smaller, more efficient, readable.. Hopefully,
more people will use these features seeing this article. That was the
goal :)

2 Reply

 
Jul 4 '19
Charlie Fuentes

Totally agree. Great article, I know will help a lot of people :)

1 Reply

Code of Conduct • Report abuse

200 40 302
More from ITNEXT

How to display a gazillion of metrics and keep your sanity


#javascript #typescript #webdev

Type checking your JavaScript with VS Code - the superpowers you didn't know
you had
#javascript #webdev #tutorial #productivity

5 things that might surprise a JavaScript beginner/ OO Developer


#tutorial #webdev #javascript #beginners

200 40 302

You might also like