adding es6 to your developer toolbox
TRANSCRIPT
#devES6ADDING ES6 TO YOUR TOOLBOX
@ j e f f re y s t r au s s
”ES6? That's the new JavaScript!
~ mr. developer
”No!
~ me
ECMAScript
ECMAScript2015
not all-or-nothingexperimentES6 IS AN EVOLUTION
experimentNOT ALL-OR-NOTHING
strings
template literals
var greeting =
"Hello, " + user.first + " " + user.last + "!";
var url =
"www.mysite.com" + "/foo/" + fooId + "/bar/" + barId;
ES5:
`backticks`
${expression}
var greeting =
"Hello, " + user.first + " " + user.last + "!";
var url =
"www.mysite.com" + "/foo/" + fooId + "/bar/" + barId;
ES5:
var greeting = `Hello, ${user.first} ${user.last}!`;
var url = `www.mysite.com/foo/${fooId}/bar/${barId}/`;
ES6:
multi-line strings
var poem = "so much depends\n"
+ "upon\n\n"
+ "a red wheel\n"
+ "barrow\n\n"
+ "glazed with rain\n"
+ "water\n\n"
+ "beside the white\n"
+ "chickens";
ES5:
var poem =
`so much depends
upon
a red wheel
barrow
glazed with rain
water
beside the white
chickens`;
ES6:
default parameters
var drawRect = function(width, height, color) {
width = width || 1;
height = height || 1;
color = color || 'orange';
/* draw stuff */
return width * height;
};
ES5:
var drawRect = function(width, height, color) {
width = width || 1;
height = height || 1;
color = color || 'orange';
/* draw stuff */
return width * height;
};
drawRect(); // draws orange; returns 1
drawRect(0, 4, 'blue'); // draws blue, but returns 4
ES5:
var drawRect = function(width=1, height=1, color='orange') { /* draw stuff */
return width * height;
};
ES6:
var drawRect = function(width=1, height=1, color='orange') { /* draw stuff */
return width * height;
};
drawRect(0, 4, 'blue'); // returns 0
ES6:
collections
arrays
var myStringArray = new Array("blue");
// ["blue"]
var myBoolArray = new Array(false);
// [false]
var myIntArray = new Array(2);
// [undefined x 2]
ES5:
var myIntArray = new Array(2);
// [undefined x 2]
ES5:
var fixedIntArray = Array.of(2); // [2]
ES6:
function getArgsArray() {
return Array.prototype.slice.apply(arguments);
};
getArgsArray('foo', true, 42);
// ['foo', true, 42]
ES5:
function getArgsArray() {
return Array.prototype.slice.apply(arguments);
};
getArgsArray('foo', true, 42);
// ['foo', true, 42]
ES5:
function getArgsArray() {
return Array.from(arguments); };
getArgsArray('foo', true, 42);
// ['foo', true, 42]
ES6:
iterables
`for-of` loop
var body = ['head', 'shoulders', 'knees', 'toes'];
for (var i = 0; i < body.length; i++) { tap(body[i]) };
ES5:
var body = ['head', 'shoulders', 'knees', 'toes'];
for (var i = 0; i < body.length; i++) { tap(body[i]) };
ES5:
var body = ['head', 'shoulders', 'knees', 'toes'];
for (var part of body) { tap(part);
}
ES6:
var alphabet = 'abcdefg';
for (var letter of alphabet) {
sing(letter);
}
ES6:
ES6:
...spread operator
var alphabet = 'abcdefg';
function sing() {
console.log(arguments);
}
sing(...alphabet); // ["a", "b", "c", "d", "e", "f", "g"]
ES6:
ES6:
destructuring
[ ] = fooArray;
{ } = fooObject;
var x, y, z, coords;
coords = [29, 22, 37];
x = coords[0];
y = coords[1];
z = coords[2];
ES5:
var x, y, z, coords;
coords = [29, 22, 37];
x = coords[0];
y = coords[1];
z = coords[2];
ES5:
var coords = [29, 22, 37];
var [x, y, z] = coords;
ES6:
var x, y, z, coords;
coords = [29, 22, 37];
x = coords[0];
y = coords[1];
z = coords[2];
ES5:
var coords = [29, 22, 37];
var [x, y, z] = coords; var [foo, , bar] = coords;
ES6:
var user, email, display;
user = { name: 'Jeff', email: '[email protected]' };
email = user.email;
display = user.name;
ES5:
var user, email, display;
user = { name: 'Jeff', email: '[email protected]' };
email = user.email;
display = user.name;
ES5:
var user = { name: 'Jeff', email: '[email protected]' };
var {email} = user; var {name: display} = user;
ES6:
swapping variables
var temp = x;
x = y;
y = temp;
ES5:
[y, x] = [x, y];
ES6:
process return values
var drawRect = function(width=1, height=1, color='orange') {
/* draw stuff */
return {area: width * height, hex: getHex(color)};
};
ES6:
var drawRect = function(width=1, height=1, color='orange') {
/* draw stuff */
return {area: width * height, hex: getHex(color)};
};
var {area, hex: rgb} = drawRect(4, 6, 'blue');
// area == 24, rgb == '#0000FF'
ES6:
{ scope }
block-scoped vars
function-scoped
var foo = function(bar) {
if (bar) {
var message = 'Hello!'; // declared here
alert(message);
}
return message; // still in scope here };
ES5:
iifeIMMEDIATELY INVOKED FUNCTION EXPRESSION
var foo = function(bar) {
if (bar) {
(function() { var message = 'Hello!'; // declared here
alert(message);
})(); }
return message; // ReferenceError: message is not defined };
ES5:
closure
// assume links has an array of DOM elements
for (var i = 0; i < links.length; i++) {
links[i].onclick = function() {
console.log(i);
};
}
// whoops! all links log the max index!
ES5:
// assume links has an array of DOM elements
for (var i = 0; i < links.length; i++) {
links[i].onclick = (function(x) { return function() { console.log(x); // preserved context }; })(i); }
// clicking links gives the correct result
ES5:
hoisting & globals
function foo() {
x = 10;
y = 20;
var x, y;
var area = x * y;
return area;
};
ES5:
function foo() {
var x, y;
var area;
x = 10;
y = 20;
area = x * y;
return area;
};
ES5:
function foo() {
var x, y;
// yikes! area may be in the global scope!
x = 10;
y = 20;
area = x * y;
return area;
};
ES5:
let
function(bar) {
if (bar) {
var message = 'Hello!'; // declared here
alert(message);
}
return message; // still in scope here };
ES5:
function(bar) {
if (bar) {
let message = 'Hello!'; // declared here alert(message);
}
return message; // ReferenceError: message is not defined };
ES6:
// assume links has an array of DOM elements
for (var i = 0; i < links.length; i++) {
links[i].onclick = function() {
console.log(i);
};
};
// whoops! all links log the max index!
ES5:
// assume links has an array of DOM elements
for (let i = 0; i < links.length; i++) { links[i].onclick = function() {
console.log(i);
};
};
// all better, with no IIFE or extra closure!
ES6:
temporal dead zone
function foo() {
x = 10; // ReferenceError: x is not defined
y = 20;
let x, y; let area = x * y;
return area;
};
ES6:
arrow functions
syntax
(args) => { statements }
function logSum(x, y) {
var sum = x + y;
console.log(sum);
}
ES5:
function logSum(x, y) {
var sum = x + y;
console.log(sum);
}
ES5:
let logSum = (a, b) => { let sum = a + b;
console.log(sum);
};
ES6:
(args) => expression;
function sum(x, y) {
return x + y;
}
ES5:
let sum = (x, y) => x + y;ES6:
let speak = () => 'Hello!';
let wrappedMethod = (arg) => innerMethod(arg);
let announce = (name) => `Announcing ${name}!`;
let getUser = () => ( { id: 42, name: 'Jeff' } );
ES6:
let speak = () => 'Hello!';
let wrappedMethod = (arg) => innerMethod(arg);
let announce = name => `Announcing ${name}!`;
let getUser = () => ( { id: 42, name: 'Jeff' } );
ES6:
let speak = () => 'Hello!';
let wrappedMethod = (arg) => innerMethod(arg);
let announce = (name) => `Announcing ${name}!`;
let getUser = () => ( { id: 42, name: 'Jeff' } );
ES6:
lexical `this`
var person = {
name: 'Jeff',
greet: function() {
console.log('Now greeting ' + this.name);
setTimeout(function() {
console.log('Hello, ' + this.name + '!');
}, 3000);
}
};
ES5:
var person = {
name: 'Jeff',
greet: function() {
console.log('Now greeting ' + this.name); setTimeout(function() {
console.log('Hello, ' + this.name + '!');
}, 3000);
}
};
person.greet();
// Now greeting Jeff
ES5:
var person = {
name: 'Jeff',
greet: function() {
console.log('Now greeting ' + this.name);
setTimeout(function() {
console.log('Hello, ' + this.name + '!'); }, 3000);
}
};
person.greet();
// Now greeting Jeff
// Hello, !
ES5:
that | self
{ }.bind(this)
var person = {
name: 'Jeff',
greet: function() {
console.log('Now greeting ' + this.name);
var that = this; setTimeout(function() {
console.log('Hello, ' + that.name + '!'); }, 3000);
}
};
ES5:
var person = {
name: 'Jeff',
greet: function() {
console.log('Now greeting ' + this.name);
setTimeout(function() {
console.log('Hello, ' + this.name + '!'); }.bind(this), 3000); }
};
ES5:
let person = {
name: 'Jeff',
greet: function() {
console.log(`Greeting ${this.name}`);
setTimeout(() => { console.log(`Hello, ${this.name}!`);
}, 3000);
}
};
ES6:
putting it to use
compatibility
http://kangax.github.io
/compat-table/es6
bit.ly/es6-compat
$ npm install --save-dev babel-cli
$ npm install --save-dev babel-preset-es2015
$ echo '{ "presets": ["es2015"] }' > .babelrc
$ babel mySource.js -o myTranspiled.js
flexibility
flexibility
babeljs.io/repl
not all-or-nothingNEXT STEPS
es6 is an evolution
evolve
@je f f re yS t r au s s #de vES6