Saiba todas as features que te ajudarão a produzir sistemas mais rapidamente.
Se quiser contribuir com JavaScript, siga essas práticas
O pattern utilizado por nós é o Revealing Module Pattern.
As principais vantagens de manter este padrão são:
A ideia é que o código mantenha unidade, seja ele escrito por uma ou várias pessoas, dentro de um projeto e entre projetos diferentes, diminuindo o tempo de aprendizado.
As regras a seguir propoem um padrão mínimo para desenvolvimento. O mais importante é manter a consistência de estilo de código. O que for escolhido como estilo para o seu projeto deverá ser seguido em todos os arquivos.
Identação: utilizamos 2 espaços, mas o mais importante é seguir um estilo único. Nunca misture espaços e tabs em único arquivo. Para facilitar incluímos no projeto um arquivo de configuraçao de editores, o ".editorconfig", saiba mais sobre ele em editorconfig.org
Existem plugins para vários editores, no nosso time usamos:
Sintaxe: para separaçao dos blocos de código, utilizamos o estilo1TBS, por exemplo:
1
2
3
4
5
if ( x < 0 ) {
console.log( x )
} else {
console.log( y )
}
Observe os alinhamentos, quebras de linhas, posição das chaves e espaços entre variáveis e operadores.
Para melhorar a organização dos arquivos, funções, performance e diminuir a chance de erros e conflitos, adotamos o Revealing Module Pattern do Christian Heilmann .
As vantagens desse pattern são: organização, clareza, performance, expõe publicamente apenas as funções e variáveis que se deseja e namespace único evitando sobrescrever métodos facilmente.
Leia mais sobre ele no livro do Addy Osmani.
Um exemplo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Define o objeto global do projeto, igual a um já existente ou cria um novo objeto.
var projeto = projeto || {};
// Define o módulo no objeto global.
projeto.moduloUm = (function() {
'use strict';
function iniciar() {
interno();
// ...
}
function atualizar() {
// ...
}
function interno() {
// ...
}
return {
iniciar:iniciar,
atualizar: atualizar
};
}());
Todos os scripts do Locaweb Style são modularizados ao máximo. Só iniciamos um comportamento se ele precisar ser usado. Todos os módulos ou os triggers destes módulos, terão um atributo data-ls-module="#"
que avisará o Locaweb Style para iniciar o módulo determinado. Para citar alguns exemplos: data-ls-module="modal"
, data-ls-module="collapse"
e data-ls-module="tabs"
O ideal é ter um módulo por arquivo, e que eles não se iniciem sozinhos.
Um módulo central que funcione como controlador de quais serão executados é uma boa prática.
Abaixo, colocamos três exemplos de módulos e como eles são carregados:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var projeto = projeto || {};
projeto.Grafico = (function() {
'use strict';
function iniciar() {
inserirGrafico();
}
function inserirGrafico() {
// ...
}
return {
iniciar:iniciar
};
}());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var projeto = projeto || {};
projeto.Servidores = (function() {
'use strict';
function iniciar() {
buscaServidores();
}
function buscaServidores() {
insereListaServidores()
// ...
}
return {
iniciar:iniciar
};
}());
Finalmente o arquivo que controla quando cada módulo será executado, da maneira que preferir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var projeto = projeto || {};
projeto.carregaModulos = (function($) {
'use strict';
function inicio() {
if ( $('.grafico').size() ) {
projeto.graficos.inicio();
}
if ( window.location.pathname === '/servidores' ) {
projeto.servidores.inicio();
}
}
return {
inicio:inicio
};
}(jQuery));
projeto.carregaModulos.inicio();
Para facilitar a manutençao e a legibilidade do código, procure usar apenas um idioma, em nomes de funções, variáveis e comentários.
O mais importante é seguir um padrão, mantendo ele do início ao fim do projeto. Exceções, claro, são libraries e plugins que utilizados.
Seja qual for a língua utilizada é importante ser claro, utilizando nomes descritivos, evitando ser prolixo nos nomes, funções e comentários, como abordado no tópico Seja compreensível abaixo.
Ao utilizar "use strict"; no início de códigos ou funções, declara-se uma mudança na sintaxe do Javascript, que lança mais exceções mostrando problemas no código. Os erros mais comuns são uso de palavras reservadas do javascript (ECMAScript 5 e 6), uso de variáveis não declaradas e uso de funções descontinuadas.
Para utilizar, basta inserir a string 'use strict'; antes do bloco de código a ser avaliado ou função. Exemplos:
1
2
3
4
5
6
7
"use strict";
idade = 17; // lança um erro de referência
function soma(a, b, c) { // erro de sintaxe
"use strict";
return a + b + c; // exibe o erro se a função é chamada
}
Leia mais em MDN - Strict mode
Um projeto pode ter muitos arquivos javascript, então é importante que estejam bem organizados desde o início, separados e bem nomeados.
A estrutura pode variar muito de projeto para projeto, mas as recomendações mínimas são:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
── javascripts
├── libs
│ ├── jquery.min.js
│ └── underscore.min.js
│ └── highcharts.min.js
├── plugins
│ ├── jquery.validate-1.2.js
│ ├── jquery.slider-3.1.js
│ └── jquery.validate.addicional-methods-0.8.js
├── modules
│ ├── charts
│ | ├── servers.js
│ | └── transfer.js
│ ├── servers.js
│ └── servers.forms.js
├── utils.js
└── main.js
Use nomes de variáveis e funções auto explicativos e simples. Crie algum padrão e mantenha em todo o projeto.
No Locastyle utilizamos variáveis e funções camelCase, pela facilidade de leitura, escrita e praticidade ao se trabalhar.
Exemplos:
1
2
3
4
5
6
7
8
// Curtos, posicionamento no código e abreviações
var x1;
var campo1;
var latXY;
// Longos demais
var valorEixoXGraficoConsumo;
var campoTextoPrimeiroNome;
1
2
3
4
5
6
7
8
// Nomes que descrevem o código, nao o objetivo da função
function maiorDeDezoitoAnos(idade){
return idade >= 18;
}
// É melhor descrever o objetivo
function possuiMaioridade(idade){
return idade >= 18;
}
1
2
3
4
5
6
7
8
9
10
// Variáveis com $ no início são elementos/objetos jQuery
var $header = $('#header');
var $menuItens = $('#menu a');
// Maiúsculas para constantes
var PASTA_IMAGENS = '/assets/images/';
var NOME_CLIENTE = 'Fulano de Tal';
// _ no início para variáveis e funções privadas
var _contador = 0;
Confira o padrão de nomenclatura do Douglas Crockford
No geral é uma péssima idéia, porque aumenta a chance de ter algo sobrescrito. Uma opção é utilizar closures e module pattern.
É possível escrever seu código de muitas maneiras, mas procure manter o mesmo estilo em todo seu projeto. Mantendo um padrão nos nomes, identacões, patterns, etc.
Uma dica, utilize o jslint para validar seu código.
É comum ouvir "Um bom código não precisa de explicação", mas na prática em projetos maiores, procure explicar a finalidade do seu código. Muitas pessoas, de diferentes níveis, podem ter que trabalhar no seu código e nem sempre elas tem experiência, tempo ou conhecimento do negócio para entender tudo. Facilite o desenvolvimento e manutenção comentando, mas não explicando o que ele faz, mas qual a regra de negócio.
Exemplo:
1
2
3
// Ruim: verifica se é maior de 18
// Bom: menores de idade são redirecionados
if( idade >= 18 ){ ... }
Lembrando que comentários devem existir apenas na versão de desenvolvimento, devendo ser removidos no arquivo minificado que é entregue em produção.
Utilizamos Jasmine para testar o Locaweb Style, assim como os comentários, é uma ótima forma de explicar o que seu código faz ou deveria fazer. Além de ter o dispositivo de alerta quando algum teste quebra, dá mais segurança para manutenções e inclusão de novas funcionalidades.
Na prática do dia a dia, algo bem simples: estilize seu HTML com CSS, não com JS.
1
2
3
4
5
6
7
// Errado
$('#nome-usuario').css({
'border': '1px solid red',
'color': 'red'
});
// Certo
$('#nome-usuario').addClass('erro');
Crie os estilos que precisar (e animações, quando possível) no CSS, e no javascript controle quando os estilos são aplicados, em vez de aplicar propriedades.
Outro ponto importante é seguir a jQuery. Eu sei que você vai querer escrever JavaScript puro em alguns momentos. Mas isso complica a leitura do código e sai totalmente do padrão inicial definido que é usar a abstração da jQuery. Por isso, use sempre os comandos da jQuery.
Conheça as notações de variáveis e funções abreviadas e procure usá-las.
Exemplo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Use
var cores = ['rosa', 'azul', 'verde'];
// Em vez de
var cores = new Array();
cores[0]='rosa';
cores[1]='azul';
cores[2]='verde';
// Use
var margem = altura || 10;
// Em vez de
if(altura === undefined){
var margem = altura;
} else {
var margem = 10;
}
// Use
var direcao = (x > 100) ? 1 : -1;
// Em vez de
var direcao;
if(x > 100){
direcao = 1;
} else {
direcao = -1;
}
Evite escrever funções, trechos de código muito longos, ou aninhados. Procure separar regras e evite códigos repetidos.
Exemplo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Em vez de
$('#botao1').on('click', function(){
$('#resultado').load('ajax/lista-pessoas.html', function() {
$('#formulario').slideUp()
});
})
$('#botao2').on('click', function(){
$('#resultado').load('ajax/lista-empresas.html', function() {
$('#formulario').slideUp()
});
})
//...
// Faça
function ocultaFormulario(){
$('#formulario').slideUp();
}
$('#botao1').on('click', function(){
$('#resultado').load('ajax/lista-pessoas.html', function() {
ocultaFormulario();
});
})
$('#botao2').on('click', function(){
$('#resultado').load('ajax/lista-empresas.html', function() {
ocultaFormulario();
});
})
// Ou melhor
function ocultaFormulario(){
$('#formulario').slideUp();
}
function carregaDados( elemento, url){
$(elemento).on('click', function(){
$('#resultado').load(url, function() {
ocultaFormulario();
});
})
}
carregaDados('#botao1', 'ajax/lista-pessoas.html');
carregaDados('#botao2', 'ajax/lista-empresas.html');
Facilite o entendimento e manutençao dos seus códigos. Utilize as práticas anteriores e evite um código do tipo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$('#botao').on('click', function(){
$.ajax({
type: "POST",
url: 'usuarios',
success: function(data){
$('resultado').fadeIn('fast', function(){
$('#formulario').animate({
heigth : 0,
opacity: 0
}, 300, function(){
$('#mensagem').animate({
heigth : 200,
opacity: 1
}, 300, function(){
// ...
})
}
)
})
},
error: function(){
$('#mensagem').text(mensageErro);
}
});
});
Existem várias maneiras de fazer loops, uma melhores que outras. Hoje, comum encontrar códigos usando loops do jquery ($.each) onde loops nativos poderiam resolver. Uma técnica simples para melhorar ainda mais os loops for() nativos é fazer cache de variáveis de comparação, evitando executar o .length a cada iteração.
Exemplo:
1
2
3
4
5
6
7
8
9
10
11
// Use
var cores = ['Azul', 'verde', 'rosa', 'vermelho'];
for(var indice = 0, quantCores = cores.length; indice < quantCores; indice++){ //
console.log( cores[indice] );
}
// em vez de
var cores = ['Azul', 'verde', 'rosa', 'vermelho'];
for(var indice = 0; indice < cores.length; indice++){
console.log( cores[indice]) ;
}
Para comparação, um teste de performance no jsperf analisando diversos tipos de loop. O loop otimizado, como acima, executou 159k vezes, contra 113k vezes do tradicional.
Evite ao máximo acessar o DOM para buscar ou inserir informações. É lento e não se pode confiar no que está no DOM. Coisas simples podem minimizar o acesso, por exemplo, se alguma função precisa atualizar uma tabela no seu HTML, em vez de percorrer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Em vez de
$('#botaoEnviar').on( 'click', function(){
$(this).prop( 'disabled', true );
$('$formulario').addClass( 'enviando' );
$.post( 'ajax/contato', function( dados ) {
$('#mensagem').html( dados );
$('$formulario').removeClass( 'enviando' );
$('#botaoEnviar').prop( 'disabled', false );
});
});
// Faça
var $botaoEnviar = $('#botaoEnviar');
var $formulario = $('#formulario');
var $mensagem = $('#mensagem');
$botaoEnviar.on( 'click', function(){
$botaoEnviar.prop( 'disabled', true );
$formulario.addClass( 'enviando' );
$.post('ajax/contato', function( dados ) {
$mensagem.html( dados );
$formulario.removeClass( 'enviando' );
$botaoEnviar.prop( 'disabled', false );
});
});