workshop 10: ecmascript 6

Post on 14-Jan-2017

331 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Front End Workshops

IX.ECMAScript 6. Novelties. Browser support

Alex Adrià Cuadripaniaadria@visual-engin.com

Mario García Martínmgarcia@visual-engin.com

Introduction

— INTRODUCTIO —

ECMAScript 6

Also known as ECMAScript 2015 or simply ES6

First working draft published on July 2011

Officially approved on June 2015

Implementation in major JavaScript engines is underway

More information in...

● http://www.ecma-international.org/ecma-262/6.0/index.html

● http://kangax.github.io/compat-table/es6/

ES6 Novelties

— ES6 NOVITATIS —

Default parameters

// ES5function multiply(a, b, c) {

b = typeof b !== 'undefined' ? b : 1;c = typeof c !== 'undefined' ? c : 1;console.log(a * b * c);

}

multiply(5); // 5

// ES6function multiply(a, b = 1, c = 1) {

console.log(a * b * c);}

multiply(5); // 5multiply(5, undefined, 2); // 10

// ES6function plurify(s, p = s + 's') {

console.log(s + ' ' + p); }

plurify('beer'); // 'beer beers'

// ES6function init(options = { 'param1': 1 }) {

console.log(options);}

init(); // { 'param1': 1 }init({ 'param': 2 }); // { 'param': 2 }

Additional usage...

Rest parameters

function f(x, ...y) {console.log(x, y);

}

f(3, 'hello', true); // 3, ['hello', true]f(3, 'hello', true, false); // 3, ['hello', true, false]

// ES 5function logAllArguments() {

for (var i=0; i < arguments.length; i++) {console.log(arguments[i]);

}}

logAllArguments(1, 2, 3, 4, 5); // 1 2 3 4 5

// ES 6function logAllArguments(...args) {

for (var i=0; i < args.length; i++) {console.log(args[i]);

}}

logAllArguments(1, 2, 3, 4, 5); // 1 2 3 4 5

Could replace usage of the ‘arguments’ variable...

Spread operator

function f(x, y, z) {console.log(x + y + z);

}

f(...[1, 2, 3]); // 6

// ES 5var numbers = [-1, 5, 11, 3];Math.max.apply(Math, numbers); // 11

// ES 6var numbers = [-1, 5, 11, 3];Math.max(...numbers); // 11

var x = ['a', 'b'];var y = ['c'];var z = ['d', 'e'];

var arr = [...x, ...y, ...z]; // ['a', 'b', 'c', 'd', 'e']

Practical uses

for..of loopsvar numbers = [2, 3, 4];for (var value of numbers) {

console.log(value);}

// 2, 3, 4

var letters = 'Homer';for (var item of letters) {

console.log(item);}

// 'H', 'o', 'm', 'e', 'r'

Do we really need another way of looping?

// Classic wayfor (var i=0; i<numbers.length; i++) {

console.log(numbers[i]);}

// ES 5numbers.forEach(function(value) {

console.log(value);});

// for..infor (var i in numbers) {

console.log(numbers[i]);}

var a = 5;var b = 10;console.log(`Fifteen is ${a + b} and not ${2 * a + b}.`); // 'Fifteen is 15 and not 20.'

Template strings

// ES 5var greetings = 'Hello\n' +

'How are you\n' +'today?';

// ES 6var greetings = `Hello

How are youtoday?`;

Offers support for multiple lines

Destructuring

var homer = {name: 'Homer',surname: 'Simpson'

};

var { name, surname } = homer;

console.log(name); // 'Homer'console.log(surname); // 'Simpson'

// ES 5var foo = ['one', 'two', 'three'];

var one = foo[0];var two = foo[1];var three = foo[2];

// ES 6var foo = ['one', 'two', 'three'];

var [one, two, three] = foo;

var foo = function() { return [175, 75];

};

var [height, weight] = foo();

console.log(height); // 175console.log(weight); // 75

const

const PI;PI = 3.14; // ERROR

const PI = 3.14;PI = 3.14159; // ERROR

const PI = 3.14;

Value must be assigned in declaration

Read-only

Block scoped

if (true) {const PI = 3.14;

}

console.log(PI); // ERROR

Characteristics

let

var fns = [];for (var i=0; i<4; i++) {

fns.push(function() {console.log(i);

});}

fns[0](); // 4fns[1](); // 4fns[2](); // 4fns[3](); // 4

var fns = [];for (let i=0; i<4; i++) {

fns.push(function() {console.log(i);

});}

fns[0](); // 0fns[1](); // 1fns[2](); // 2fns[3](); // 3

Block scopedlet name = 'Homer';

In previous workshops...

“var”... Are we going to see you ever again?

Block-level function declaration

'use strict';function f() { return 1; }

{console.log(f()); // 2

function f() { return 2; }console.log(f()); // 2

}

console.log(f()); // 1

Arrow functions

// ES5var sum = function(a, b) {

return a + b;}

// ES6var sum = (a, b) => a + b;

function Person() {this.age = 0;

setInterval(() => {this.age++;

}, 1000);}

function Person() {var self = this;

self.age = 0;setInterval(function() {

self.age++;}, 1000);

}

// ES 5var data = ['one', 'two', 'three'];

data.forEach(function(value) {console.log(value)

});

// ES 6var data = ['one', 'two', 'three'];

data.forEach(value => { console.log(value);

});

Class

// ES6class Media {

constructor(title, duration, isPlaying) {this.title = title;this.duration = duration;this.isPlaying = isPlaying;}

start() {this.isPlaying = true;

}

stop() {this.isPlaying = false;

}}

// ES5function Media(title, duration, isPlaying) {

this.title = title;this.duration = duration;this.isPlaying = isPlaying;

}

Media.prototype.start = function start() {this.isPlaying = true;

};

Media.prototype.stop = function stop() {this.isPlaying = false;

};

Inheritance

// ES6class Song extends Media {

constructor(title, artist, duration) {super(title, duration, false);

this.artist = artist;}

}

class Movie extends Media {constructor(title, year, duration) {

super(title, duration, false);this.year = year;

}}

// ES5function Song(title, artist, duration) {

Media.call(this, title, duration, false);this.artist = artist;

}

Song.prototype = Object.create(Media.prototype);

function Movie(title, year, duration) {Media.call(this, title, duration, false);this.year = year;

}

Movie.prototype = Object.create(Media.prototype);

Modules

// lib/math.jsexport function sum(x, y) {

return x + y;}

export const PI = 3.14159;

// lib/ux-math.jsexport * from 'lib/math';export const E = 2.7182;export default function(x) {

return Math.exp(x);}

// app.jsimport * as math from 'lib/math';

console.log(math.sum(math.PI, math.PI));

// otherApp.jsimport {sum, PI} from 'lib/math';

console.log(sum(PI, PI));

// app.jsimport exp, {PI, E} from 'lib/ux-math';

console.log(exp(PI));

Generators

function* genFunc() {console.log('First');yield; // (A)console.log('Second'); // (B)

}

let genObj = genFunc();

genObj.next()

//First

{ value: undefined, done: false }

genObj.next()

//Second

{ value: undefined, done: true }

function* objectEntries(obj) {let keys = Object.keys(obj);

for (let key of keys) {yield [key, obj[key]];

}}

let batman = { first: 'Bruce', last: 'Wayne' };

for (let [key,value] of objectEntries(batman)) {

console.log(`${key}: ${value}`);

}

// Output:

// first: Bruce

// last: Wayne

Typed Arrays

let typedArray = new Uint8Array([0,1,2]);

console.log(typedArray.length); // 3

typedArray[0] = 5;

let normalArray = [...typedArray]; // [5,1,2]

// The elements are stored in typedArray.buffer.

let dataView = new DataView(typedArray.buffer);

console.log(dataView.getUint8(0)); // 5

Typed Arrays

Map

let map = new Map();

map.set('name','Bruce');

map.set('surname','Wayne');

map.size //2

map.get('name'); //Bruce

map.has('name'); //true

map.delete('name'); //true

map.clear();

map.size //0

let map = new Map([

[1, 'one'],

[2, 'two'],

[3, 'three'],

]);

for (let [key, value] of map) {

console.log(key, value);

}

WeakMap

//keys cannot be primitive types

let key = {a:1};

let wm = new WeakMap();

wm.set(key,"value");

wm.get(key); //you can get "value";

key=undefined;

console.log(wm.get(key));

console.log(wm.size); //undefined

//loop through the keys in an weakmap

doesn't work

for(let i of wm) {

console.log(i);

}

//delete all keys doesn't work

wm.clear();

Set

let set = new Set();

set.add('luke');

set.add('yoda');

set.size //2

set.has('luke'); //true

set.delete('luke'); //true

set.has('luke'); //false

set.size //1

set.clear();

set.size //0

let set = new Set(['luke', 'yoda', 'ben']);

set = new Set().add('luke').add('yoda').add('ben');

for (let x of set) {

console.log(x);

}

WeakSet

//values cannot be primitive types

let weakset = new WeakSet();

let obj = {name: 'Vito Corleone'};

weakset.add(obj);

weakset.add(function(){});

weakset.has({name: 'Vito Corleone'}); //false

weakset.has(obj); //true

obj = undefined;

weakset.delete(obj); //false

weakset.delete(function(){}); //false

weakset.size undefined

//loop through the values in an weakset

doesn't work

for (let x of weakset) {

console.log(x);

}

//delete all values doesn't work

weakset.clear();

Proxy

let handler = {

get: function(target, name){

return name in target?

target[name] :

'not a jedi';

}

};

let proxy = new Proxy({}, handler);

proxy.a = 'ben';

proxy.b = 'yoda';

console.log(proxy.a, proxy.b); // ben, yoda

console.log(proxy.c); // not a jedi

let target = {}; // Start with an empty object

let handler = {}; // Don’t intercept anything

let {proxy, revoke} = Proxy.revocable(target,

handler);

proxy.foo = 123;

console.log(proxy.foo); // 123

revoke();

console.log(proxy.foo); // TypeError: Revoked

Promises

var promise = new Promise(

function (resolve, reject) {

...

if (...) {

resolve(value); // success

} else {

reject(reason); // failure

}

});

● Pending: the result hasn’t been computed, yet

● Fulfilled: the result was computed successfully

● Rejected: a failure occurred during computation

Promises

function httpGet(url) {

return new Promise(

function (resolve, reject) {

var request = new XMLHttpRequest();

request.onreadystatechange = function () {

if (this.status === 200) {

resolve(this.response);

//success

} else {

// Something went wrong (404 etc.)

reject(new Error(this.statusText));

}

}

Promises

request.onerror = function () {

reject(new Error('XMLHttpRequest Error: '+this.statusText));

};

request.open('GET', url);

request.send();

});

}

Promises

httpGet('http://myserver.com/example')

.then(

function (value) {

console.log('Contents: ' + value);

},

function (reason) {

console.error('Something went wrong', reason);

});

Object static methods

var original = {};

var merged = {};

original.a = 1;

merged.b = 2;

Object.assign(original, merged);

console.log(original.b) //2

Object.assign(target, source_1, ..., source_n)

Object.is(value1, value2)

Object.is(2, 2) //true

Object.is('test', 'aaa') //false

Object.is(NaN, NaN) //true

Object.is(-0, +0) //false

Object static methods

var human = {

sleep() {

return 'sleeping...';

}

};

var worker = {

work() {

return 'working...';

},

};

Object.setPrototypeOf(worker, human);

worker.sleep(); //sleeping...

Object.setPrototypeOf(obj, prototype);

String static methods

let name = 'Bob';

String.raw`Hi\n${name}!`;

// 'Hi\\nBob!', substitutions are processed.

String.raw`templateString`;

String.fromCodePoint(42); // "*"

String.fromCodePoint(65, 90); // "AZ"

String.fromCodePoint(0x404); // "\u0404"

String.fromCodePoint('_'); // RangeError

String.fromCodePoint(num1[, ...[, numN]])

String.prototype methods

'abc'.repeat(2); // 'abcabc'

String.prototype.repeat

'Ser, o no ser.'.startsWith('Ser'); // true

String.prototype.startsWith

'Ser, o no ser.'.endsWith('ser.'); // true

String.prototype.endsWith

'Ser, o no ser.'.includes('no'); // true

String.prototype.includes

Array static methods

// Array-like primitive types to Array

Array.from([1, 2, 3]);

//[1, 2, 3]

// Any iterable object...

// Set

var s = new Set(["foo", window]);

Array.from(s);

// ["foo", window]

Array.from(arrayLike[, mapFn[, thisArg]])

// Map

var m = new Map([[1, 2], [2, 4], [4, 8]]);

Array.from(m);

// [[1, 2], [2, 4], [4, 8]]

// String

Array.from("foo");

// ["f", "o", "o"]

// Using an arrow function as the map

function to manipulate the elements

Array.from([1, 2, 3], x => x + x);

// [2, 4, 6]

Array static methods

Array.of(1); // [1]

Array.of(1, 2, 3); // [1, 2, 3]

Array.of(undefined); // [undefined]

//The difference between Array.of() and the Array constructor is in the handling of

//integer arguments: Array.of(42) creates an array with a single element, 42, whereas

//Array(42) creates an array with 42 elements, each of which is undefined.

Array.of(element0[, element1[, ...[, elementN]]])

Array.prototype methods

Array.from([ 'a', 'b' ].keys()); //[ 0, 1 ]

Array.prototype.keys()

Array.from([ 'a', 'b' ].values()); //[ 'a', 'b' ]

Array.prototype.values()

Array.from([ 'a', 'b' ].entries()); //[ [ 0, 'a' ], [ 1, 'b' ] ]

for (let [index, elem] of ['a', 'b'].entries()) {

console.log(index, elem);

}

Array.prototype.entries()

Array.prototype methods

[6, -5, 8].find(x => x < 0); //-5

Array.prototype.find(predicate, thisArg?)

[6, -5, 8].findIndex(x => x < 0); //1

Array.prototype.findIndex(predicate, thisArg?)

['a', 'b', 'c'].fill(7); //[ 7, 7, 7 ]

['a', 'b', 'c'].fill(7, 1, 2); //[ 'a', 7, 'c' ]

Array.prototype.fill(value, start?, end?)

Number properties

Number.isFinite(Infinity);

//false

Number.isFinite(NaN);

//false

Number.isFinite(number)

Number.isInteger(number)

Number.isFinite(123);

//true

Number.isInteger(-17);

//true

Number.isInteger(33);

//true

Number.isInteger(33.1);

//false

Number.isInteger('33');

//false

Number.isInteger(NaN);

//false

Number.isInteger(Infinity);

//false

Number properties

Number.isSafeInteger(number)

Number.isSafeInteger(3); // true

Number.isSafeInteger(Math.pow(2, 53)); // false

Number.isSafeInteger(Math.pow(2, 53) - 1); // true

Number.isSafeInteger(NaN); // false

Number.isSafeInteger(Infinity); // false

Number.isSafeInteger('3'); // false

Number.isSafeInteger(3.1); // false

Number.isSafeInteger(3.0); // true

Number.isNAN(number)

Number.isNaN(NaN); // true

Number.isNaN(Number.NaN); // true

Number.isNaN(0 / 0) // true

Number.isNaN("NaN"); // false

Number.isNaN(undefined); // false

Number.isNaN({}); // false

Number.isNaN("blabla"); // false

Number.isNaN(true); // false

Number.isNaN(null); // false

Number.isNaN(37); // false

Math methods

Math.sign(3); // 1

Math.sign(-3); // -1

Math.sign('-3'); // -1

Math.sign(0); // 0

Math.sign(-0); // -0

Math.sign(number)

Math.trunc(13.37); // 13

Math.trunc(0.123); // 0

Math.trunc(-0.123); // -0

Math.trunc('-1.123'); // -1

Math.trunc(number)

Math methods

Math.sinh(0); // 0

Math.sinh(1); // 1.1752011936438014

Math.sinh(number)

Math.log10(2); // 0.3010299956639812

Math.log10(1); // 0

Math.log10(number)

More information in...

● http://blog.teamtreehouse.com/get-started-ecmascript-6

● https://babeljs.io/docs/learn-es2015/

● http://es6-features.org/

● Exploring ES6, by Dr. Axel Rauschmayer (http://exploringjs.com/es6/index.html)

● Setting up ES6, by Dr. Axel Rauschmayer (https://leanpub.com/setting-up-es6/read)

● https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla

Tools

— INSTRUMENTUM —

Browser support...

Browser’s edge versions

Intended mainly for developers (and crazy users)

Frequent updates

Capable of running side by side with stable version

Chrome Canary

Firefox nightly

Opera beta

WebKit nightly

Transpilers

Compile from ES6 source code into ES5 source code

Offer support for ES6 features, to various degrees

More information in...

● https://www.google.com/chrome/browser/canary.html

● https://nightly.mozilla.org/

● http://www.opera.com/es/computer/beta

● http://nightly.webkit.org/

● https://github.com/google/traceur-compiler

● https://babeljs.io/

top related