ECMAScript
An introduction
Paul Verbeek
- Only Dutch client-side developer
- BookingHome Partner Experience
- Started two weeks ago
- Now expects a party in the RAI every other week
- Worked with ES6 at previous job (Randstad)
Data proves (...) cats (..)
- Eduardo Shiota
ECMAScript Harmony
ECMAScript 6
ECMAScript 2015
ECMAScript?
ECMA-262
ECMA-402
Dart Programming Language
ECMA-222
Adaptive Lossless Data Compression Algorithm
ECMA-74
Measurement of Airborne Noise Emitted by Information Technology and Telecommunications Equipment
ECMA-262
ECMAScript® Language Specification
ActionScript
Adobe ExtendScript
JScript
JScript.NET
V8
SpiderMonkey Chakra
JavaScript
ECMA-262 6th edition
The ECMAScript® 2015 Language Specification
ES6
ECMAScript 5.1
-
strict mode ("use strict")
-
JSON
-
String.trim()
-
getters & setters
- Function.prototype.bind()
-
New Object methods (e.g. Object.create())
-
New Array methods (e.g. Array.map())
-
Date.now()
ECMAScript 5.1
ECMAScript 6
ECMAScript 6
-
Arrow functions
-
Binary and Octal Literals
-
Block-scoped variables
-
Classes
-
Comprehension
-
Default + rest + spread parameters
-
Destructuring
-
Iterators
-
Generators
-
Map + Set + WeakMap + WeakSet
ECMAScript 6
-
Math + Number + String + Object APIs
-
Modules
-
Promises
-
Proxies
-
Reflect API
-
Subclassable Built-ins
-
Symbols
-
Tail Calls
-
Template strings
-
Unicode
ECMAScript 6
-
Arrow functions
-
Block-scoped variables
-
Classes
-
Default, rest & spread parameters
-
Destructuring
-
Modules
-
Template strings
Block-scoped variables
function logPaul() {
if (true) {
var name = 'Paul Verbeek';
}
console.log(name);
}
logPaul();
Function-scoped variables
function logPaul() {
if (true) {
var name = 'Paul Verbeek';
}
console.log(name); // Paul Verbeek
}
logPaul();
function logPaul() {
var name = undefined;
if (true) {
name = 'Paul Verbeek';
}
console.log(name);
}
logPaul();
Block-scoped variables
function logPaul() {
if (true) {
let name = 'Paul Verbeek';
}
console.log(name); // name is not defined
}
logDan();
function logThePauls() {
let pauls = ['Paul Verbeek',
'Paul McCartney',
'Paul Simon'],
for (let i = 0; i < pauls.length; i++) {
console.log(pauls[i]);
}
console.log(i); // i is not defined
}
logThePauls();
var globalVar = 'global variable';
let globalLet = 'also global';
function f() {
var functionVar = 'function-scoped';
let functionLet = 'this one too';
}
f();
function logPaul() {
let name = 'Paul Verbeek';
let name = 'Paul McCartney';
// Identifier 'name' has already been declared
console.log(name);
}
logPaul();
Block-scoped variables
function logConstantPaul() {
const PAUL = 'Paul Verbeek';
PAUL = 'Paul Simon';
// 'PAUL' is read-only
console.log(PAUL);
}
logConstantPaul();
Block-scoped variables
function logConstantPaul() {
const PAUL = {
firstName: 'Paul',
lastName: 'McCartney'
};
PAUL.lastName = 'Verbeek';
console.log(PAUL.lastName); // Verbeek
}
logConstantPaul();
Block-scoped variables
function logConstantPaul() {
const PAUL = {
firstName: 'Paul',
lastName: 'Verbeek'
};
PAUL = {};
// 'PAUL' is read-only
console.log(PAUL.lastName); // Verbeek
}
logConstantPaul();
Temporal Dead Zone (TDZ)
TEMPORAL
Temporal Dead Zone (TDZ)
console.log(typeof foo); // ReferenceError
console.log(typeof bar); // 'undefined'
let foo = 'inner scope';
Temporal Dead Zone (TDZ)
let foo = 'outer scope';
(function() {
console.log(typeof foo); // ReferenceError
console.log(typeof bar); // 'undefined'
let foo = 'inner scope';
}());
Destructuring
// Single values
var name = {};
name.first = 'Paul';
name.last = 'Verbeek';
// Single values
var first = name.first;
var last = name.last;
// Single values
var name = {};
name.first = 'Paul';
name.last = 'Verbeek';
// Multiple values
var name = {
first: 'Paul',
last: 'Verbeek'
};
Constructing
Extracting
vs.
// Single values
var first = name.first;
var last = name.last;
// Multiple values
var ??? = name;
Constructing
Extracting
vs.
// Single values
let name = {};
name.first = 'Paul';
name.last = 'Verbeek';
// Multiple values
let name = {
first: 'Paul',
last: 'Verbeek'
};
// Single values
let first = name.first;
let last = name.last;
// Multiple values
let { first, last } = name;
let name = {
first: 'Paul',
last: 'Verbeek'
};
let { first: firstName, last: lastName } = name;
// firstName = 'Paul'
// lastName = 'Verbeek'
Objects
function logName({ first: firstName,
last: lastName }) {
console.log(firstName, lastName);
}
let name = {
first: 'Paul',
last: 'Verbeek'
};
logName(name);
// Paul, Verbeek
let nameArr = ['Paul', 'Verbeek'];
let [firstName, lastName] = nameArr;
// firstName = 'Paul', lastName = 'Verbeek'
Arrays
let nameArr = ['Paul', 'Verbeek'];
let [firstName, lastName] = nameArr;
// firstName = 'Paul', lastName = 'Verbeek'
[firstName, lastName] = [lastName, firstName];
// firstName = 'Verbeek', lastName = 'Paul'
let nameArr = ['Paul', 'Verbeek'];
let [firstName, lastName] = nameArr;
// firstName = 'Paul', lastName = 'Verbeek'
[firstName, lastName] = [lastName, firstName];
// firstName = 'Verbeek', lastName = 'Paul'
let [all, day, month, year] =
/^(\d\d)-(\d\d)-(\d\d\d\d)$/
.exec('28-08-2015');
Modules
// modules/math.js
const π = 3.14159265359;
// modules/math.js
export const π = 3.14159265359;
// modules/math.js
export const π = 3.14159265359;
// main.js
import { π } from './modules/math.js';
console.log(π); // 3.14159265359
// modules/math.js
export const π = 3.14159265359;
// main.js
import { π as pi } from './modules/math.js';
console.log(pi); // 3.14159265359
// modules/math.js
export const π = 3.14159265359;
// main.js
import { π as pi } from './modules/math.js';
pi = 3.14; // 'pi' is read-only
// modules/math.js
export const π = 3.14159265359;
export function square(x) {
return x * x;
}
// main.js
import { π as pi, square } from './modules/math.js';
console.log(square(4)); // 16
// modules/math.js
export const π = 3.14159265359;
export function square(x) {
return x * x;
}
// main.js
import * as math from './modules/math.js';
console.log(math.square(4)); // 16
console.log(math.π); // 3.14159265359
// modules/foo.js
export default function() {
console.log('bar!');
}
// script.js
import fooFunc from './modules/foo.js';
fooFunc(); // bar!
Arrow functions
(λ expressions)
1. Less typing
let arr = [1, 2, 3];
let square;
// ES5
square = arr.map(function (a) { return a * a });
// SS6
square = arr.map(a => a * a);
// ES5
function Interface() {
var that = this;
var button = document.getElementById('myButton');
button.addEventListener('click', function () {
console.log('CLICK');
that.handleClick();
});
}
Interface.prototype.handleClick = function () { ... };
// ES6
function Interface {
let button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log('CLICK');
this.handleClick();
});
}
Interface.prototype.handleClick = function () { };
2. no more 'var that = this'
Template strings
console.log('In ECMAScript 5.1 this
will result in an error.');
// Uncaught SyntaxError: Unexpected token ILLEGAL
console.log(`In ES6 this
will log with a newline.`);
// In ES6 this
// will log with a newline.
A what?
A backtick
or accent grave
So this: `
Instead of this: '
var location = 'Tech Talks',
topic = 'ES6';
console.log('Talking about ' + topic + ' at ' + location);
// Talking about ES6 at Tech Talks
let location = 'Tech Talks',
topic = 'ES6';
console.log(`Talking about ${topic} at ${location}`);
// Talking about ES6 at Tech Talks
Classes
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person.prototype.fullName = function () {
return this.firstName + ' ' + this.lastName;
};
Person.prototype.toString = function () {
return 'My name is ' + this.fullName();
};
var me = new Person('Paul', 'Verbeek');
console.log(me.toString());
// My name is Paul Verbeek
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName () {
return `${this.firstName} ${this.lastName}`;
}
toString () {
console.log(`My name is ${this.fullName}`);
}
}
let me = new Person('Paul', 'Verbeek');
console.log(me.toString());
// My name is Paul Verbeek
class Person {
...
}
class Employee extends Person {
constructor(firstName, lastName, company) {
super(firstName, lastName);
this.company = company;
}
toString () {
return `${super.toString()}
and I work at ${this.company}`;
}
}
let me = new Employee('Paul', 'Verbeek', 'Booking.com');
console.log(me.toString());
// My name is Paul Verbeek
// and I work at Booking.com
Default, rest & spread parameters
multiply(3); // 6
multiply(3, 3); // 9
function multiply(x, y) {
if (typeof y === "undefined") { y = 2; }
return x * y;
}
multiply(3); // 6
multiply(3, 3); // 9
function multiply(x, y = 2) {
return x * y;
}
multiply(3); // 6
multiply(3, 3); // 9
default
function f(...foo) {
console.log(foo); // [4, 8, 15]
}
f(4, 8, 15);
...spread & ...rest
function f(...foo) {
let numbers = [...foo, 16, 23, 42]
console.log(numbers); // [4, 8, 15, 16, 23, 42]
}
f(4, 8, 15);
function logPaul() {
if (true) {
let name = 'Paul Verbeek';
}
console.log(name); // name is not defined
}
logPaul();
'use strict';
function logPaul() {
if (true) {
var _name = 'Paul Verbeek';
}
console.log(name); // name is not defined
}
logPaul();
function f(...foo) {
let numbers = [...foo, 16, 23, 42]
console.log(numbers); // [4, 8, 15, 16, 23, 42]
}
f(4, 8, 15);
"use strict";
function f() {
for (var _len = arguments.length, foo = Array(_len),
_key = 0; _key < _len; _key++) {
foo[_key] = arguments[_key];
}
var numbers = [].concat(foo, [16, 23, 42]);
console.log(numbers); // [4, 8, 15, 16, 23, 42]
}
f(4, 8, 15);
http://exploringjs.com/
Dr. Axel Rauschmayer
ECMAScript 6
ECMAScript 2015
ECMAScript Harmony
ECMA-262 6th edition
The ECMAScript® 2015 Language Specification
-
Binary and Octal Literals
-
Comprehension
-
Iterators
-
Generators
-
Map + Set + WeakMap + WeakSet
-
Math + Number + String + Object APIs
-
Promises
-
Proxies
-
Reflect API
-
Subclassable Built-ins
-
Symbols
-
Tail Calls
-
Unicode
- Easier to write
- Easier to maintain
- Faster code execution (eventually)
How are we going to use this at Booking.com?
¯\_(ツ)_/¯
ECMAScript 2015 - Booking.com
By Paul Verbeek
ECMAScript 2015 - Booking.com
- 754