ECMAScript 6
@MichalZalecki
michalzalecki.com
Overview
- ECMAScript 1 - June 1997
- ECMAScript 2 - June 1998
- ECMAScript 3 - December 1999
- ECMAScript 4 - Abandoned
- ECMAScript 5 - December 2009
- ECMAScript 5.1 - June 2011
- ECMAScript 6 "Harmony" - June 2015
- ECMAScript 7 - ?
LET
if (true) {
var x = 1;
}
expect(x).toEqual(1);
if (true) {
let x = 1;
}
expect(x).toEqual(1); // ReferenceError
LET
let funcs = [];
for (var i of [4, 5, 6]) {
funcs.push(function() { return i; });
}
funcs[0](); // 6
funcs[1](); // 6
funcs[2](); // 6
let funcs = [];
for (let i of [4, 5, 6]) {
funcs.push(function() { return i; });
}
funcs[0](); // 4
funcs[1](); // 5
funcs[2](); // 6
CONST
const x = 1;
const y = {x: 1};
x = 2; // x is read-only
y.x = 2; // 2
Arrow functions
let square = x => x * x;
let triangleHeron = (a, b, c) => {
let p = (a + b + c)/2;
return Math.sqrt(p*(p-a)*(p-b)*(p-c));
};
let objectify = x => ({ value: x });
square(13); // 169
triangleHeron(3, 4, 5); // 6
objectify("foo"); // { value:"foo" }
Default Parameters
function f(list, indexA, indexB) {
indexA = indexA || 0;
indexB = indexB || list.length;
return [list, indexA, indexB];
}
f([1, 2, 3]); // [[1, 2, 3], 0, 3]
f([1, 2, 3], 1); // [[1, 2, 3], 1, 3]
f([1, 2, 3], 1, 2); // [[1, 2, 3], 1, 2]
function f(list, indexA = 0, indexB = list.length) {
return [list, indexA, indexB];
}
f([1, 2, 3]); // [[1, 2, 3], 0, 3]
f([1, 2, 3], 1); // [[1, 2, 3], 1, 3]
f([1, 2, 3], 1, 2); // [[1, 2, 3], 1, 2]
CLASSES
function Point(x, y) {
this.x = x || 0;
this.y = y || 0;
}
Point.prototype.distance = function(x, y) {
return Math.sqrt(Math.pow(this.x - x, 2)
+ Math.pow(this.y - y, 2));
};
var a = new Point(2, 1);
a.distance(1, 2); // 1.4142135623730951
class Point {
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
distance(x, y) {
return Math.sqrt(Math.pow(this.x - x, 2)
+ Math.pow(this.y - y, 2));
}
}
let a = new Point(2, 1);
a.distance(1, 2); // 1.4142135623730951
CLASSES
function Circle(r, x, y) {
Point.call(this, x, y);
this.r = r;
}
Circle.prototype = new Point();
var a = new Circle(6, 2, 1);
expect(a.r).toEqual(6);
class Circle extends Point {
constructor(r, x, y) {
super(x, y);
this.r = r;
}
}
let a = new Circle(6, 2, 1);
expect(a.r).toEqual(6);
Destructing Assignment
let [a, , [b, c]] = [1, 2, [3, 4]];
expect(a).toEqual(1);
expect(b).toEqual(3);
expect(c).toEqual(4);
Destructing Assignment
let {firstName, lastName: surname,
info: {age, driver}} =
{firstName: "Foo", lastName: "Bar",
info: {age: 20, driver: true}};
expect(firstName).toEqual("Foo");
expect(surname).toEqual("Bar");
expect(age).toEqual(20);
expect(driver).toEqual(true);
Rest Parameters
function buy(where, ...items) {
return "I'm going to " + where + " to buy "
+ items.length + " items: "
+ items.slice(0, -1).join(", ")
+ " and " + items.slice(-1) + ".";
}
buy("the mall", "jacket", "bag", "headphones")
// "I'm going to the mall to buy 3
// items: jacket, bag and headphones."
Spread
function send(what, where, toWhom) {
return "I'm sending " + what + " to " + toWhom
+ " who is in " + where + ".";
}
send(...["the letter", "Poland", "Mike"]);
// "I'm sending the letter to Mike
// who is in Poland."
Enhanced Object Literals
function greet(name) {
return "Hello " + name;
}
let x = 2;
let obj = {
[x*2]: "Computed Property Name",
__proto__: {
hi: function () { return "Hi!" },
by: function () { return "By!" }
},
greet
};
expect(obj[4]).toEqual("Computed Property Name");
expect(obj.hi()).toEqual("Hi!");
expect(obj.by()).toEqual("By!");
expect(obj.greet("Bob")).toEqual("Hello Bob");
Symbols
expect(Symbol("bar"))
.not.toBe(Symbol("bar"));
expect(Symbol.for("bar"))
.toBe(Symbol.for("bar"));
Symbols
function Safe(secretData) {
let s = Symbol("secret symbol");
this[s] = secretData;
}
let obj = new Safe("secret");
expect(obj["secret symbol"]).toBeUndefined();
expect(obj[Symbol("secret symbol")])
.toBeUndefined();
expect(obj[Object.getOwnPropertySymbols(obj)[0]])
.toEqual("secret");
Iterators & for...oF
function fibonacci(i) {
return {
[Symbol.iterator]() {
let pre = -1, cur = 1;
return {
next() {
[pre, cur] = [cur, pre + cur];
return {done: !(i--), value: cur};}
}
}
}
}
let fib = [];
for (let n of fibonacci(10)) {
fib.push(n);
}
expect(fib).toEqual([0, 1, 1, 2, 3, 5, 8, 13, 21, 34]);
GENERATORS
function* foo() {
let i = 0;
yield ++i;
yield ++i;
yield ++i;
}
let seq = foo();
expect(seq.next().value).toEqual(1);
expect(seq.next().value).toEqual(2);
expect(seq.next().value).toEqual(3);
GENERATORS
function* flatten(t, n = 0) {
if (t[n]) {
if (Array.isArray(t[n]))
yield* flatten(t[n])
else
yield t[n];
yield* flatten(t, n + 1);
}
}
let nums = [];
for (let n of flatten([10, 11, 12, [13, 14, [15, 16]], 17])) {
nums.push(n);
}
expect(nums).toEqual([10, 11, 12, 13, 14, 15, 16, 17]);
GENERATORS
// The idea comes from
// http://youtu.be/s-BwEk-Y4kg?t=14m42s
function* powGenerator() {
return Math.pow(yield "a", yield "b");
}
let g = powGenerator();
expect(g.next().value).toEqual("a");
expect(g.next(10).value).toEqual("b");
expect(g.next(2).value).toEqual(100);
Numeric Literals
expect([
0b111,
0b11110000,
0b00001111
]).toEqual([
7,
240,
15
]);
expect([
0o7,
0o360,
0o17
]).toEqual([
7,
240,
15
]);
Template literals
let name = "Foo";
let surname = "Bar";
expect(`${name} ${surname}`)
.toEqual("Foo Bar");
Template literals
let name = "Michal";
let surname = "Zalecki";
`${name} ${surname} greats`
// 'Michal Zalecki greats'
Email`${name} ${surname} greats`
// 'Michal Zalecki <michal@michalzalecki.com> greats'
function Email(strs, ...values) {
return values[0] + " " + values[1]
+ " <" + values[0].toLowerCase() + "@"
+ values[0].toLowerCase() + values[1].toLowerCase()
+ ".com>" + strs[strs.length - 1];
}
Promises
new Promise((resolve, reject) => {
setTimeout(() => {
if (!(-1/0)) {
resolve("Success!");
} else {
reject(new Error("WTF?"));
}
}, 1000);
});
(new Promise(...))
.then((data) => {
expect(data).toEqual("Success!");
})
.catch((err) => {
expect(err).toEqual(new Error("WTF?"));
});
Promises
stepPromise(stepper.step())
.then((stepper) => stepPromise(stepper.step()))
.then((stepper) => stepPromise(stepper.step(2)))
.then((stepper) => stepPromise(stepper.step()))
.then((stepper) => stepPromise(stepper.step(3)))
.then((stepper) => stepPromise(stepper.step(99999)))
.then((stepper) => {}, (err) => {
expect(err).toEqual(new Error("That's enough!"));
});
Modules
// modules/math.js
export function sum(x, y) {
return x + y;
}
export var pi = 3.141593;
// modules/person.js
export var name = "Foo";
export var surname = "Bar";
// modules.js
import * as mathematics from "modules/math";
import {name, surname} from "modules/person";
expect(mathematics.sum(2, 3)).toEqual(5);
expect(mathematics.pi).toEqual(3.141593);
expect(name).toEqual("Foo");
expect(surname).toEqual("Bar");
Modules
<script>
System.import('modules/math').then((m) => {
expect("2π = " + m.sum(m.pi, m.pi))
.toEqual("2π = 6.283186");
});
System.import('modules/person').then((m) => {
expect("I'm " + m.name + " " + m.surname)
.toEqual("I'm Foo Bar");
});
</script>
PROXY
var address = {
'Marie Lynch': 'mlynch2@state.tx.us',
...
'Ryan Bradley': 'rbradley3@com.com' };
var handler = {
set: (target, property, value, receiver) => {
if (!value.match(/^\S+@\S+\.\S+$/))
throw new TypeError(`${value} is invalid email!`);
target[property] = value;
return true;
},
get: (target, property, receiver) => {
return property in target ?
target[property] : "Not Found"; }
// deleteProperty
// enumerate
// ...
};
var addressBook = new Proxy(address, handler);
try {
addressBook['Joseph Fields'] = 'jfields9@fedbur.com';
addressBook['Kathryn Lewis'] = 'klewis.com';
} catch(e) {
console.error(e.message);
// "klewis.com is invalid email!"
}
console.log(addressBook['Marie Lynch']);
// "mlynch2@state.tx.us"
console.log(addressBook['Joseph Fields']);
// "jfields9@fedbur.com"
console.log(addressBook['Kathryn Lewis']);
// "Not Found"
What else?
- Reflect
- Object API
- Number API
- Math API
- Array API
- Map, Set, WeakMap, WeakSet
- Tail Call Optimization
- Typed Arrays
- and more... (but not much more)
ES6 Features Runtime
git clone https://github.com/MichalZalecki/es6features-runtime
ECMAScript 6 Overview
http://michalzalecki.com/ecmascript-6-overview/
Questions?