código limpo e eficiente com javascript
DESCRIPTION
Palestra de 9/11/2011 do DotNetFloripaTRANSCRIPT
DotNetFloripa – 9/11/2011 Rodrigo Vieira
@rodbv 1
Wednesday, November 09, 2011 2
Um pouco de história Tipos de dados Funções Escopo, closures Objetos Encapsulamento Dicas e erros comuns
4
Mocha! LiveScript!
Brendan Eich Scheme
Linguagem dinâmica, fracamente tipada, funcional e OO
Objetos e arrays são dicionários “melhorados”
Não precisa ser compilada, em geral roda dentro de um “host”
Variáveis globais amarram diferentes componentes
Herança por prototipação
Wednesday, November 09, 2011 5
Java + script
DOM
AJAX , XmlHttpRequest
jQuery Wednesday, November 09, 2011 6
Valor String, Number, Boolean, null, undefined
Referência Objetos
Funções
Arrays
RegEx
Date
Math
Wednesday, November 09, 2011 7
Sequência de caracteres unicode
Strings com mesmo valor são consideradas idênticas
Não existe tipo char
Podemos usar aspas simples e duplas
Possui métodos
Wednesday, November 09, 2011 8
Ponto flutuante de 64 bits Não existe tipo inteiro NaN Infinity Hexa (0xa12) Notação científica (1.23e-8) Octal: primeiro dígito zero, cuidado!
parseInt(‚08‛) //0
parseInt(‚08‛, 10) //8
Wednesday, November 09, 2011 9
null: objeto nulo, atribuído explicitamente
undefined: valor padrão para variáveis,
parâmetros e atributos sem valor atribuído
Wednesday, November 09, 2011 10
true false
Wednesday, November 09, 2011 11
Os seguintes valores são avaliados como false quando fazem partes de expressões booleanas (falsy):
0
‚‛
null
undefined
NaN
Todo o resto é avaliado como true (truthy)
inclusive as strings ‛false‛ e ‛0‛!
Wednesday, November 09, 2011 12
d = new Date(); //data atual
d = new Date (88500); //ms desde 1.1.1970
d = new Date(2011, 10, 9);
Wednesday, November 09, 2011 13
Não são arrays de verdade, mas um dicionário com chaves numéricas
Não dá erro de limite
var a = new Array(); //oldskool var a = []; var a = [1, ‚a‛, obj]; //inline
a.push(‚floripa‛); a.length; //4
Wednesday, November 09, 2011 14
Wednesday, November 09, 2011 15
var r = new RegExp(‚\\w{1,3}\\d{2}‛, ‚gim‛);
var r = /\w{1,3}\d{2}/gim;
r.test(‚ab12‛); //true ‚abc12xyz‛.replace(/\w{1,3}/gim, ‚‛); //12xyz
Wednesday, November 09, 2011 16
O coração de programação decente em JS
Cidadãs de primeira classe
Uma função pode ser:
▪ Variável
▪ Parâmetro
▪ Propriedade de objeto
▪ Anônima
▪ Retorno de outra função
▪ Interna a outra função
Wednesday, November 09, 2011 17
Declaração comum
function fala(texto) {
alert(‚Fala,‛ + texto + ‚!‛);
}
fala(‚amigo‛); //Fala,amigo!
Wednesday, November 09, 2011 18
Variável com função anônima
var fala = function(texto) { alert(‚Fala,‛ + texto + ‚!‛); }; fala(‚amigo‛); //Fala,amigo!
Wednesday, November 09, 2011 19
function geraSoma (x) { return function(num) { return x + num; } } var soma5 = geraSoma(5); soma5(3); //8
Wednesday, November 09, 2011 20
function geraSoma (x) { return function(num) { return x + num; } } var soma5 = geraSoma(5); soma5(3); //8
Wednesday, November 09, 2011 21
Closure
function executa(func) { func(); } function dizOi() { alert(‚oi!‛); } executa(dizOi); //oi!
Wednesday, November 09, 2011 22
executa(function() { alert(‘oi’);}); //oi!
Wednesday, November 09, 2011 23
function soma(x,y) { return x + y; } soma(2,3); //5 soma(2,‛5‛) //‛25‛
Wednesday, November 09, 2011 24
function soma(x,y) { return x + y; } soma(2,3,5,‛hello‛); //5 soma(2); //NaN
Wednesday, November 09, 2011 25
Coleção de argumentos passado para a função
function soma() {
var total=0;
for (var i=0; i<arguments.length; i++) {
total += arguments[i];
}
return total; } soma(1,2,3,4,5); //15
Wednesday, November 09, 2011 26
JavaScript possui apenas 2 blocos de escopo Global
Função
Variável declarada dentro de função, com “var”, é local
Função declarada dentro de função é local
Variáveis declaradas dentro de blocos if, while, for etc não são locais ao bloco, e sim à função.
Wednesday, November 09, 2011 27
Esse código é feio, mas é válido
function calculaMedia(x,y){
soma = fazSoma();
return soma/2;
function fazSoma() {
return x + y;
}
var soma;
}
Wednesday, November 09, 2011 28
function calculaMedia(x,y){
soma = x + y;
return soma/2;
}
calculaMedia(2,3); //5
alert(soma); //5
Wednesday, November 09, 2011 29
Variável global
Um dicionário enfeitado
Wednesday, November 09, 2011 30
Clássica var ator = new Object(); ator.nome = ‚Jim‛; ator.sobrenome = ‚Parsons‛;
Simplificada
var ator = {}; ator.nome = ‚Jim‛;
ator.sobrenome = ‚Parsons‛;
Inline var ator = { nome: ‚Jim‛, sobrenome: ‚Parsons‛ };
Wednesday, November 09, 2011 31
var ator = {
nome: ‚Jim‛,
sobrenome: ‚Parsons‛,
nomeCompleto: function() {
return this.nome + ‚ ‛ + this.sobrenome;
} }; ator.nomeCompleto(); //Jim Parsons
Wednesday, November 09, 2011 32
function Ator(nome, sobrenome){ this.nome = nome; this.sobrenome = sobrenome; this.nomeCompleto = function() { return this.nome + ‚ ‛ + this.sobrenome; }; } var jim = new Ator(‚Jim‛, ‚Parsons‛); jim.nomeCompleto(); //Jim Parsons
Convenciona-se usar inicial maiúscula Wednesday, November 09, 2011 33
function Ator(nome, sobrenome){ var ator = {} ; ator.sobrenome = sobrenome; ator.nomeCompleto = function() { return ator.nome + ‚ ‛ + ator.sobrenome; }; return ator; } var jim = new Ator(‚Jim‛, ‚Parsons‛); jim.nomeCompleto(); //Jim Parsons
Wednesday, November 09, 2011 34
carro.marca = ‚Citroen‛;
carro[‚placa‛] = ‚MHJ8832‛;
A segunda forma aceita palavras reservadas, símbolos etc
carro[‚#‛] = ‚dummy‛;
carro[‚for‛] = ‚yammy‛;
Wednesday, November 09, 2011 35
Permitem executar uma função especificando qual objeto será o “this”
Wednesday, November 09, 2011 36
function setStyle(color, border){ this.style.backgroundColor = color; this.style.borderColor = border; } var botao1 = document.getElementById(‚botao1‛); var botao2 = document.getElementById(‚botao2‛); setColors.call(botao1, ‚red‛, ‚blue‛); setColors.call(botao2, ‚blue‛, ‚green‛);
Wednesday, November 09, 2011 37
“this”
function setStyle(color, border){ this.style.backgroundColor = color; this.style.borderColor = border; } var botao1 = document.getElementById(‚botao1‛); var botao2 = document.getElementById(‚botao2‛); setColors.apply(botao1, [‚red‛, ‚blue‛]); setColors.apply(botao2, arguments);
Wednesday, November 09, 2011 38
“this”
Como funções são objetos, elas podem ter atributos – isso evita variáveis globais
Wednesday, November 09, 2011 39
function executaUmaVez() { if (executaUmaVez.jaExecutou) { return; } //executa a funcao alert(‘oeeee’); executaUmaVez.jaExecutou = true; } executaUmaVez(); //oeeee executaUmaVez(); //Não executa
Wednesday, November 09, 2011 40
function ehPrimo(x) { if (!ehPrimo.cache) { ehPrimo.cache = {}; } if (!ehPrimo.cache[x]) { ehPrimo.cache[x] = … //calcula a parada } return ehPrimo.cache[x]; }
Wednesday, November 09, 2011 41
function ehPrimo(x) { if (!ehPrimo.cache) { ehPrimo.cache = {}; } if (!ehPrimo.cache[x]) { ehPrimo.cache[x] = … //calcula a parada } return ehPrimo.cache[x]; }
Quiz: por que eu usei um objeto e não um array no memo?
Wednesday, November 09, 2011 42
Usando método construtor
function MeuModulo(p1,p2) { //privado var x = p1, y = p2; function funcaoPrivada() { //… } //público this.valor1 = x + y; this.funcaoPublica = function() { return funcaoPrivada(x,y); }; } var m = new MeuModulo(1,2); alert(m.valor1); //3
Wednesday, November 09, 2011 43
Usando função
function meuModulo(p1,p2) { //privado var x = p1, y = p2; function fazAlgumaCoisa() { //… } //público return { valor1: x + y, funcaoPublica: function() { return fazAlgumaCoisa(x,y); } }; } var m = meuModulo(1,2); alert(m.valor1); //3
Wednesday, November 09, 2011 44
Declare todas variáveis e funções no topo da função (já que o escopo é esse mesmo…) function minhaFuncao() {
var x = 1,
z = ‚a‛;
function() { … }
//resto do código
}
Wednesday, November 09, 2011 45
function soma(x,y) {
return
x + y;
}
soma(2,3); //undefined
Wednesday, November 09, 2011 46
Ponto-e-vírgula é opcional, mas o js coloca pra você na hora de rodar
function soma(x,y) {
return;
x + y;
}
soma(2,3); //undefined
Wednesday, November 09, 2011 47
Pra quebrar linha, use “pontuação”
function soma(x,y) {
return x +
y;
}
soma(2,3); //5
Wednesday, November 09, 2011 48
Caso você queira usar uma variável global, use MAIÚSCULAS (assim todos sabem que foi por querer)
E, melhor ainda, crie “namespaces” para suas variáveis e funções globais var DOTNETFLORIPA = {};
DOTNETFLORIPA.usuario = ‚rodbv‛;
DOTNETFLORIPA.quebraTudo = function() {…};
Wednesday, November 09, 2011 49
Executando código descartável
(function() {
/* todas variáveis e funções declaradas aqui têm acesso ao escopo global,
mas sairão de escopo quando a
função terminar de ser executada */
})();
Wednesday, November 09, 2011 50
Use === e !==
Wednesday, November 09, 2011 51
1 == ‚1‛ //true 1 === ‚1‛ //false
0 == false //true 0 === false //false
‚‛ == 0 //true ‚‛ === 0 //false
1 != true //false 1!== true //true
Lembre-se do “var” no for loop
function minhaFuncao() {
for (i = 0; i < 10; i++){
//…
} } alert(i) //10;
Wednesday, November 09, 2011 52
Cuidado com o seguinte padrão
function minhaFuncao() {
var a = b = 10;
} minhaFuncao();
alert(a); //undefined, beleza
alert(b); //10 ?!?
Wednesday, November 09, 2011 53
Cuidado com o seguinte padrão
function minhaFuncao() {
var a = b = 10;
} minhaFuncao();
alert(a); //undefined, beleza
alert(b); //10 ?!?
Wednesday, November 09, 2011 54
Evite eval setTimeout(‚alert(‘ola’);‛, 10);
setTimeout(function() { alert(‘ola’);}, 10);
var p = eval(‚ator.‛ + propr);
var p = ator[propr];
Wednesday, November 09, 2011 55
Coloque o seu javascript sempre no fundo da página
Minifique e combine os arquivos
<script type="text/javascript" src="http://yui.yahooapis.com/combo?2.9.0/build/utilities/utilities.js&2.9.0/build/datasource/datasource-min.js&2.9.0/build/autocomplete/autocomplete-min.js&2.9.0/build/calendar/calendar-min.js&2.9.0/build/tabview/tabview-min.js"></script>
Wednesday, November 09, 2011 56
Wednesday, November 09, 2011 57
Douglas Crockford é o cara http://javascript.crockford.com/
@rodbv [email protected]
Wednesday, November 09, 2011 58