Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
JS Funcional NANDO VIEIRA // @fnando
Slide 2
Slide 2 text
Nando Vieira
Slide 3
Slide 3 text
http://hellobits.com
Slide 4
Slide 4 text
howto. http://howto.io
Slide 5
Slide 5 text
http://codeplane.com.br
Slide 6
Slide 6 text
* * *
Slide 7
Slide 7 text
O JS não é uma linguagem nova
Slide 8
Slide 8 text
VS Programação Imperativa Funcional
Slide 9
Slide 9 text
Programação Funcional
Slide 10
Slide 10 text
O poder do JS está nas funções
Slide 11
Slide 11 text
function add(a, b) { return a + b; }
Slide 12
Slide 12 text
Função é apenas um tipo de objeto
Slide 13
Slide 13 text
Você pode definir uma função e atribuir a uma variável.
Slide 14
Slide 14 text
var add = function(a, b) { return a + b; };
Slide 15
Slide 15 text
Você pode executar uma função e retornar uma função.
Slide 16
Slide 16 text
function adder(a) { return function(b) { return a + b; }; }
Slide 17
Slide 17 text
var plus2 = adder(2); plus2(3); // 5 plus2(5); // 7
Slide 18
Slide 18 text
Você pode passar funções como argumentos de uma função.
Slide 19
Slide 19 text
var button = document.querySelector(".button"); ! button.addEventListener("click", function(event){ // Do whatever... });
Slide 20
Slide 20 text
Você pode definir funções dentro de outras funções.
Slide 21
Slide 21 text
function A() { function B() { console.log("B executed"); } ! console.log("A executed"); B(); } ! A(); // A executed // B executed
Slide 22
Slide 22 text
O JavaScript possui muitas características de linguagens funcionais.
Slide 23
Slide 23 text
E isso permite usar muitos patterns interessantes.
Slide 24
Slide 24 text
Um pouco sobre Loops
Slide 25
Slide 25 text
Loops são usados para causar efeito colateral.
Slide 26
Slide 26 text
var numbers = [1, 2, 3, 4, 5]; ! for (var i = 0; i < numbers.length; i++) { console.log(numbers[i]); }
Slide 27
Slide 27 text
Loops são usados para transformar os dados de uma lista.
Slide 28
Slide 28 text
var users = [ {name: "John Doe"} , {name: "Mary Doe"} ]; var names = []; ! for (var i = 0; i < users.length; i++) { names.push(users[i].name); }
Slide 29
Slide 29 text
Loops são usados para agregar dados de uma lista.
Slide 30
Slide 30 text
var sales = [{revenue: 1000}, {revenue: 2000}]; var totalSales = 0; ! for (var i = 0; i < sales.length; i++) { totalSales += sales[i].revenue; }
Slide 31
Slide 31 text
Loops são usados para filtrar dados de uma lista.
Slide 32
Slide 32 text
var users = [{age: 24}, {age: 45}, {age: 13}]; var allowedToDrink = []; ! for (var i = 0; i < users.length; i++) { if (users[i].age >= 18) { allowedToDrink.push(users[i]); } }
Slide 33
Slide 33 text
Loops imperativos focam a lógica do loop.
Slide 34
Slide 34 text
No JavaScript temos outras alternativas.
Slide 35
Slide 35 text
Array#forEach foca no efeito colateral.
Slide 36
Slide 36 text
var numbers = [1, 2, 3, 4, 5]; ! numbers.forEach(function(number){ console.log(number); });
Slide 37
Slide 37 text
Array#map foca na transformação.
Slide 38
Slide 38 text
var users = [ {name: "John Doe"} , {name: "Mary Doe"} ]; ! var names = users.map(function(user){ return user.name; });
Slide 39
Slide 39 text
Transformar arrays é uma tarefa recorrente.
Slide 40
Slide 40 text
Podemos simplificar com uma função que extrai propriedades.
Slide 41
Slide 41 text
function attr(name) { return function(object) { return object[name]; }; }
Slide 42
Slide 42 text
var users = [ {name: "John Doe"} , {name: "Mary Doe"} ]; ! var names = users.map(attr("name"));
Slide 43
Slide 43 text
Array#filter foca no filtro da lista.
Slide 44
Slide 44 text
var users = [{age: 24}, {age: 45}, {age: 13}]; ! var allowedToDrink = users.filter(function(user){ return user.age >= 18; });
Slide 45
Slide 45 text
Array#reduce foca na agregação da lista.
Slide 46
Slide 46 text
var sales = [{revenue: 1000}, {revenue: 2000}]; var revenues = sales.map(attr("revenue")); ! var totalSales = sales.reduce(function(buffer, revenue){ return revenue + buffer; }, 0);
Slide 47
Slide 47 text
A função de agregação já foi usada antes.
Slide 48
Slide 48 text
function(buffer, revenue){ return revenue + buffer; }
Slide 49
Slide 49 text
function add(a, b) { return a + b; }
Slide 50
Slide 50 text
Juntando todos os pedaços fica mais simples
Slide 51
Slide 51 text
var sales = [{revenue: 1000}, {revenue: 2000}]; var totalSales = sales .map(attr("revenue")) .reduce(add, 0) ;
Slide 52
Slide 52 text
Exemplo Dada uma lista de pessoas, ordene-a pelo nome e renderize cada item como um conteúdo HTML.
Slide 53
Slide 53 text
Lista Apenas um array de objetos.
Slide 54
Slide 54 text
var users = [ {name: "John Doe", age: 42} , {name: "Mary Doe", age: 37} , {name: "Eddie Doe", age: 24} ];
Slide 55
Slide 55 text
Ordenação Utilize a função Array#sort
Slide 56
Slide 56 text
var ordered = users.sort(function(a, b){ return (a.name < b.name ? -1 : 1); });
Slide 57
Slide 57 text
Renderização Crie uma função que lida com essa abstração.
Slide 58
Slide 58 text
function UserView(user) { this.user = user; } ! UserView.prototype.render = function() { return "" + this.user.name + "" + "" + this.user.age + "" ; };
Slide 59
Slide 59 text
Agregação Transforme a lista em um resultado agregado.
Slide 60
Slide 60 text
var html = ""; var view; ! for (var i = 0; i < ordered.length; i++) { view = new UserView(ordered[i]); html += view.render(); }
Slide 61
Slide 61 text
Primeira Solução
Slide 62
Slide 62 text
function UserView(user) { this.user = user; } ! UserView.prototype.render = function() { return "" + this.user.name + "" + "" + this.user.age + ""; }; ! var ordered = users.sort(function(a, b){ return (a.name < b.name ? -1 : 1); }); ! var html = ""; var view; ! for (var i = 0; i < ordered.length; i++) { view = new UserView(ordered[i]); html += view.render(); }
Slide 63
Slide 63 text
Segunda Solução
Slide 64
Slide 64 text
function UserView(user) { this.user = user; } ! UserView.prototype.render = function() { return "" + this.user.name + "" + "" + this.user.age + ""; }; ! var html = users .sort(function(a, b){ return a.name > b.name ? 1 : -1; }) .map(function(user){ return new UserView(user); }) .map(function(view){ return view.render(); }) .join("\n") ;
Slide 65
Slide 65 text
Extraia padrões
Slide 66
Slide 66 text
function asc(attribute) { return function(a, b) { return a[attribute] > b[attribute] ? 1 : -1; }; } ! function desc(attribute) { return function(a, b) { return a[attribute] > b[attribute] ? -1 : 1; }; } ! users.sort(asc("name"));
Slide 67
Slide 67 text
function wrapWith(constructor) { return function(object) { return new constructor(object); }; } ! users.map(wrapWith(UserView));
Slide 68
Slide 68 text
function call(funcName) { return function(object) { return object[funcName].call(object); }; } ! views.map(call("render"));
Slide 69
Slide 69 text
users .sort(asc("name")) .map(wrapWith(UserView)) .map(call("render")) .join("\n") ;
Slide 70
Slide 70 text
Performance importa!
Slide 71
Slide 71 text
for-loop functional pure functions DOM 0 300,000 600,000 900,000 1,200,000 37,543 193,477 204,795 1,105,783 Ops/second (maior é melhor) http://fnando.me/10i
Slide 72
Slide 72 text
Performance importa?
Slide 73
Slide 73 text
Function Composition pode ajudar! (mas não sempre)
Slide 74
Slide 74 text
compose(a, b, c);
Slide 75
Slide 75 text
a(b(c()));
Slide 76
Slide 76 text
var callRender = call("render"); var wrapView = wrapWith(UserView); var render = compose(callRender, wrapView); ! users .sort(asc("name")) .map(render) .join("\n") ;
Slide 77
Slide 77 text
compose(callRender, wrapView)(user); ! ! callRender(wrapView(user)); é equivalente a
Slide 78
Slide 78 text
Ferramentas que podem ajudar e inspirar
Slide 79
Slide 79 text
http://fnando.me/10o
Slide 80
Slide 80 text
http://fnando.me/10n
Slide 81
Slide 81 text
http://fnando.me/10r
Slide 82
Slide 82 text
http://fnando.me/10s
Slide 83
Slide 83 text
http://fnando.me/10p
Slide 84
Slide 84 text
http://fnando.me/10q
Slide 85
Slide 85 text
Aprenda Programação Funcional
Slide 86
Slide 86 text
http://fnando.me/10j http://fnando.me/10k
Slide 87
Slide 87 text
http://fnando.me/10l
Slide 88
Slide 88 text
http://fnando.me/10m
Slide 89
Slide 89 text
http://fnando.me/10t
Slide 90
Slide 90 text
Finalizando
Slide 91
Slide 91 text
Prefira funções puras
Slide 92
Slide 92 text
Prefira abstrações genéricas
Slide 93
Slide 93 text
Prefira abstrações menores
Slide 94
Slide 94 text
Conheça outros paradigmas
Slide 95
Slide 95 text
Mais uma técnica no seu arsenal.
Slide 96
Slide 96 text
“Às vezes a implementação mais elegante é uma função. Não é um método. Não é uma classe. Não é um framework. É apenas uma função. — John Carmack
Slide 97
Slide 97 text
Obrigado! @fnando