Kuba Niechcial
I am senior software developer and team leader at netguru, Poland. I work mostly with Ember.js, React and Ruby on Rails. I am passionate blogger and you can find out most of my work on my website.
@jniechcial
@nekath
What is ES2015 (aka ES6)?
New specification for JavaScript that introduces huge amount of great features that were impossible to either get or prototype polyfill
Arrow functions, classes, interpolation, iterators, and more...
Is it supported already?
Only partially. So how can we use it safely?
Babel - the cure for incompatibilities
Babel is a tool to transform ES2015 to ES5 (fully supported)
How Babel works - quick insight
Babel is... transforming your code
Parser
Creates
Abstract Syntax Tree
Transformer
Manipulates
Abstract Syntax Tree
Generator
Generate JS from
Abstract Syntax Tree
ES2015 setup in Rails
Sprockets-es6
Javascript libraries are not managed.
It’s not a production gem.
Just don’t use it ! :)
ES2015 setup in Rails
Perfect setup
ES2015 setup in Rails
Browserify-rails
browserify will recursively analyze all the require() calls in your app in order to build a bundle you can serve up to the browser in a single <script> tag
ES2015 setup in Rails
Browserify-rails
ES2015 setup in Rails
Browserify-rails
Summary:
Be able to use es6 modules - yes, but it needs a small hack
Libs are maintained by npm - yes
Libs css files are served too - no
Simple (less magic/sprockets hacks) - yes/no
ES2015 setup in Rails
Webpack
It’s a module bundler, but it also handles ‘javascript friends’ like images, fonts, css
ES2015 setup in Rails
Webpack
Summary:
Be able to use es6 modules - yes
Libs are maintained by npm - yes
Libs css files are served too - yes
Simple (less magic/sprockets hacks) - yes
What we will cover from ES2015?
Arrow functions
let array = [1, 2, 3];
let newArray = array.map( (item) => {
return item * 2;
});
Major change is that arrow function
share the same this as their surroundings!
(like fat arrow in CoffeeScript)
Classes
// ---- EXAMPLE FROM
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.sqrt(dx*dx + dy*dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
console.log(Point.distance(p1, p2));
But JavaScript is still prototype based inherited, so classes are only syntax sugar :)
What is new? Constructors, static functions
and super calls
Enhanced Object Literal Part 1
Shorthand Property Names
// Old way
var a = "foo", b = "bar";
var obj = { a: a, b: b};
// New way - shorthand property names
var a = "foo", b = "bar";
var obj = { a, b};
// Old way
var obj = {
someFunction: function(params) {
// ...
}
};
// New way - shorhand function names
var obj = {
someFunction(params) {
// ...
}
};
Enhanced Object Literal Part 2
Computed Property Names
var prop = "foo";
var obj = {
[prop]: "hey",
["b" + "ar"]: "there",
};
// ---> obj["foo"] == "hey"; obj["bar"] == "there";
Template strings Part 1
Bye, bye, CoffeeScript
var name = "Bob", time = "today";
var string = `Hello ${name}, how are you ${time}?`;
Have you noticed?
What looks strange here?
Template strings Part 2
Bye, bye, CoffeeScript
var a = 5;
var b = 10;
function taggingFunction(strings, ...values) {
console.log(strings[0]); // "Hello "
console.log(strings[1]); // " world "
console.log(values[0]); // 15
console.log(values[1]); // 50
return "Bazinga!";
}
taggingFunction`Hello ${ a + b } world ${ a * b}`;
// What's the result here?
Remember about security - tagged template strings should not be created by untrusted users.
Destructing Part 1
// list matching
var [a, , b] = [1, 2, 3]; // or var [a, _, b] (...)
// object matching
var { newX: x, newY: y } = getPoint(); // #getPoint returns { x: someX, y: someY }
// object matching shorthand
var { x, y } = getPoint();
// destructing in function params
function greetings({name: x}) {
console.log(`Hello, ${x}!`);
};
greetings({name: "Foo Bar"});
It fails silently, returning just undefined.
Destructing Part 2
// swapping vars
var a = 1, b = 3;
[a, b] = [b, a]; // nice, huh?
// multiple-value returns
function f() {
return [1, 2, 3];
}
var [a, b, c] = f();
Default and spread args
// default args
function multiply(x, y = 1) {
return x * y;
}
multiply(5); // 5
// rest arguments (remove needs for arguments propert on Function object
function f(x, ...y) {
return x * y.length;
}
f(3, "hi", "ho", true); // 9
// spread is destructing the array to args
function f(x, y, z) {
return x + y + z;
}
f(...[1, 2, 3]); // 6
Let, var and const
function varTest() {
var x = 31;
if (true) {
var x = 71; // same variable!
console.log(x); // 71
}
console.log(x); // 71
}
function letTest() {
let x = 31;
if (true) {
let x = 71; // different variable
console.log(x); // 71
}
console.log(x); // 31
}
Let is the new var, but safer
Let and const are block-scoped
var was declaring either globally on window or for whole function
Iterators
function idMaker(){
var index = 0;
return {
next: function(){
return {value: index++, done: false};
}
};
}
var it = idMaker();
console.log(it.next().value); // 0
Iterators must implement simple interface - return object with next method that returns object with next value and done flag
Iterables
// example from Babeljs.io
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1;
return {
next() {
[pre, cur] = [cur, pre + cur];
return { done: false, value: cur }
}
}
}
}
for (var n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000)
break;
console.log(n);
}
Iterables are objects that implements iterators
Predefined iterables are e.g. arrays
Modules
// lib/math.js
export function sum(a, b) {
return a + b;
}
// app.js
import * as math from "lib/math";
math.sum(5, 7);
// e.g. in Emberjs:
// my-component.js
export default Ember.Component.extend({
// ...
});
// some other component
import Component from "my-component";
export default Component.extend({
// ...
});
Language-level support for modules for component definition
Array and Object API
[1, 2, 3, 4].includes(3) // true
"abc".repeat(3) // "abcabcabc"
["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
["a", "b", "c"].keys() // iterator 0, 1, 2
["a", "b", "c"].values() // iterator "a", "b", "c"
Formerly supported as polyfills, now accessible
Promises
// chaining - the exit from callback hell
fetch("www.items.com/items").then( (result) => {
this.items = result;
return fetch("www.items.com/me");
}).then( (result) => {
this.myCompany = result;
});
Already used in modern JS frameworks
Promises represent objects that eventually will become values
If you think you know how Promises work, check out this blog post
Linter
In Ember, you can set your tests to fail if Linter outputs any error
Use JSLint or ESLint in your code to quickly learn new ES6 features, improve your code quality and make it less buggy
Questions?
More to read
By Kuba Niechcial
Introduction to JS ES2015, covering most commonly used new features in day to day JS development. Previously presented on Netguru internal meetup by @jniechcial.
I am senior software developer and team leader at netguru, Poland. I work mostly with Ember.js, React and Ruby on Rails. I am passionate blogger and you can find out most of my work on my website.