Paradigmas no
JavaScript
evolução e 

futuro do uso de
jcemer.com
github.com/jcemer
twitter.com/jcemer
speakerdeck.com/jcemer
porto alegre
talentos.globo.com
Assim como a maioria das
linguagens, o JavaScript
atende a uma série de
paradigmas
Existe confusão e falta de
entendimento de como os
paradigmas funcionam e se
relacionam
Esta é uma palestra
avançada (e extensa) sobre
programação e JavaScript
Programando
de maneira
imperativa
Solução baseada em uma
sequência de passos
<SCRIPT>
var visits = getCookie("counter");
if (visits) {
visits = parseInt(visits) + 1;
document.write("By the way, you have been here " + visits + 

" times.");
}
else {
visits = 1;
document.write("By the way, this is your first time here.");
}
setCookie("counter", visits);
</SCRIPT>
http://www.sislands.com/coin70/week7/counter.htm
if e else
<SCRIPT>
// Use single-spaced text for Multiplication table
document.write("<CENTER><BLOCKQUOTE><STRONG><PRE><FONT COLOR='FF0000'">)
var i, j, total; // global variables
for (i = 1; i <= 10; i++) {
for (j = 1; j < 10; j++) {
total = i * j;
total = " " + total //add space before each number
// Add another space before single digits
if (total < 10) total = " " + total;
// Display result
document.write(total);
} // end inner j loop
document.write("<BR>"); // end of line break
} // end of i outer loop
document.write("</FONT></PRE></STRONG></BLOCKQUOTE></CENTER>");
</SCRIPT>
http://www.sislands.com/coin70/week2/NestedLoops1.htm
foooorr
Código que explicitamente
altera o estado e fluxo de
execução do programa
Difícil de manter, reusar e
evoluir
REQ HTML
CLICK
JSO
N
G
EN
E
ADD
JSON
CLICK
UE
RATE
ST
O surgimento de
tecnologias foi essencial
para o aperfeiçoamento do
uso de paradigmas
A comunidade foi o
principal agente
Orientando a
objetos com
protótipos
Solução baseada em um
conjunto de objetos e troca
de mensagens entre eles
Prototype.js
a saudosa
var Person = Class.create({
initialize: function(name) {
this.name = name
},
say: function(message) {
return this.name + ': ' + message
}
})
var Pirate = Class.create(Person, {
say: function($super, message) {
return $super(message) + ', yarr!'
}
})
http://prototypejs.org/learn/class-inheritance
herança
Objetos são instâncias de
um construtor e mantêm
estado
Todo construtor deve
possuir uma única
responsabilidade
Single responsibility
principle
http://www.infoq.com/br/news/2014/02/solid-principios-javascript
Até mesmo as tarefas mais
simples eram complexas
utilizando Web APIs
Abstrações
Orientando a objetos com
protótipos
new Ajax.Request('/some_url', {
method:'get',
onSuccess: function(transport) {
var response = transport.responseText
alert("Success! nn" + response)
},
onFailure: function() {
alert('Something went wrong...')
}
})
http://prototypejs.org/learn/introduction-to-ajax
getTransport: function() {
return Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
) || false
}
Código fonte da versão 1.7.2.0 da Prototype.js
Operação interna
do Request
Abstrações servem para
isolar a complexidade de
uma operação
Abstrações normalizam e
delegam operações
Em alguns casos parecia
mais fácil estender
if (!document.getElementsByClassName) 

document.getElementsByClassName = function(instanceMethods){
Código fonte da versão 1.7.2.0 da Prototype.js
Object.extend(Function.prototype, (function() {
var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :
Element.prototype;
Estender document
Estender construtor de função
Estender objetos do DOM
DOM extension is one of the
biggest mistakes Prototype.js has
ever done.
http://perfectionkills.com/whats-wrong-with-extending-the-dom
- Kangax
Modificar objetos que não
pertencem ao seu código
não é uma boa prática
https://www.nczonline.net/blog/2010/03/02/maintainable-javascript-
dont-modify-objects-you-down-own
jQuery
a unipresente
$('li').hide()
http://jqfundamentals.com/chapter/jquery-basics
jQuery possui as mesmas
operações da Prototype.js
implementas da maneira
correta
Encadeando
operações
Orientando a objetos 

com protótipos
$('li')
.click(function () {
$(this).addClass('clicked')
})
.find('span')
.attr('title', 'Hover over me')
http://jqfundamentals.com/chapter/jquery-basics
Encadeamento permite
executar uma série de
operações em um
mesmo objeto
A biblioteca padrão do
JavaScript é pobre e
obscura
Aprimorando a
biblioteca
padrão
Orientando a objetos 

com protótipos
Underscore.js
a útil
var toString = Object.prototype.toString
toString.call("Oops") == "[object String]"
_.isString("Opps")
Com underscore.js
- keys
- allKeys
- values
- mapObject
- pairs
- invert
- create
- functions
- findKey
- extend
- extendOwn
- pick
- omit
- defaults
- clone
- tap
- has
- property
- propertyOf
- isEqual
- isMatch
- isEmpty
- isElement
- isArray
- isObject
- isArguments
- isFunction
- isString
- isNumber
- isFinite
- isBoolean
- isDate
- isRegExp
- isNaN
- isUndefined
- noConflict
- identity
- constant
- noop
- times
- random
- mixin
- iteratee
- uniqueId
- escape
- unescape
- result
- now
- template
- isNull
- matcher
Operações utilitárias 

são essenciais para um
código mais legível
Invariavelmente seus
projetos enfrentarão os
mesmos problemas
Código
modularizado
Orientando a objetos 

com protótipos
Módulos separam porções
de código que possuem
algo em comum
Módulos são coesos,
desacoplados e reusáveis
Lodash
a modular
var methods = ['Arguments', 'Function',
'String', 'Number', 'Date',
'RegExp', 'Error'];
_.each(methods, function(name) {
_['is' + name] = function(obj) {
return toString.call(obj) ===
'[object ' + name + ']';
};
});
underscore.js
var isObjectLike = require('./isObjectLike');
var stringTag = '[object String]';
var objectProto = global.Object.prototype;
var objToString = objectProto.toString;
function isString(value) {
return typeof value == 'string' || 

(isObjectLike(value) 

&& objToString.call(value) == stringTag);
}
module.exports = isString;
lang/isString.js
var isObjectLike = require('./isObjectLike');
var numberTag = '[object Number]';
var objectProto = global.Object.prototype;
var objToString = objectProto.toString;
function isNumber(value) {
return typeof value == 'number' ||
(isObjectLike(value)
&& objToString.call(value) == numberTag);
}
module.exports = isNumber;
lang/isNumber.js
DEPENDÊNCIA DUPLICAÇÃO
VS
A manutenção do equilíbrio,
reduzindo a duplicação

David Chelimsky 

https://www.youtube.com/watch?v=ugTQF2uw9eg
O importante é definir bem o
critério de modularização
JavaScript suporta diferentes
padrões de módulos,
escolha um
http://eloquentjavascript.net/10_modules.html
Programando
de maneira
funcional
Solução baseada em
transformação de valores
https://smthngsmwhr.wordpress.com/2014/02/02/eloquent-javascript-
with-underscore-js
First-class functions movem o
JavaScript significativamente
em direção a FP
Funções podem ser
passadas e retornados por
outras funções
First-class functions
Underscore.js
a funcional
_.reduce(collection, function(a, b) {
return a + b
})
_.filter(collection, function(n) {
return (n % 2) === 0
})
Livro: Introducing Functional Programming with Underscore.js
Construções funcionais são
mais fáceis de ler e manter
array.forEach(iteratee)
array.map(iteratee)
array.reduce(iteratee, memo)
array.every(predicate)
array.find(predicate)
array.includes(element)
[...arguments]
Object.keys(object)
https://www.reindex.io/blog/you-might-not-need-underscore
ES 5.1 + ES2015 + ES2016
Ausência de estado
compartilhado, funções que
não geram efeito colateral
Funções puras
Programação funcional vai
muito além de manipulação
de coleções
var mult = function (a, b) { return a * b }
var negate = _.partial(mult, -1)
var mult2 = _.partial(mult, 2)
var square = function (n) { return n * n }
var result = _.compose(negate, mult2, square)
export default store => next => action => {
// [...]
}
https://github.com/rackt/redux/blob/master/examples/real-world/
middleware/api.js
export default function (store) {
return function (next) {
return function (action) {
}
}
}
Portando para ES 5.1
Código original
http://documentcloud.github.io/underscore-contrib#curry
_.curry(function (store, next, action) {
// [...]
})
Underscore-contrib
Funções precisam aceitar e
retornar dados imutáveis
// frozen value type
const xy = #[ x, y ]
// functional extension
const xyz = #[ ...xy, z ]
https://github.com/sebmarkbage/ecmascript-immutable-data-structures
Mas nem tudo está disponível:
é preciso aprender a esperar
por operações assíncronas
getFiles('.', function (files) {
generateIndex(files, function () {
generatePosts(files, ready)
})
})
Funções que geram um blog
Programação funcional é
sobre valores e suas
relações
https://blog.jcoglan.com/2013/03/30/callbacks-are-imperative-
promises-are-functional-nodes-biggest-missed-opportunity
Utilizando
Promises
Programando de maneira 

funcional
Promises são valores que
representam o possível
resultado de uma operação
assíncrona
http://tableless.com.br/fluxo-de-execucao-assincrono-em-
javascript-promises
https://blog.jcoglan.com/2011/03/11/promises-are-the-monad-of-
asynchronous-programming
pipe([getFiles, generateIndex, generatePosts])
Promises are the monad of
asynchronous programming
http://tableless.com.br/fluxo-de-execucao-assincrono-em-javascript-
promises
blogParser.start()
.then(getFiles)
.then(generateIndex)
.then(generatePosts)
Utilizando Promises/A+
Interfaces basicamente
reagem a eventos vindos do
usuário e servidor
Programando
orientado a
eventos
Solução guiada pela
ocorrência de eventos
externos
Web APIs são massivamente
apoiadas no paradigma de
eventos
Backbone.js
o organizado
Backbone.js faz seus dados
funcionarem igual ao DOM:
emitindo eventos
Apresentar palestra
na RubyConf
var TaskView = Backbone.View.extend({
events: {
'click [data-check]': 'done'
},
done: function (event) {
this.model.set({done: true})
},
initialize: function () {
this.listenTo(this.model, 'change', this.render)
},
render: function () {
// build task HTML
}
})
var TaskView = Backbone.View.extend({
events: {
'click [data-check]': 'done'
},
done: function (event) {
this.model.set({done: true})
},
initialize: function () {
this.listenTo(this.model, 'change', this.render)
},
render: function () {
// build task HTML
}
})
var TaskView = Backbone.View.extend({
events: {
'click [data-check]': 'done'
},
done: function (event) {
this.model.set({done: true})
},
initialize: function () {
this.listenTo(this.model, 'change', this.render)
},
render: function () {
// build task HTML
}
})
O DOM não é performático
quando aplicamos
modificações a revelia
var TaskView = Backbone.View.extend({
//...
initialize: function () {
this.listenTo(this.model,
'change:done', this.renderStatus)
},
renderStatus: function () {
var done = this.model.get('done') ? 'ok' : ''
this.$('[data-status]').text(text)
}
});
Neste cenário é que o 

data-binding fez rir e
chorar
data
$scope.Field = "data"
Data-binding
$scope.Field = "data"
Two-way data-binding
data
AngularJS
o benevolente
<div ng-controller="TaskCtrl" ng-click="change()">
<span>{{ done ? 'Ok' : '' }}</span>
{{ description }}
</div>
app.controller('TaskCtrl', function($scope) {
$scope.description = 'My task'
$scope.change = function () {
$scope.done = true
}
})
HTML?
JavaScript
http://leoasis.github.io/posts/2014/10/28/think-twice-or-thrice-
before-using-angular
http://tutorials.jenkov.com/angularjs/critique.html
https://medium.com/@mnemon1ck/why-you-should-not-use-
angularjs-1df5ddf6fc99
Think Twice (or Thrice)
Before Using Angular
React.JS
o vanguardista
var Task = React.createClass({
getInitialState: function () {
return {done: false}
},
render: function () {
return <div onClick={this.change}>
{this.state.done ? 'Ok' : ''}
{this.props.description}</div>
},
change: function () {
this.setState({done: true})
}
})
React.render(<Task description='My task' />,
document.body)
XML?!
var Task = React.createClass({
getInitialState: function () {
return {done: false}
},
render: function () {
return <div onClick={this.change}>
{this.state.done ? 'Ok' : ''}
{this.props.description}</div>
},
change: function () {
this.setState({done: true})
}
})
React.render(<Task description='My task' />,
document.body)
var Task = React.createClass({
getInitialState: function () {
return {done: false}
},
render: function () {
return <div onClick={this.change}>
{this.state.done ? 'Ok' : ''}
{this.props.description}</div>
},
change: function () {
this.setState({done: true})
}
})
React.render(<Task description='My task' />,
document.body)
Estado
Manipular e manter o histórico
dos estados do DOM é difícil. A
solução é escrever código como
se você recriasse o DOM toda
vez que o estado muda
https://github.com/Matt-Esch/virtual-dom
Já existe um esquema
gratuito para o fluxo dos
dados: O DOM
http://www.code-experience.com/why-you-might-not-need-mvc-with-
reactjs/
(os eventos e CSS já utilizam)
Componentes mantêm estado
e recebem propriedades dos
seus ancestrais
Set state Dirty Re-render
React Components
http://calendar.perfplanet.com/2013/diff/
var newTree = render(data)
var patches = diff(tree, newTree)
rootNode = patch(rootNode, patches)
tree = newTree
Patch!
Virtual DOM
https://github.com/Matt-Esch/virtual-dom
React.js♥
Ainda precisamos lidar
com eventos a todo tempo
instant search
var onType = _.debounce(function() {
$.get('data.json')
}, 300)
Buscar depois de 300ms de
inatividade
var onType = _.debounce(function() {
$.get('data.json')
}, 300)
Buscar depois de 300ms de
inatividade
ZzzZzzZz...
E se as request não
retornarem na ordem?!
Programando
de maneira
funcional
reativa
Solução guiada por streams
de dados assíncronos
Stream é uma sequência de
eventos ordenados no
tempo
var text = $('#input')
.asEventStream('keydown')
.debounce(300)
.map(function(event) {
return event.target.value
})
https://baconjs.github.io
instant search
text BACO NJS
Debonced 300ms
var text = $('#input')
.asEventStream('keydown')
.debounce(300)
.map(function(event) {
return event.target.value
})
function movieSearch(query) {
return Bacon.fromPromise(queryMovie(query))}
text.flatMap(movieSearch)
.onValue(function(results) {
console.log(results)
})
text BACO NJS
Query BACO
Query BACONJS
Request para a nuvem
text
results
BACO NJS
Query BACO
Query BACONJS
Ops
var text = $('#input')
.asEventStream('keydown')
.debounce(300)
.map(function(event) {
return event.target.value
})
function movieSearch(query) {
return Bacon.fromPromise(queryMovie(query))}
text.flatMapLatest(movieSearch)
.onValue(function(results) {
console.log(results)
})
latest
text
results
BACO NJS
Query BACO
Query BACONJS
x
http://nullzzz.blogspot.com.br/2012/12/baconjs-tutorial-part-iii-ajax-and-stuff.html
FRP é sobre relações
dependentes que se estabilizam
com o passar do tempo
https://www.zweitag.de/en/blog/technology/functional-reactive-
programming-frp
Conhecer paradigmas e
práticas vai além de sair
implementando em projetos
Compreender contextos e
aplicar as soluções mais
adequadas é o mais
importante
só, por favor, 

não usem o
maldito ;
@jcemer
Obrigado

Evolução e futuro do uso de paradigmas no JavaScript