4 Modern JavaScript (ES6+) Features You Should Be Using Now
JavaScript has progressed a lot over the past few years. Whether you are new to JavaScript, or have some experience up your sleeves and want to quickly get up to speed with the most commonly used features in modern JavaScript, this post is for you.
In this post, I’m going to share with you the features I use on a daily basis. These features include:
- Template literals
- Let and Const
- Arrow Functions
- Destructuring
This is not a comprehensive list of all the new features since ECMAScript 2015 (ES6). But these are the 20% of features that you use 80% of the time. Plus, this article is a work in progress. I’ll be adding more features to this list. For now, I want to publish this today!
All these new features are natively supported in all modern browsers. If you want to try out any of the code snippets below, simply open up Chrome Developer Tools and type the code.
So, let’s get started!
Template Literals
Before ES6, we had to deal with these ugly string concatenations:
var name = 'Mosh';
var message = 'Hi ' + name + ',';
Now, with template literals (previously called template strings), we can define a string with placeholders and get rid of all those concatenations:
var name = 'Mosh';
var message = `Hi ${name},`;
Note that I’m using the backtick character here. As funny as it sounds, nobody knew what backticks were until Angular 2 was released! That’s the character before number 1 on your keyboard.
To add a placeholder in a template literal, we use the ${expression} syntax. You can replace “expression” with any JavaScript expressions. Here, we are adding the name variable there. You can also call a function or pass any JavaScript expressions that results in a value.
Another benefit of using template literals is that they can expand multiple lines. They are particularly useful when composing email messages:
var message = `
Hi ${name},
Thank you for joining my mailing list.
Happy coding,
Mosh
`;
Let and Const
Prior to ES6, we used the var keyword to define variables. The scope of a variable defined using the var keyword is the entire enclosing function. Here’s an example:
function doSomething() {
for (var x = 0; x < 5; x++) {
// Technically, x should only be scoped to this block because this is
// where we have defined x.
}
// But it turns out that x is available here as well!
console.log(x); // 5
}
That’s not how most if not all other programming languages behave! Variables defined within a block should be scoped to that block only. In this example, x should not be accessible outside of the for block.
Another issue with the var keyword is that if you use it at the top level outside of a function, it creates a property on the global object:
var x = 1;
console.log(window.x); // 1
ES6 introduced 2 new keywords for resolving these issues: let and const. Both these keywords define variables that are scoped to the containing “block” not “function”:
function doSomething() {
for (let x = 0; x < 5; x++) {
// With the "let" keyword, now x is only accessible in this block.
}
// x is out of the scope here
console.log(x); // x is not defined
}
With const we can define a constant. So we cannot reassign it later:
const x = 1;
x = 2; // throws "Assignment to constant variable."
Also, unlike the var keyword, let and const don’t create a property on the global object if you use them at the top level:
let x = 1;
console.log(window.x); // undefined
So, here is what you should take away:
- Ditch the var keyword. Use only let and const.
- Prefer const to let. Use let only if you need to re-assign the identifier; otherwise, use const to prevent accidentally re-assigning a constant.
Arrow Functions
My favorite feature in ES6! Inspired by lambda expressions in C#, arrow functions give you a clean and concise syntax for writing function expressions. Here’s a function expression in ES5:
const square = function(number) {
return number * number;
}
With arrow functions, we get rid of the function keyword and put a fat arrow (=>) between the parameters and the body of the function:
const square = (number) => {
return number * number;
}
If our function is a one-liner and returns a value, we can drop the return keyword as well as the curly braces:
const square = (number) => number * number;
Isn’t that much cleaner and more concise than the former syntax?
But wait, we can make this even shorter: If our arrow function includes only a single parameter, we can even drop the parenthesis:
const square = number => number * number;
What if our arrow function doesn’t have any parameters? We need to use a pair of parenthesis:
const sayHello = () => { console.log('hello'); };
Arrow functions are particularly useful when you need to pass callback functions as arguments:
// ES5
var activeJobs = jobs.filter(function(job) {
return job.isActive;
});
// ES6
const activeJobs = jobs.filter(job => job.isActive);
Arrow functions, unlike normal functions, don’t rebind this. Does this pattern look familiar to you?
// ES5
function onSubmit() {
// Keep a reference to "this" so we can use it in the inner function below.
var that = this;
orderService.store(order, function(result) {
// In JavaScript, ever function defines its own "this" value. So, "this" in this inner function
// here is different from "this" in the onSubmit() function. That's why we had to keep a
// reference to "this" and store it in "that". Now, we can use "that":
that.result = result;
});
}
Arrow functions, unlike normal functions, don’t rebind this. They use the this value of the enclosing execution context. So, if we replace the inner function above with an arrow function, we don’t need to keep a reference to this anymore.
// ES6
function onSubmit() {
orderService.store(order, result => {
// Since we're using an arrow function here, "this" references the "this" value of the containing function
// (onSubmit). Arrow functions don't re-define "this".
this.result = result;
});
}
Destructuring
Destructuring is an expression that allows us to extract properties from an object, or items from an array. Let’s say we have an address object like this:
const address = {
street: '123 Flinders st',
city: 'Melbourne',
state: 'Victoria'
};
Now, somewhere else we need to access these properties and store their values in a bunch of variables:
const street = address.street;
const city = address.city;
const state = address.state;
We have this repetitive code over and over: “address.” repeated 3 times. Object destructuring gives us a short and clean syntax to extract the value of multiple properties in an object:
const { street, city, state } = address;
That’s it! This code is exactly equivalent to the snippet above. We use curly braces on the left to destructure the address object. Inside the braces, we’re defining 3 variables: street, city, and state. Their values will be extracted from the corresponding properties in the address object.
Note that we don’t have to list all the properties in the address object. Maybe we’re interested only in the street property:
const { street } = address;
Object destructuring is particularly useful when you’re dealing with nested objects:
const person = {
name: 'Mosh',
address: {
billing: {
street: '123 Flinders st',
city: 'Melbourne',
state: 'Victoria'
}
}
};
Without destructuring, we would have to write this ugly and repetitive code:
const street = person.address.billing.street;
const city = person.address.billing.city;
const state = person.address.billing.state;
// So annoying!
Now, we can achieve the same result using a single line of code:
const { street, city, state } = person.address.billing;
We can also destructure arrays but we use square brackets ([]) instead of curly braces ({}). Let’s say we have an array and we want to extra the first and second item and store them in two different variables:
// ES5
const values = ['John', 'Smith'];
const first = values[0];
const last = values[1];
// ugly!
With destructuring, we can re-write the above code like this:
// ES6
const values = ['John', 'Smith'];
const [first, last] = values;
I’m planning to create a comprehensive course on the topic. If you’re interested, join my mailing list to get notified when the course is ready and get it with a discount.
What are your favorite ES6+ features? Use the comment box below and let us know!
If you enjoyed this post, please share it.
Thanks! Short n Sweet.
I believe you have a typo:
The following should be changed
const street = person.address.billing;
const city = person.address.city;
const state = person.address.state;
// So annoying!
To :
const street = person.address.billing.street;
const city = person.address.billing.city;
const state = person.address.billing.state;
// So annoying!
And also,
const { street, city, state } = person.address;
Should be
const { street, city, state } = person.address.billing;
Absolutely! Thank you! I fixed it.
Awesome post, but there’s an error on this example:
const { street, city, state } = person.address;
it would be
const { street, city, state } = person.address.billing;
Yes, yes, that was a typo! You’re the second person mentioning that. I fixed it! Thank you 🙂
const { street, city, state } = person.address; ==> const { street, city, state } = person.address.billing;
Yes, yes, that was a typo! You’re the third person mentioning that. I fixed it! Thank you 🙂
you are hilarious..!! 🙂 😀
Awesome post Mosh! Arrow functions is one my favs too. Your explanation of destructuring was the best I’ve read. I finally get it now.
Yes. There was some typos, but it did not take anything away from the excellent content. I knew exactly what you meant.
Looking forward to your next posts and course.
Tony
Very helpful blog…thanks Mosh
Great post Mosh
spot on.. awesome
Hey Most, i must say that it’s a great explanation !
Sorry for Typo…
Hey Mosh, i must say that it’s a great explanation !
Waaow, Thanks a lot , I learnt new things today.
And hey , I guess there was another typo down there
“…square brackets ([]) instead of curly braces ({}). Let’s say we have an array and we want to extra the first and second item …”. I believe you meant “extract”.
Hi Mosh, just wanna ask is your JS OOP course released? I have subscribed your courses annually and but after I cliked into the JS course, there was nothing shown.
Great Post.
I think you have another typo in the text. Please find below
Let’s say we have an array and we want to extra the first and second item and store them in two different variables
Let’s say we have an array and we want to extract the first and second item and store them in two different variables
If you can notice the difference.
Thanks for these tips!
But if I could make a suggestion: in my version of Firefox, your code snippets appear as white text on a gray background, which makes them a little hard to read.
Very nice explanation. Thanks Mosh.
Hi Mosh, awesome post! Super helpful. One little typo: “Let’s say we have an array and we want to extra the first and second item…” (extra -> extract)
It’s awesome and very excited to Look forward your next course. Thanks!
Hi, Mosh,
Please let me put few questions because it is something strange in the destructuring syntax, so I will try to explain my understanding, using the blocks of code that you presented above.
First of all, you used always *const instead of *let (or *var – which, btw, goes out of discussion because we are in ES6). Which makes me thinking that once put in this way, the object named as a constant is immutable (no property whatsoever can be changed in the future):
const address = {
street: ‘123 Flinders st’,
city: ‘Melbourne’,
state: ‘Victoria’
};
However, in the real world, a programmer would never use a single object as above (because the *address could be as well named *John – or at most *John.address – if there is existing also *Mary.address or *Mosh.address etc.). We group the properties instead of simply assigning 3 certain variables for some *street, *city, or *state of someone single in our library 🙂
Also, you again define the values of the properties (that you collect from that object using *address.street, respectively *address.city or *address.state) as CONST, which is breaking the logic, as time as we already established that *address.city (of John) is immutable. Exactly as when saying the word “century” (which implies the number 100) it is useless to repeat /or to extract/ the digits 1, 0, and again 0, and to claim that they are constants (which obviously they are, from the defitinion of century itself).
If we go further, maybe it is implied that somewhere is visible the use of each separate digit / property, as above / , or at least where the content of their data is stored (which isn’t very obvious). I mean, in the expression below
*const { street, city, state } = address;
it is not very obvious where is the recipient for storing the newly created constant – instead, the expression seem to be like the abstract of a book – where if someone want however to know what is in page 42 must actually read that page 42 not only its title …
In ES5 we have the variables that are declared (so the browser know they exist and what’s their name) and then assigned (so the variables are also “populated” with value[s], either strings, booleans, integers, arrays, etc.)
Same thing appears also in line
*const { street, city, state } = person.address.billing;
which also seems like a compressed form of a table of content of a book – which makes me find difficult to understand how we can expose that compressed content to any specific kind of operations. In Javascript we use very precise operations applied to the strings, for example, when reversing, counting, replacing, split and so on. Maybe I’m wrong, but I can’t find very useful that way of even copying (??) the properties from an object to another by a single line of code as above.
With the array it’s a different story, I see there a lot of uses for such way of writing things 😉 Maybe it’s because I could transform an object in an array, if needed, and apply easier many operations on its elements.
It’s like in some front-end frameworks – where people just beginning to learn them are excited because they can change in browser one or two super simple things with a click, and forgeting the purpose of a website – to change the browser content for each separate user according to what is stored / and happens / in the server for that specific user (which implies that not the aesthetic approach is important but instead the good interaction between the user and the *server, the transport of data in two directions, and most of all, the persistent storage of data after the user ended his interaction with the website/server – or even with other users – so the admin can control and manage the scope of the website or develop it accordingly).
Again, I am in front of learning ES6 so please correct me if I’m wrong 🙂
Thank you !
short, clean and clear. Thank you for sharing.
This is what I call Power Of Simplicity!
Another very useful ES6 feature is Spread syntax . Great for cloning objects, and is very useful in reducers where state is immutable as the code looks very clean, e.g.
`return {…state, active: true}`
Great post great info. Thanks
I always have the motivation and drive to read or take Mosh’ courses and post because of the simplicity of his explanation. I’m an unconditional fan of his and it is benefiting a whole lot, thanks Mosh. Very, simple, clear and concise.
Hi, Mosh, How are you doing, i have been watching your tutorials on YouTube. Actually i really like the way you teach. God bless you my man. Thank you for supporting us. Engr. Rabs from Nigeria.
Thanks Mosh! I love your quick tutorials.
I wanted to be the fourth person to correct your typo. I missed my chance you are too fast! Thanks for the article. JavaScript is better with Mosh.
You cover most of the ES new syntax but I want to add some new feature like asynchrounous iteration, promoise.finally, regular expressions and module things. It will be great if you add these too.
Its awesome. very clean and easily understandable.
Very good expalnations. Thanks for your job, Mosh!
short, clean and clear. Thank you for sharing.