ES6 JavaScript

The less weird parts

A couple of months ago I wrote about “JavaScript — The weird parts”. It was very well received and I thank everybody who recommended, shared and commented. In this short follow-up I’d like to go over some of those weird parts and how ES6 — the next version of JavaScript — makes some of those things easier.

Keep in mind that ES6 is backwards compatible. That means that old weirdness will still be around, most likely for a very long time so it is definitely a good thing to be aware of it. We do however get some great new language constructs that help to avoid some of those pitfalls.

Function defaults

In “the weird parts” we discussed how the || operator can be used to assign defaults to falsy values like so

function add(first, second) {

first = first || 0;

second = second || 0;



return first + second;

} add() // -> 0 instead of NaN

add(1) // -> 1 instead of NaN

ES6 allows to declare default values in function parameters which gets us the same functionality with much less code

function add(first = 0, second = 0) {

return first + second;

}

Iterating and destructuring

If we take the original sum calculation example

function sum() {

var sum = 0;

for(var i = 0; i < arguments.length; i++) {

sum += arguments[i];

}

return sum;

}

We have two new language features in ES6 to make it nicer to read. First, there is no need anymore to use the arguments object. We can use the spread operator (…) instead and give our list of arguments a more meaningful name (thank you @rauschma for pointing that out). Second we can use the for … of loop to iterate over arrays and array-like objects. The sum calculation now looks like this:

function sum(...numbers) {

var sum = 0;

for(let current of numbers) {

sum += current;

}

return sum;

} sum(1, 2, 3, 4); // -> 10

It is worth mentioning that the spread operator also covers the fairly common case of passing an array as function arguments (this works for all functions of course):

var args = [1, 2];

// before

sum.apply(null, args);

// now

sum(…args) // -> 3

Scope

We also talked about how JavaScript variables only know function scope and that functions within other functions can access variables from their parent scope (closure).

ES6 introduces two new keywords to declare a variable: let and const. Variables declared with const can only be set once. A variable declared using let will only be available in the current block (instead of the entire function when using var).

This solves a common JavaScript pitfall which we originally discussed with the example of creating 10 buttons and adding a click handler that alerts the current count. In order to circumvent the function scoping problem of var — which manifested in every button click handler alerting the number 10 if just used in a plain loop — we had to introduce a new scope with a wrapper function like this:

for(var i = 0; i < 10; i++) {

var button = $('<button>Button #' + i + '</button>');

var wrapper = function(counter) {

button.click(function() {

alert(counter);

});

}

wrapper(i);

$('body').append(button);

}

With ES6 we can simply declare the counter variable with let and will get the expected result

for(let i = 0; i < 10; i++) {

let button = $('<button>Button #' + i + '</button>');

button.click(function() {

alert(i);

});

$('body').append(button);

}

Similar to the best practise of using triple (===) instead of double equals (==) for comparison it is also a good idea to always use let instead of var when writing ES6 code.

Arrow functions

Functions are used a lot in JavaScript. From Node to AJAX callbacks to DOM event handlers. This is one of the reasons why ES6 introduces a shorter way of declaring a function using the arrow notation (=>). Besides the new declarations style there are also some other differences:

If the function is just a single statement and does not have a body, the value of that statement will be the implicit return value. This makes arrow functions great to use with array methods

[2, 3, 4].map(number => number + 2) // -> [ 4, 5, 6 ]

The this reference of an arrow function is always the same as its surrounding code. This means you won’t loose this in callbacks (but also that this can’t be changed with .call, .apply or .bind).

Lets take the callback example from “the weird parts”

$('button').click(function() {

// Store the old this reference (the clicked button)

var self = this; $.getJSON('someFile.json', function(data) {

// Set the button content

$(self).html(data.text);

});

});

Which becomes a lot shorter using an arrow function:

$('button').click(function() {

$.getJSON('someFile.json', data => $(this).html(data.text));

});

Note: As of the writing of this article V8 does not support the lexical this in arrow function.

Conclusion

ES6 has many new language features that can help to make the JavaScript we know less weird (without hopefully adding too much new weirdness). Have a look at this great overview and then start using it today.