"JavaScript in 2016" by Eduard Tomàs
Some years ago in a far far away company, Brendan Eich created JavaScript. A lot of things happened since then. Times changed, the web grown, the language itself was updated, and we as a developers need to adapt too. Last year the last standard of the language arose: ECMAScript 2015 is here, and has some new and interesting features. In this talk we will show the most relevant ones, and also we will introduce some interesting patterns that you can use in JavaScript: you'll learn how to master the language and made JavaScript your best ally to conquest the world!
6. • About JavaScript
• How it was
• How it is now
• How it will be in the (near) future
What i will talk about?
7. No excuses to not use ES2015 now
Most features
already implemented
in modern browsers
For everything else…
Babel
8. • Invented 20 years ago (1995) by Brendan Eich (in
Netscape) for using mainly as a scripting Language
• Currently in version 6 (this is the version we will
talking about)
• Version 6 is from 2015
• Previous version 5 is from 2009
• A lot of people still don’t use all version 5 features!
A bit of history...
9. • Getters and Setters
• strict mode
• Reflection
Underused v5 features
10. • A lot of new features...
• Three groups of features
• Minor improvements (mostly syntax sugar)
• New Language core features
• Other features
ECMAScript 2015 (aka v6)
11. • A lot of new features...
• Three groups of features
• Minor improvements (mostly syntax sugar)
• String interpolation, arrow functions, binary and octal literals, block
scope, enhanced object notation, new types (map, set, typed arrays)
• New Language core features
• Symbols, Iterators and generators, destructuring, classes
• Other features
• Promises, Modules, Proxies
ECMAScript 2015 (aka v6)
12. • A lot of new features...
• Three groups of features
• Minor improvements (mostly syntax sugar)
• String interpolation, arrow functions, binary and octal literals, block
scope, enhanced object notation, new types (map, set, typed arrays)
• New Language core features
• Symbols, Iterators and generators, destructuring, classes
• Other features
• Promises, Modules, Proxies
ECMAScript 2015 (aka v6)
15. • A new, compact and cleaner syntax for creating a
function
Arrow Functions
function (i) {
return i*2;
}
i => i*2
• Very compact, easy to read
16. • A new, compact and cleaner syntax for creating a
function
• And they come with a gift: arrow operator preserves
context!
Arrow Functions
var Brewery = function(name) {
this.name = name;
this.beers = [];
this.getBeersWithFullName = function() {
return this.beers.map(function(element) {
return {
name: element.name + " by " + this.name,
style: element.style};
});
}
}
17. • A new, compact and cleaner syntax for creating a
function
• And they come with a gift: arrow operator preserves
context!
Arrow Functions
var Brewery = function(name) {
this.name = name;
this.beers = [];
this.getBeersWithFullName = function() {
return this.beers.map(function(element) {
return {
name: element.name + " by " + this.name,
style: element.style};
}.bind(this));
}
}
18. • A new, compact and cleaner syntax for creating a
function
• And they come with a gift: arrow operator preserves
context!
Arrow Functions
var Brewery = function(name) {
this.name = name;
this.beers = [];
this.getBeersWithFullName = function () {
return this.beers.map(e => ({
name: e.name + " by " + this.name,
style: e.style
}));
}
}
19.
20. But be aware...
var x = {
nick: '1. eiximenis',
identify: () => console.log('I am ' + this.nick)
}
x.identify();
var X = function () {
this.nick = '2. eiximenis';
this.identify = () => console.log('I am ' + this.nick)
}
new X().identify();
21. • Pipe operator – Only syntax, but matters!
Maybe in the (near) future (ES7)...
function doubleSay(str) {
return str + ", " + str;
}
function capitalize(str) {
return str[0].toUpperCase() +
str.substring(1);
}
function exclaim(str) {
return str + '!';
}
let result = exclaim(capitalize(doubleSay("hello"))); // Hello, hello!
let result = "hello"|> doubleSay |> capitalize |> exclaim;
22.
23. Destructuring
• You have an array with two values.
• How to assign these two values to two independent
variables?
var values = [42, 69];
var x = 42;
var y = 69;
var values = [42, 69];
var [x,y] = values;
24. • Works with objects too
Destructuring
let obj = {a:10, b: 30, c:'Hello'};
let {a:x, c:y} = obj;
• Very easy to extract partial info of an object
let user= {
name:'eiximenis',
beers:[{id: 1, name: 'Moretti'},
{id: 2, name: 'Epidor'}],
city: 'Igualada'
};
let {name, beers: [,epidor]} = user;
25. • A very powerful operator that maps to “the rest
values of an iterable”
• Key concept is “rest” (only values not yet iterated are
apped to the array)
Spread operator
var lost = [4, 8, 15, 16, 23, 42];
var [,eight,fifteen,...others] = lost;
26. • Spread operator also maps an array to a N arguments
in a function
• A new fresh way to call functions from arrays without
need for apply
• In fact is far more powerful than apply...
Spread operator
let foo = function (a, b, c, d, e) { }
foo(10, ...[20, 30], 40, ...[50]);
27. • Last parameter of function can be prepended with
spread operator
• This parameter will contain an array with all extra
parameters passed to this function
Rest parameters
• It is like arguments but better...
• It is really an array
• Only contains non-named parameters
var foo = function (a, b, ...c) { }
foo(1, 1, 2, 3, 5);
29. • An iterator enables custom iteration over an object
• Is a function that returns an object (the iterator)
• Name of this function is Symbol.iterator
• Only one iterator per object
• Iterators are lazy, evaluated as values are needed
• Any object with an iterator is an iterable and
• Can be iterated using for...of
• Spread operator can map the object to an array
Iterators
30. • It’s a bit cumbersone...
Need to declare Symbol.iterator as a function that
returns an object
with only one function
called next that returns
an object
with two properties
value (the current value)
done (true if iteration finished)
Creating an iterator
31. Creating an iterator
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1;
return {
next() {
[pre, cur] = [cur, pre + cur];
return { done: false, value: cur }
}
}
}
}
for (var n of fibonacci) {
if (n > 1000)
break;
console.log(n);
}
32.
33. Generating iterators
for (var n of fibonacci) {
if (n > 1000)
break;
console.log(n);
}
var fibonacci = {
[Symbol.iterator]: function*() {
let pre = 0, cur = 1;
for (;;) {
[pre, cur] = [cur, pre + cur];
yield cur;
}
}
}
34. • Generators can be objects by themselves
• Can create a function that is a generator and iterate
over its values
Generators
function* lost() {
yield 4;
yield 8;
yield 15;
yield 16;
yield 23;
yield 42;
}
[...lost()];
35. • A generator can yield all values of another generator
using yield*
Chaining generators
function* lostrange(limit) {
for (let idx=0; idx<limit;idx++) {
yield idx;
yield* lost();
}
}
var lost = function* () {
yield 4;
yield 8;
yield 15;
yield 16;
yield 23;
yield 42;
}
36. • but classes allow some specific features unavailable in ES5, so...
37. • Objects must be created with new and classes do not
exist in runtime (typeof Point is ‘function’)
• This is equivalent to ES5 constructor pattern
Classes – The basics
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
38. • Properties (using the same ES5 get/set syntax)
• Inheritance (class Point3D extends Point)
• Prototype of Point3D objects will be a Point object
• Static methods
• Classes define the constructor pseudo-method
(invoked when object is creatred).
• Derived constructors must call base to call the base
constructor before using this
• But still...
Classes – The basics
40. • By defining all methods inside constructor as closures
(ES5 way to do this)
Faking classes private methods
class SimpleDay {
constructor(day) {
let _day = day;
this.getDay = function () {
return _day;
}
}
}
41. • By using Symbols to hide names
Faking classes private methods
let SimpleDay = (function () {
let _dayKey = Symbol();
class SimpleDay {
constructor(day) {
this[_dayKey] = day;
}
getDay() {
return this[_dayKey];
}
}
return SimpleDay;
}());
42. • By using Weak Map (preferred way)
Faking classes private methods
let SimpleDay = (function () {
let _days = new WeakMap();
class SimpleDay {
constructor(day) {
_days.set(this, day);
}
getDay() {
return _days.get(this);
}
}
return SimpleDay;
}());
43. • By using Weak Map (preferred way)
Faking classes private methods
let SimpleDay = (function () {
let _days = new WeakMap();
class SimpleDay {
constructor(day) {
_days.set(this, day);
}
getDay() {
return _days.get(this);
}
}
return SimpleDay;
}());
• External function can be avoided if using modules
44. • A function can return or receive a class
• This gives us an standard way of creating mixins
• Suppose a hierarchy of classes:
Classes are 1st class-citizens
class BarClass {
bar() {
console.log('Bar from BarClass');
}
}
class BazClass extends BarClass {
baz() {
console.log('Baz from BazClass');
}
}
45. Classes are 1st class-citizens
• We can declare a mixin:
let FooMixin = (sc) => class extends sc {
foo() {
console.log('FooMixin method');
}
}
• And apply it...
class BazFooClass extends FooMixin(BazClass) { }
var bfc = new BazFooClass();
bfc.bar(); // from superclass BarClass
bfc.baz(); // from bazclass
bfc.foo(); // from mixin
47. • Similar to CommonJS modules because
• Compact syntax
• Prefer single export
• Support for cyclic dependences
• Similar to AMD modules because
• Support for asynchronous module loading
• Configurable module loading
Modules ES6
48. 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));
}
Any declaration prefixed by
“export” keyword is an export of
the module
Using import keyword we can
choose what of the exports of
the module we want to include
to the global namespace
//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
49. Importing into namespace
//------ 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));
}
Any declaration prefixed by
“export” keyword is an export of
the module
You can, of course, specify a
namespace for the import, keeping
the global namespace clean
//------ main.js ------
import * as lib from 'lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(4, 3)); // 5
Did you notice the use of * to import all the exports of a module?
50. Default export
Module exports a class (note the use
of default).
Default exports must be named on
import
Module exports just a function
//------ MyClass.js ------
export default class { ... };
//------ main2.js ------
import MyClass from 'MyClass';
let inst = new MyClass();
//------ myFunc.js ------
export default function () { ... };
//------ main1.js ------
import myFunc from 'myFunc';
myFunc();
• Mean to be the “most important” export
• Represents “the module” itself
51. • A module can have one default and so many named
exports
Default and named exports
Module ‘react-native’has so
many named exports (i. e.
Image, Text) and also has the
default export.
Default export is the most
important and represents
“the core of react”
This is a common pattern in JS (think about jQuery)
52. Modules
• Modules are statically defined and imported.
CommonJS allows for:
This is not allowed in ES6
Less flexibility but no need to execute the
code to find the imports or exports of a
module. Can be optimized.
var mylib;
if (Math.random()) {
mylib = require('foo');
} else {
mylib = require('bar');
}
54. • No more callbacks needed
• Promise encapsulates the task and its State (pending,
fulfilled or error found)
• Allows execution of code after its fulfillment or after
an error is found
• Can be chained
Promises – the basics
57. Promises - usage
var pxhr = xhrget('http://www.plainconcepts.com/');
pxhr.then(function (req) {
console.log(req.responseText);
});
pxhr.catch(function(err) {
console.log('Oooops!');
});
• Assume xhrget is a function that returns a Promise for
loading a URL using GET
61. Promises - creating
var xhrget = function (url) {
var pr = new Promise(function (resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url, true);
req.onreadystatechange = function () {
if (req.readyState == XMLHttpRequest.DONE) {
if (req.status == 200) {
resolve(req);
}
else {
reject(new Error("Err " + req.status));
}
}
};
req.send(null);
});
return pr;
}
62. • Support for asynchronous will be in the core language
through async/await
• await -> a non-blocking wait over a promise. When an
await is found, code returns to its caller and when the
promise is fulfilled, the execution re-enters and
continues after the await
In the (near) future (ES7)...
(async function() {
doSomeSynchronousStuff();
await loadStoryAsync();
console.log("Done!");
}());
• Something similar could be done with ES6 with
promises and generators combined
63. • Develop using ES6
• Take a look on ES7 proposals!!!!
• Learn about reactive way to do things and even reactive
extensions
• New frameworks and libs (Flux/Redux/Cyclejs but also Angular2)
are heavy based on this.
• Invest in TypeScript or flow if you would like to have static
typing in ES
• Learn some funcional language, it will help you as JS is
everyday more functional
What to look next?
65. Thanks!
ROME 18-19 MARCH 2016
Eduard Tomàs - @eiximenis
Plain Concepts
http://www.plainconcepts.com
All pictures belong
to their respective authors