ES6 need to know
ES6 is out, browser support is actually decent and if that is not enough for you there is always Babel. So lets get up to speed with the most important and awesome new features.
Let there be Const
Scope in JavaScript come unfamiliar to most. Because we have a thing called "variable hosting" that pulls all variables out and defines them at the top of their Scope. Their Scope being either the global one or the first surrounding function. The classic example here is a for loop.
function foo() {
for(var i = 0; i < 10; i++) {
console.log(i) // 0 1 2 3 4 5 6 7 8 9
}
console.log(i) //10
}
That is because what actually happens is that var i
get hoisted to its Scope.
function foo() {
var i
for(i = 0; i < 10; i++) {
console.log(i) // 0 1 2 3 4 5 6 7 8 9
}
console.log(i) //10
}
Knowing this it makes perfect sense. But now we get awesome new keyword that are actually scoped to their surrounding Blocks.
let is effectively the new var. It is only present within the corresponding Block.
function foo() {
for(let i = 0; i < 9; i++) {
console.log(i) // 0 1 2 3 4 5 6 7 8 9
}
console.log(i) //undefined
}
const defines a constant. That is it can not be re-assigned. And can therefore also not be used in a for loop where the iterator variable gets constantly updated. If you define a constant that is an Object you can alter and define its properties but not re-assign the variable to be something else.
const obj = {
name: 'HoverBaum'
}
obj.name = 'Tester' //works
obj.awesome = true //also okay
obj = [] //NOPE, this is an error
Arrow Functions
Do you remember the good old function
keyword?
function foo() {
return 'bar'
}
Well the cools kids found a way to do this with way less code. Really nice for people writing blogs and holding presentations. We can cramp more logic into less space using syntax that confuses our readers.
//ES6 equivalent
const foo = () => {
return 'bar'
}
//And even shorter because returns are implied
const foo = () => 'bar'
But they come in really handy when you need to pass a function to something. Like mapping over an array. And with functional programming (whatever that is) being all ther age right now you will see people doing this more and more.
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const doubled = arr.map(number => {return number * 2})
// [2, 4, 6, 8, 10, 12, 14, 15, 19, 20]
//And again all the sugar to leave out things.
const awesomeDouble = arr.map(number => number * 2)
// [2, 4, 6, 8, 10, 12, 14, 15, 19, 20]
//That implicit return even works for Objects.
const wrapped = arra.map(number => ({num: number}))
//[{num: 1}, {num: 2}, {num: 3}, {num: 4}, ...]
Did you notice how you have to wrap the Objects in ()
to get them to work with implicit returns? very consistent code we are writing here. So you might wanna keep a { return 'bar' }
pattern just to make your code consistent and not confuse yourself. Because trust me that will confuse you. And lets not have the argument about less code vs. people including the writer can read it read it easily because I am in favor of the later and this is my blog.
Did I mention that Arrow Functions also keep the current Scope? So this
inside an Arrow Function will be the same as outside of it. Just a thing to keep in mind.
Destructuring
We can now get Objects out of other. Mainly we use this for imports and exports (coming up next, only in this blogpost) but you could also use it on Objects or to get named parameters for functions.
let {a, b} = {
a: 1,
b: 2
}
console.log(a) // 1
function foo ({greeting, name}) {
console.log(greeting + ' ' + name)
}
foo({name: 'HoverBaum', greeting: 'Hello'})
Modules
Victory dance here with big celebration! We finally get native modules. Now if only we could all use them and they were compatible with node. But they are super awesome. We can now import
things from modules that exported
them.
//app.js
//import the default export fro logger
import log from './logger'
//only import a from letters
import { a } from './letters'
log(a) // 1
// ****
//logger.js
export default const log = (msg) => {
console.log(msg)
}
// ****
//letters.js
export const a = 1
export const b = 2
Template String
This is another "OHHH my god why didn't we have this before???!?". Because we all remember building String with variables in them. now we can do it using "`" and ${}
.
function greet(greeting, name) {
console.log(`${greeting} ${name}, nice to see you.`)
}
If this does not seriously excite you... then go back and build a few dozen websites without it!
Default Parameters
Read the first sentence from the last paragraph again ^^
With Default Paramters we can easily define what a Parameter should be if not supplied.
//Old way
function greet(greeting, name) {
if (!greeting) {
greeting = 'Hello'
}
if (!name) {
name = 'Friend'
}
console.log(`${greeting} ${name}.`)
}
//ES6 Default Paramteres
function greeti(greeting = 'Hello', name = 'Friend') {
console.log(`${greeting} ${name}.`)
}
We saved a total of six lines of code! Is that not amazing?
Object.assign
If you read my React post you will have already seen this a lot. Using Object.assign
allows us to create a new Object and pass in other Objects. What? Examples:
const obj = {
a: 1,
b: 2,
}
const newObj = Object.assign({}, obj, {
b: 13,
})
/*
newObj == {
a: 1,
b: 13
}
*/
The important thing here is that we create an entirely new Object. You call the function like such Object.assign(target, ...sources)
handing it an Object and then Objects whoes values should be merged into that.
This is useful to create immutable data stores where you want to not modify your stored data or state but create a new one. Thus enabling you to remember the old one and jump back to it.
Property shorthands
Yet another feature to save lines of code and possibly confuse people are Property Shorthands. If you want to pass name
into and object as that objects object.name
property you can just put it there.
const name = 'HoverBaum'
//old
const nameObj = {
name: name,
}
//ES6
const es6Obj = {
name,
}
Further reading
Here are a few links to good references and further reading.