BreizhCamp 2015
#BzhCmp
#ES6Today #BzhCmp
BreizhCamp 2015
#BzhCmp
Architecte Web, passionné par le Front-End
Co-Fondateur de @RennesJS
#ES6Today #BzhCmp
BreizhCamp 2015
#BzhCmp
#ES6Today #BzhCmp
Meetup le dernier jeudi de chaque mois
25/06/2015 à Epitech
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
Langage transpilé en Javascript créé fin 2009 par Jérémy Ashkenas (créateur de Backbone et Underscore).
#ES6Today #BzhCmp
Plateforme basée sur le moteur Javascript V8 de Chrome créé en 2009
#ES6Today #BzhCmp
#ES6Today #BzhCmp
Parser
Transformer
Generator
Convertit le code Javascript en AST
Manipule l'AST
Convertit l'AST en Javascript
#ES6Today #BzhCmp
{
type: "Program",
body: [{
type: "VariableDeclaration",
kind: "var",
declarations: [{
type: "VariableDeclarator",
id: { type: "Identifier", name: "foo" },
params: [],
body: [{
type: "BlockStatement",
body: [{
type: "ReturnStatement",
argument: { type: "Identifier", name: "bar" }
}]
}]
}]
}]
}
AST
var foo = function foo() {
return bar;
};
ES5
AST: Abstract Synthax Tree
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
# ProTip™ .bashrc
export PATH=$PATH:./node_modules/.bin
# Installation locale
npm install babel -S
# Transpiler vos sources ES6 en ES5
babel src/main.js -o dist/main.js
# Executer vos sources ES6
babel-node src/server.js
CLI
#ES6Today #BzhCmp
# Install dependencies
npm i -S browserify babelify watchify
# Browserify + debug
browserify src/main.js -t babelify --debug --outfile dist/bundle.js
# Watching
watchify src/main.js -t babelify --debug --outfile dist/bundle.js
CLI
Démo
#ES6Today #BzhCmp
Question de timing on ne verra pas tout ...
#ES6Today #BzhCmp
#ES6Today #BzhCmp
class Talk {
constructor(date, subject) {
this.date = date;
this.subject = subject;
}
getDate() {
return this.date;
}
getSubject() {
return this.subject;
}
static isValid(talk) {
return null !== talk.subject;
}
}
function Talk(date, subject) {
this.date = date;
this.subject = subject;
}
Talk.prototype.getDate = function getDate() {
return this.date;
};
Talk.prototype.getSubject = function getSubject() {
return this.subject;
};
Talk.isValid = function isValid(talk) {
return null !== talk.subject;
};
ES6
ES5
#ES6Today #BzhCmp
class JsTalk extends Talk {
constructor(date) {
super(date, 'JS');
}
}
ES6
function _extends(child, parent) {
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
return child;
}
function JsTalk() {
Talk.prototype.constructor.call(this, Date.now(), 'JS');
}
_extends(JsTalk, Talk);
ES3
function JsTalk() {
Talk.prototype.constructor.call(this, Date.now(), 'JS');
}
JsTalk.prototype = Object.create(Talk.prototype);
ES5
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
// Verbose
var getTitle = (item) => {
return item.title;
};
// Implicit return
var getTitle = (item) => item.title;
// Optional parenthesis
var getTitle = item => item.title;
ES6
#ES6Today #BzhCmp
function clicker(node) {
this.counter = 0;
node.addEventListener((event) => {
// Lexical binding sur le context parent
++this.counter;
arguments[0] === event; // false
arguments[0] === node; // true
});
}
ES6
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
// ./controller/home.js
export default class HomeController {
...
}
// ./main.js
import HomeController from './controller/home.js';
ES6
#ES6Today #BzhCmp
// ./utils.js
export function mixin() {
...
}
export const API_VERSION = 1;
// ./main.js
import * as utils from './utils';
utils.API_VERSION; // 1
ES6
#ES6Today #BzhCmp
// ./utils.js
function mixin() {
...
}
const API_VERSION = 1;
// Une instruction pour les exporter tous
export { mixin, API_VERSION };
ES6
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
// Template simple
function text(messages) {
return `you have ${ messages } message${ messages !== 1 ? `s` : `` }`;
}
// Template avancé
function html(list) {
return `<ul>${list.map((item) => {
return `<li>${item.value}</li>`;
})}</ul>`;
}
ES6
#ES6Today #BzhCmp
// Evaluation
var welcome = `Welcome ${user} at Breizhcamp!`;
// user is not defined
// Multi lines
var multilines =
`Header
Content
Footer`;
ES6
#ES6Today #BzhCmp
ES6
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
function todo() {}
var context = {
// Raccourci
todo,
// Propriété calculée
['uniq' + Date.now()]: 'test',
// Méthode
toString() {
return 'another value';
}
};
ES6
#ES6Today #BzhCmp
#ES6Today #BzhCmp
arguments
#ES6Today #BzhCmp
function log(level, ...messages) {
console.log(`${level} ${messages.length} messages`);
}
log('warn');
//> warn 0 messages
log('debug', 'hello', 'breizhcamp', 2015);
//> debug 3 messages
ES6
#ES6Today #BzhCmp
var args = [
'click',
(event) => { console.log(event); },
false
];
document.addEventListener(...args);
ES6
var args = [
'click',
function (event) { console.log(event); },
false
];
document.addEventListener.apply(document, args);
ES5
#ES6Today #BzhCmp
function img(src, height = 100, width = 100) {
return `<img src="${src}" height="${height}" width="${width}" />`;
}
img('avatar.png');
//> <img src="avatar.png" height="100" width="100" />
img('player.png', 50, 50);
//> <img src="player.png" height="50" width="50" />
ES6
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
// Object Destructuring
var node = document.querySelector('input[type=password]');
var { top, right, left, bottom } = getComputedStyle(node);
// Array Destructuring
var pattern = /(\d\d)\/(\d\d)\/(\d\d\d\d)/;
var value = '07/05/2015';
var [all, day, month, year] = pattern.exec(value);
// ou
var [, day, , year] = pattern.exec(value);
ES6
#ES6Today #BzhCmp
// Object Destructuring
var node = document.querySelector('input[type=password]');
console.log(node)
//> {
name: 'mypassword',
value: '1234',
style: {
top: 0,
...
}
...
}
var { name, value: password, style: { top } } = node;
ES6
var name = node.name;
var password = node.value;
var top = node.style.top;
ES5
#ES6Today #BzhCmp
// Parameters Destructuring + Default
function open({ src, readonly = true}) {
console.log(src, readonly);
}
let src = '/tmp/user.json';
open({src, readonly: false});
//> '/tmp/user.json', false
open({src});
//> '/tmp/user.json', true
ES6
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
function* workflow(initial = 0) {
var step = initial;
console.log('step', step);
yield 'step' + step;
++step;
console.log('step', step);
yield 'step' + step;
}
var w = workflow(1);
w.next(); // {"done":false, "value":"step1"}
w.next(); // {"done":false, "value":"step2"}
w.next(); // {"done":true}
ES6
#ES6Today #BzhCmp
var app = require('koa')();
// x-response-time
app.use(function *(next){
var start = new Date;
yield next;
var ms = new Date - start;
this.set('X-Response-Time', ms + 'ms');
});
// logger
app.use(function *(next){
var start = new Date;
yield next;
var duration = new Date - start;
console.log(`${this.method} ${this.url} - ${duration}`);
});
// response
app.use(function *(){
this.body = 'Hello World';
});
app.listen(3000);
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
if (true) {
let first = 0;
}
console.log(first, second);
//> first is undefined
if (false) {
function test() {}
}
console.log(test);
//> test is undefined
const VERSION = 1.1;
VERSION = 2.0;
//> "VERSION" is read-only
ES6
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp
function after(delay = 1000) {
return new Promise((resolve, reject) => {
setTimeout(resolve, delay);
});
}
after(100).then(() => {
console.log('exectued after 100ms');
});
ES6
#ES6Today #BzhCmp
// Map fonctionne comme un dictionnaire
var map = new Map();
map.set('key', 'value');
// WeakMap permet d'utiliser un objet comme clé
var map = new WeakMap();
var key = new Date();
map.set(key, 'value');
// Set stock uniquement des valeurs
var set = new Set([1, 2, 3, 2, 3, 4]);
set.values()
//> [1, 2, 3, 4]
ES6
#ES6Today #BzhCmp
var Api = (function() {
const secret = Symbol('secret');
const API_SECRET = 'ThisIsSecret';
return class Api {
constructor() {
this[secret] = API_SECRET;
}
static isValid(Api) {
return Api[secret] === API_SECRET;
}
}
}());
var api = new Api();
console.log(Api.isValid(api)); // true
console.log(Api.secret); // undefined
ES6
#ES6Today #BzhCmp
// Proxying a normal object
var target = {};
var handler = {
get: (receiver, name) => {
return `Hello, ${name}!`;
}
};
var p = new Proxy(target, handler);
p.world === "Hello, world!";
// Proxying a function object
var target = function () { return "I am the target"; };
var handler = {
apply: (receiver, ...args) => {
return "I am the proxy";
}
};
var p = new Proxy(target, handler);
p() === "I am the proxy";
ES6
#ES6Today #BzhCmp
#ES6Today #BzhCmp
#ES6Today #BzhCmp