Presented by Leon Plata
Let's Start with ES6
Support
1

Compatibility Table
Why no try?
Traspilers
io.js and node.js
Traspilers
2

let and const
3
let statement
let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope
Unlike most programming languages, JavaScript does not have block-level scope (variables scoped to surrounding curly brackets); instead, JavaScript has function-level scope. Variables declared within a function are local
Example
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
}
for (let i = 0; i<10; i++) {
console.log(i); // 0, 1, 2, 3, 4 ... 9
}
console.log(i); // i is not defined
const statement
This declaration creates a constant that can be global or local to the function in which it is declared. Constants are block-scoped. The value of a constant cannot change through re-assignment, and a constant cannot be re-declared. An initializer for a constant is required. A constant cannot share its name with a function or a variable in the same scope.
Example
// Assigning to A const variable is a syntax error
const A = 1; A = 2;
// const requires an initializer
const FOO; // SyntaxError: missing = in const declaration
Destructuring
4
Object Destructuring
Object destructuring assignment syntax uses an object literal on the left side of an assignment operation
Example
var o = {p: 42, q: true};
var {p, q} = o;
console.log(p); // 42
console.log(q); // true
// Assign new variable names
var {p: foo, q: bar} = o;
console.log(foo); // 42
console.log(bar); // true
Array Destructuring
Similarly, you can destructure arrays using array literal syntax on the left side of an assignment operation
Example
var foo = ["one", "two", "three"];
// without destructuring
var one = foo[0];
var two = foo[1];
var three = foo[2];
// with destructuring
var [one, two, three] = foo;
// swapping variables
var a = 1;
var b = 3;
[a, b] = [b, a];
// Ignoring some values
function f() {
return [1, 2, 3];
}
var [a, , b] = f();
console.log("A is " + a + " B is " + b);
Mixed Destructuring
It’s possible to mix objects and arrays together in a destructuring assignment expression using a mix of object and array literals
Example
var options = {
repeat: true,
save: false,
colors: [ "red", "green", "blue" ]
};
var { repeat, save, colors: [ firstColor, secondColor ]} = options;
console.log(repeat); // true
console.log(save); // false
console.log(firstColor); // "red"
console.log(secondColor); // "green"
Example
var metadata = {
title: "Scratchpad",
translations: [
{
locale: "de",
localization_tags: [ ],
last_edit: "2014-04-14T08:43:37",
url: "/de/docs/Tools/Scratchpad",
title: "JavaScript-Umgebung"
}
],
url: "/en-US/docs/Tools/Scratchpad"
};
var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata;
console.log(englishTitle); // "Scratchpad"
console.log(localeTitle); // "JavaScript-Umgebung"
Example
var people = [
{
name: "Mike Smith",
family: {
mother: "Jane Smith",
father: "Harry Smith",
sister: "Samantha Smith"
},
age: 35
},
{
name: "Tom Jones",
family: {
mother: "Norah Jones",
father: "Richard Jones",
brother: "Howard Jones"
},
age: 25
}
];
for (var {name: n, family: { father: f } } of people) {
console.log("Name: " + n + ", Father: " + f);
}
// "Name: Mike Smith, Father: Harry Smith"
// "Name: Tom Jones, Father: Richard Jones"
For loop iteration
Example
function userId({id}) {
return id;
}
function whois({displayName: displayName, fullName: {firstName: name}}){
console.log(displayName + " is " + name);
}
var user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
console.log("userId: " + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"
Function parameter
Function Related
5
Default parameters
// ECMAScript 5
function makeRequest(url, timeout, callback) {
timeout = timeout || 2000;
callback = callback || function() {};
// the rest of the function
}
// ECMAScript 2015
function makeRequest(url, timeout = 2000, callback = function() {}) {
// the rest of the function
}
Rest Parameters
// ECMAScript 5
function pick(object) {
let result = Object.create(null);
for (let i = 1, len = arguments.length; i < len; i++) {
result[arguments[i]] = object[arguments[i]];
}
return result;
}
// ECMAScript 2015
function pick(object, ...keys) {
let result = Object.create(null);
for (let i = 0, len = keys.length; i < len; i++) {
result[keys[i]] = object[keys[i]];
}
return result;
}
Allows you to specify that multiple independent arguments should be combined into an array
Spread Operator
// Normal way
let value1 = 25,
value2 = 50;
console.log(Math.max(value1, value2)); // 50
// Better
let values = [25, 50, 75, 100]
console.log(Math.max.apply(Math, values)); // 100
// Much better
let values = [25, 50, 75, 100]
// equivalent to
// console.log(Math.max(25, 50, 75, 100));
console.log(Math.max(...values)); // 100
Allows you to specify an array that should be split and have its items passed in as separate arguments to a function
Object Related
6
Property initializer shorthand
// ECMAScript 5
function createPerson(name, age) {
return {
name: name,
age: age
};
}
// ECMAScript 2015
function createPerson(name, age) {
return {
name,
age
};
}
Method initializer shorthand
// ECMAScript 5
var person = {
name: "Nicholas",
sayName: function() {
console.log(this.name);
}
};
// ECMAScript 2015
var person = {
name: "Nicholas",
sayName() {
console.log(this.name);
}
};
Computed property names
var suffix = " name";
var person = {
["first" + suffix]: "Nicholas",
["last" + suffix]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person["last name"]); // "Zakas"
Arrow Functions
7
Description
Arrow functions are, as the name suggests, functions defined with a new syntax that uses an “arrow” (=>)
// inline
var reflect = value => value;
// block
var reflect = value => {
return value;
};
// effectively equivalent to:
var reflect = function(value) {
return value;
};
// parenthesis
var sum = (num1, num2) => num1 + num2;
// empty
var nothing = () => {};
// return object inline
var createObj = () -> ({id: 1, value: 10});
What's the difference?
- Lexical this binding
- Not newable
- Can’t change this
- No arguments object
Lexical this binding (without)
var PageHandler = {
id: "123456",
init: function() {
document.addEventListener("click", (function(event) {
this.doSomething(event.type); // no error
}).bind(this), false);
},
doSomething: function(type) {
var self = this;
setTimeout(function() {
console.log("Handling " + type + " for " + self.id);
});
},
getFirstArgFunc: function() {
var args = arguments;
return function() {
return args[0];
}
}
};
Lexical this binding (with)
var PageHandler = {
id: "123456",
init: function() {
document.addEventListener("click",
event => this.doSomething(event.type), false);
},
doSomething: function(type) {
setTimeout(() => console.log("Handling " + type + " for " + this.id));
},
getFirstArgFunc: function() {
return () => arguments[0];
}
};
Modules
8
JavaScript Modules
- Asynchronous Module Definition (AMD)
- CommonJS
- Universal Module Definition (UMD)
How modules should work
- Module code automatically runs in strict mode and there’s no way to opt-out of strict mode.
- Variables created in the top level of a module are not automatically added to the shared global scope. They exist only within the top-level scope of the module.
- The value of this in the top level of a module is undefined.
- Modules must export anything that should be available to code outside of the module.
Be careful with ES6 transpilers
ES6 transpilers compile ES6 modules to ES5. Due to the completely new way of passing on data (via bindings), you should expect the ES5 version to not always be completely compliant with the ES6 spec. Things are even trickier when transpiled ES6 code has to interoperate with native CommonJS or AMD modules.
Named Exports
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
//------ main.js ------
import * as lib from 'lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(4, 3)); // 5
Importing the whole module
Default Exports
//------ myFunc.js ------
export default function () { ... };
//------ main1.js ------
import myFunc from 'myFunc';
myFunc();
Classes
9
Resctrictions
- Class declarations, unlike function declarations, are not hoisted.
- All code inside of class declarations runs in strict mode automatically.
- All methods are non-enumerable.
- Calling the class constructor without new throws an error.
- Attempting to overwrite the class name within a class method throws an error.
Class Expression
// class expressions do not require identifiers after "class"
let PersonClass = class {
// equivalent of the PersonType constructor
constructor(name) {
this.name = name;
}
// equivalent of PersonType.prototype.sayName
sayName() {
console.log(this.name);
}
};
As argument
function createObject(classDef) {
return new classDef();
}
let obj = createObject(class {
sayHi() {
console.log("Hi!");
}
});
obj.sayHi(); // "Hi!"
Anonymous class
let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}("Nicholas");
person.sayName(); // "Nicholas"
Accesor Properties
class CustomHTMLElement {
constructor(element) {
this.element = element;
}
get html() {
return this.element.innerHTML;
}
set html(value) {
this.element.innerHTML = value;
}
}
Statics Members
class PersonClass {
// equivalent of the PersonType constructor
constructor(name) {
this.name = name;
}
// equivalent of PersonType.prototype.sayName
sayName() {
console.log(this.name);
}
// equivalent of PersonType.create
static create(name) {
return new PersonClass(name);
}
}
Static Properties
There is (intentionally) no direct declarative way to define either prototype data properties (other than methods) class properties, or instance property
Class properties and prototype data properties need be created outside the declaration.
Properties specified in a class definition are assigned the same attributes as if they appeared in an object literal.
class declarations to declare and define the capabilities of a class. Not its members. An ES6 class declaration defines its contract for its user.
Derived Classes
class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width;
}
getArea() {
return this.length * this.width;
}
}
class Square extends Rectangle {
constructor(length) {
// same as Rectangle.call(this, length, length)
super(length, length);
}
}
var square = new Square(3);
console.log(square.getArea()); // 9
console.log(square instanceof Square); // true
console.log(square instanceof Rectangle); // true
new.target
// abstract base class
class Shape {
constructor() {
if (new.target === Shape) {
throw new Error("This class cannot be instantiated directly.")
}
}
}
class Rectangle extends Shape {
constructor(length, width) {
super();
this.length = length;
this.width = width;
}
}
var x = new Shape(); // throws error
var y = new Rectangle(3, 4); // no error
console.log(y instanceof Shape); // true
Symbols
10
What are Symbols?
ECMAScript 6 symbols began as a way to create private object members.
The focus was around creating properties that were not identified by string names.
Any property with a string name was easy picking to access regardless of the obscurity of the name.
The initial “private names” feature aimed to create non-string property names. That way, normal techniques for detecting these private names wouldn’t work.
Creating Symbols
var firstName = Symbol("first name");
var lastName = Symbol();
var person = {};
person[firstName] = "Nicholas";
person[lastName] = "Zakas";
console.log("first name" in person); // false
console.log(person[firstName]); // "Nicholas"
console.log(firstName); // "Symbol(first name)"
console.log(person[lastName]); // "Zakas"
Sharing Symbols
var uid = Symbol.for("uid");
var object = {
[uid]: "12345"
};
console.log(object[uid]); // "12345"
console.log(uid); // "Symbol(uid)"
var uid2 = Symbol.for("uid");
console.log(uid === uid2); // true
console.log(object[uid2]); // "12345"
console.log(uid2); // "Symbol(uid)"
Simulating private properties
var Person = (function() {
var nameSymbol = Symbol('name');
function Person(name) {
this[nameSymbol] = name;
}
Person.prototype.getName = function() {
return this[nameSymbol];
};
return Person;
}());
var p = new Person('John');
console.log('Person 3 name: ' + p.getName());
delete p.name;
console.log('Person 3 name: ' + p.getName() + ' — stays private.');
console.log('Person 3 properties: ' + Object.getOwnPropertyNames(p));
Well-known symbols
In addition to your own symbols, JavaScript has some built-in symbols which represent internal language behaviors which were not exposed to developers in ECMAScript 5 and before
Template Strings
11
Multiline Strings
let message = `Multiline
string`;
console.log(message); // "Multiline
// string"
console.log(message.length); // 16
let message = `Multiline
string`;
console.log(message); // "Multiline
// string"
console.log(message.length); // 31
Replacing
let count = 10,
price = 0.25,
message = `${count} items cost $${(count * price).toFixed(2)}.`;
console.log(message); // "10 items cost $2.50."
Maps and Sets
12
Very quick reference
Any kind of object or primitive type can be used as key
Let's store unique values of any type of data
Map
Set
var key = {};
var map = new Map();
map.add(key, 'this is a value');
var set = new Set();
map.add(101);
map.add(101);
for (var value of set) {
console.log(value);
} // 101 once
WeakMaps and WeakSets
13
WeakMap
The WeakMap object is a collection of key/value pairs in which the keys are weakly referenced. The keys must be objects and the values can be arbitrary values
new WeakMap([iterable])
// WeakMap.prototype.delete(key)
// WeakMap.prototype.get(key)
// WeakMap.prototype.has(key)
// WeakMap.prototype.set(key, value)
WeakSet
new WeakSet([iterable])
// WeakSet.prototype.add(value)
// WeakSet.prototype.delete(value)
// WeakSet.prototype.has(value)
WeakSets are collections of objects only and not of arbitrary values of any type.
The WeakSet is weak: References to objects in the collection are held weakly. If there is no other reference to an object stored in the WeakSet, they can be garbage collected.
WeakSets are not enumerable.
Iterators
14
function makeIterator(array){
var nextIndex = 0;
return {
next: function(){
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} : {done: true};
}
}
}
An object is an iterator when it knows how to access items from a collection one at a time, while keeping track of its current position within that sequence
for ... of
The for...of statement creates a loop Iterating over iterable objects
let arr = [3, 5, 7];
arr.foo = "hello";
for (let i in arr) {
console.log(i); // logs "0", "1", "2", "foo"
}
for (let i of arr) {
console.log(i); // logs "3", "5", "7"
}
This is really just an optimization. Instead of heaving to return a full array, you can just return a generator which lazily gives individual values back at each iteration. This reduces memory and allocation. Since no array allocation is necessary, you can also express infinite data structures.
for ... of
var fibonacci = {
[Symbol.iterator]: function*() {
var pre = 0, cur = 1;
for (;;) {
var temp = pre;
pre = cur;
cur += temp;
yield cur;
}
}
}
for (var n of fibonacci) {
// truncate the sequence at 1000
if (n > 1000)
break;
console.log(n);
}
Symbol.iterator
The Symbol.iterator well-known symbol specifies the default iterator for an object. Used by for...of.
Iterable
var myIterable = {}
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
Generators
15
A generator is a special type of function that works as a factory for iterators
function* idMaker(){
var index = 0;
while(true)
yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
// ...
function *
yield
The yield keyword causes generator function execution to pause and the value of the expression following the yield keyword is returned to the generator's caller. It can be thought of as a generator-based version of the return keyword.
Promises
16
Very quick reference
var promise = new Promise(
function (resolve, reject) { // (A)
...
if (...) {
resolve(value); // success
} else {
reject(reason); // failure
}
});
Thank you for your attention
References
- https://leanpub.com/understandinges6
- http://es6-features.org/
- https://kangax.github.io/compat-table/es6/
- https://babeljs.io/
- http://www.ecma-international.org/ecma-262/6.0/
- https://developer.mozilla.org/en-US/
- https://curiosity-driven.org/private-properties-in-javascript
- http://www.2ality.com/2014/09/es6-modules-final.html
React JS Section 3.0
By Tarun Sharma
React JS Section 3.0
- 858