internal workshop es6_2015
TRANSCRIPT
ES6 (2015)Enterprise Java
ECMAScript 6
History
European Computer Manufacturers' Association, ECMA
What we will see...● Declaration variables with let, var and const
● Template String
● Arrows
● Destructuring
● Default + Rest + Spread
● Iterators
● Classes
● Module Loaders
● Map + Set + WeakMap + WeakSet
● Promises
Let vs Var
Using let instead of var prevents variable declarations from being moved to the top of the scope.
Prior to executing our code, JS moves var declarations all the way up to the top of the scope
This is known as: hoisting
http://jsfiddle.net/rmXcF/5/
var is scoped to the nearest function block and let is scoped to the nearest enclosing block
for(var i = 1; i < 6; i++) {
document.getElementById('my-element' + i) .addEventListener('click',
function() { alert(i) })
}
//reference to the i object is being stored in the click handler closure, rather than the actual value of i.
We can also use CONST for read-only named contants
● Consts must always be assigned an initial value.● Consts are scoped by blocks.
Can we safety use let?
● Server side: YES● Transpiled JS: YES● Client-Side + Not
Transpiled JS: Check browsers support
● If you're writing server-side JavaScript code (Node.js), you can safely use the let statement.
● If you're writing client-side JavaScript code and use a transpiler (like Traceur), you can safely use the let statement, however your code is likely to be anything but optimal with respect to performance.
● If you're writing client-side JavaScript code and don't use a transpiler, you need to consider browser support.
● Today, Feb 2016, these are some browsers that either don't support let or have only partial support
● Internet explorer 10 and below (no support)● Firefox 43 and below (no support)● Safari 9 and below (no support)● Opera Mini 8 and below (no support)● Android browser 4 and below (no support)● Opera 36 and below (partial support)● Chome 51 and below (partial support)
Template Strings
``
We can interpolate
Strings easily with
new ES6 standard
//ES5
var sayHi = "ola " +
"k " +
"ase ";
//ES6
var sayHi = `ola
k
ase`;
//ES6
let name1 = "JavaScript";
let name2 = "awesome";
console.log(`I just wanna say that ${name1} is
${name2)`;
Arrows
=>
//ES5
var data = [{...}, {...}, {...}, ...];
data.forEach(function(elem){
// We treat the element
console.log(elem)
});
Imagine a variable with
some data that includes
an array of objects
With arrow function, we
can substitute this code
//ES6
var data = [{...}, {...}, {...}, ...];
data.forEach(elem => {
console.log(elem);
});
We could also use it
like this...
//ES5
var myFunction = function(num) {
return num + num;
}
// ES6
var myFunction = (num) => num + num;
Destructuring
Destructuring allows
using pattern matching,
with support for
matching arrays and
objects.
Destructuring is fail-soft,
similar to standard object
lookup foo["bar"],
producing undefined
values when not found.
Arrays
The destructuring assignment uses similar syntax, but on the left-hand side of the assignment
to define what elements to extract from the sourced variable.
var foo = ["one", "two", "three"];
var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
A variable can be assigned its value via destructuring separate from the variable's declaration.
var a, b;
[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2
A variable can be assigned a default, in the case that the value pulled from the array is
undefined.
var a, b;
[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7
We can ignore same returned values and get them from a function call
function f() {
return [1, 2, 3];
}
var [a, , b] = f();
console.log(a); // 1
console.log(b); // 3
Objects
var a, b;
({a, b} = {a:1, b:2});
Default values
var {a=10, b=5} = {a: 3};
console.log(a); // 3
console.log(b); // 5
//ES5
function drawES5Chart(options) {
options = options === undefined ? {} : options;
var size = options.size === undefined ? 'big' : options.size;
var cords = options.cords === undefined ? { x: 0, y: 0 } :
options.cords;
var radius = options.radius === undefined ? 25 : options.radius;
console.log(size, cords, radius);
// now finally do some chart drawing
}
drawES5Chart({
cords: { x: 18, y: 30 },
radius: 30
});
Setting a function
parameter's default value
//ES6
function drawES6Chart({size = 'big', cords = { x: 0, y: 0 }, radius =
25} = {}) {
console.log(size, cords, radius);
// do some chart drawing
}
// In Firefox, default values for destructuring assignments are not
yet implemented (as described below).
// The workaround is to write the parameters in the following way:
// ({size: size = 'big', cords: cords = { x: 0, y: 0 }, radius:
radius = 25} = {})
drawES6Chart({
cords: { x: 18, y: 30 },
radius: 30
});
Setting a function
parameter's default value
Take really care with
Browser compatibility!
Default, Rest + Spread
...
We won´t have to do
function(valor) {
value = value ||
"foo";
}
anymore...now:
//ES6
function(value = "foo")
{...};
(Default) Callee-evaluated default parameter values.
function f(x, y=12) {
// y is 12 if not passed (or passed as undefined)
return x + y;
}
f(3) == 15
(Rest) Turn an array into consecutive arguments in a function call.function f(x, ...y) {
// y is an Array
return x * y.length;
}
f(3, "hello", true) == 6
(Spread) allows an expression to be expanded in places where multiple
arguments are expected.function f(x, y, z) {
return x + y + z;
}
//ES5
f.apply(null,[1,2,3]);
// Pass each elem of array as argument
f(...[1,2,3]) == 6
Iterators
for (let … in ...){
...
}
//over an Array
let iterable = [10, 20, 30];
for (let value of iterable) {
console.log(value);
}
//over a Map
let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (let entry of iterable) {
console.log(entry);
}
// [a, 1]
// [b, 2]
// [c, 3]
for (let [key, value] of iterable) {
console.log(value);
}
var iterable = {
[Symbol.iterator]() {
return {
i: 0,
next() {
if (this.i < 3) {
return { value: this.i++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (var value of iterable) {
console.log(value);
}
// 0
// 1
// 2
Iteration is based on
these duck-typed
interfaces (using
TypeScript type
syntax for exposition
only) so...
We can also iterate
over an Iterable
Object
The for...in loop will iterate
over all enumerable
properties of an object.
The for...of syntax is specific
to collections, rather than all
objects. It will iterate in this
manner over the elements of
any collection that has a
[Symbol.iterator] property.
Difference between for...of and for...inObject.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};
let iterable = [3, 5, 7];
iterable.foo = "hello";
for (let i in iterable) {
console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}
for (let i of iterable) {
console.log(i); // logs 3, 5, 7
Wanna go deeper?Check Generators!
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Re
ference/Iteration_protocols
Classes
class X extends Y {
}
This is how a Class
looks like in new ES6
class TechnicalBook extends Book {
constructor(theme, pages) {
super(theme, pages);
this.caps = [];
this.price = "";
// ...
}
method() {
// ...
}
_privateMethod() {
// ...
}
}
Modules
import * from modules/*
//File: lib/person.js
module "person" {
export function hello(name) {
return name;
}
}
//File: app.js
import { hello } from "person";
var app = {
foo: function() {
hello("Mike");
}
}
export app;
This is like browserfy
native.
We can import
functions from others
scripts with no need
to import scripts from
the HTML
Map + Set + WeakMap + WeakSet
// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;
// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;
// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size === undefined
WeakMap.prototype.get(key) : anyWeakMap.prototype.set(key, value) : thisWeakMap.prototype.has(key) : booleanWeakMap.prototype.delete(key) : boolean// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });
// Because the added object has no other references,
it will not be held in the set
WeakSet.prototype.add(value)WeakSet.prototype.has(value)WeakSet.prototype.delete(value)
Primitive data types as keys are not allowed
A WeakMap is a map (dictionary) where the keys are weak - that is, if all references to the key are lost and there are no more references to the value - the value can be garbage collected
We can’t iterate over the contents
No clear method!
When to use what?
http://stackoverflow.com/questions/29413222/what-are-the-
actual-uses-of-es6-weakmap
Promises
//promise implementationfunction readFile(filename, enc){ return new Promise(function (fulfill, reject){ fs.readFile(filename, enc, function (err, res){ if (err) reject(err); else fulfill(res); }); });}
//using the promisefunction readJSON(filename){ return readFile(filename, 'utf8').then(function (res){ return JSON.parse(res) })}
https://www.promisejs.org
What more…?Proxies
Proxies enable creation of objects with the full range of behaviors available to host objects. Can be used for interception, object virtualization, logging/profiling, etc.
Symbols
Symbols allow properties to be keyed by either string (as in ES5) orsymbol
Subclassable Built-ins
In ES6, built-ins like Array, Date and DOM Elements can be subclassed.
What more…?Math + Number + String + Array + Object APIs
Many new library additions, including core Math libraries, Array conversion helpers, String helpers, and Object.assign for copying.
Reflect API Full reflection API exposing the runtime-level
meta-operations on objects. This is effectively the inverse of the Proxy API, and allows making calls corresponding to the same meta-operations as the proxy traps. Especially useful for implementing proxies.
Tail Calls Calls in tail-position are guaranteed to not grow the stack
unboundedly. Makes recursive algorithms safe in the face of unbounded inputs.
Thanks!
migueloop.github.io