Style Guide baseado no Airbnb JavaScript Style Guide
- Tipos
- Referências
- Objetos
- Arrays
- Destructuring
- Strings
- Funções
- Arrow Functions (Lambdas)
- Construtores
- Módulos
- Iteradores e Geradores
- Propriedades
- Variáveis
- Hoisting
- Operadores
- Blocos
- Comentários
- Whitespace
- Vírgulas
- Ponto e vírgula
- Casting
- Nomes
- Acessores
- Events
- jQuery
- Anotações de Tipo
- Interfaces
- Organização
- Compatibilidade com ECMAScript 5
- ECMAScript 6
- Typescript 1.5
- License
-
1.1 Primitivo: A manipulação de um tipo primitivo é feita diretamente no seu valor.
string
number
boolean
null
undefined
const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
-
1.2 Complexo: A manipulação de um tipo complexo é feito por uma referência para o seu valor.
object
array
function
const foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
- 2.1 Use
const
para todas as suas referências; evite usarvar
.
Isso garante que você não vá reatribuir suas referências (mutação), o que pode levar a bugs e código de difícil compreensão. Com objeto complexos, o
const
não garante a imutabilidade dos valores dos atributos do objeto.
```javascript
// ruim
var a = 1;
var b = 2;
// bom
const a = 1;
const b = 2;
```
- 2.2 Se as referências necessitam ser alteradas, use
let
ao invésvar
.
let
possui escopo de bloco (block-scoped) ao invés do escopo de função (function-scoped) quevar
possui.
```javascript
// ruim
var count = 1;
if (true) {
count += 1;
}
// bom, usando let
let count = 1;
if (true) {
count += 1;
}
```
-
2.3
let
econst
possuem escopo de block (block-scoped). No Typescript, o compilador faz a verificação e emite um erro em tempo de compilação.// const e let existem apenas nos blocos em que foram definidos { let a = 1; const b = 1; } console.log(a); // Erro do TSC console.log(b); // Erro do TSC
-
3.1 Utilize a sintaxe literal para criar um objeto
// ruim const item = new Object(); // bom const item = {};
-
3.2 Não utilize palavras reservadas como nome de atributos. Garante a compatibilidade com versões antigas do IE.
// ruim const superman = { default: { clark: 'kent' }, private: true, }; // bom const superman = { defaults: { clark: 'kent' }, hidden: true, };
-
3.3 Utilize sinônimos legíveis no lugar de palavras reservadas.
// ruim const superman = { class: 'alien', }; // ruim const superman = { klass: 'alien', }; // bom const superman = { type: 'alien', };
- 3.4 Utilize propriedades computadas quando criar objetos com nome dinâmico de propriedade.
Permite que você defina todas as propridades de um objeto em apenas um lugar.
```javascript
const getKey = function(k) {
return `um atributo chamado ${k}`;
}
// ruim
const obj = {
id: 5,
name: 'San Francisco',
};
obj[getKey('enabled')] = true;
// bom
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true,
};
```
-
3.5 Utilize lambdas (arrow functions) ou object-shorthand methods para objetos com métodos ao invés de propriedades ou funções anônimas.
// ruim const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // bom const atom = { value: 1, addValue(value) { return atom.value + value; }, }; // bom const atom = { value: 1, addValue: (value) => atom.value + value };
- 3.6 Utilize a forma reduzida de atribuição de valor.
Maneira mais sucinta e descritiva.
```javascript
const lukeSkywalker = 'Luke Skywalker';
// ruim
const obj = {
lukeSkywalker: lukeSkywalker,
};
// bom
const obj = {
lukeSkywalker,
};
```
- 3.7 Agrupe as atribuições de forma reduzida no começo da declaração do objeto.
Facilita o entendimento das propriedades atribuídas de forma reduzida.
```javascript
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
// ruim
const obj = {
episodeOne: 1,
twoJedisWalkIntoACantina: 2,
lukeSkywalker,
episodeThree: 3,
mayTheFourth: 4,
anakinSkywalker,
};
// bom
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJedisWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
```
-
4.1 Utilize a sintaxe literal para criar arrays.
// ruim const items = new Array(); // bom const items = [];
-
4.2 Utilize Array#push ao invés de atribuição direta para adicionar itens ao array.
const someStack = []; // ruim someStack[someStack.length] = 'abracadabra'; // bom someStack.push('abracadabra');
-
4.3 Utilize array spreads
...
para copiar arrays.// ruim const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // bom const itemsCopy = [...items];
-
4.4 Para converter um objeto array-like para um array, utilize Array#from.
const foo = document.querySelectorAll('.foo'); const nodes = Array.from(foo);
- 5.1 Utilize object destructuring quando é necessário acessar e utilizar múltiplas propriedades de um objeto.
Com destructuring é desnecessário criar referências temporárias para utilizar as propriedades do objeto.
```javascript
// ruim
const getFullName = function(user) {
const firstName = user.firstName;
const lastName = user.lastName;
return `${firstName} ${lastName}`;
}
// bom
const getFullName = function(obj) {
const { firstName, lastName } = obj;
return `${firstName} ${lastName}`;
}
// muito bom
const getFullName = function({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
```
-
5.2 Utilize array destructuring.
const arr = [1, 2, 3, 4]; // ruim const first = arr[0]; const second = arr[1]; // bom const [first, second] = arr;
-
5.3 Utilize object destructuring para múltiplos valores de retorno, não array destructuring.
Você pode adicionar novas propriedades sem quebrar as funções que utilizam o método.
```javascript
// ruim
const processInput = function(input) {
return [left, right, top, bottom];
}
// o caller precisa pensar sobre a ordem dos valores dentro do array
const [left, __, top] = processInput(input);
// bom
const processInput = function(input) {
return { left, right, top, bottom };
}
// o caller seleciona apenas os atributos necessários
const { left, right } = processInput(input);
```
-
6.1 Aspas simples
''
para strings.// ruim const name = "Capt. Janeway"; // bom const name = 'Capt. Janeway';
-
6.2 Strings mais longas que 120 caracteres devem ser escritas em mútiplas linhas.
-
6.3 Nota: Concatenação de strings longas pode causar problemas de performance. jsPerf & Discussion.
// ruim const errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.'; // ruim const errorMessage = 'This is a super long error that was thrown because \ of Batman. When you stop to think about how Batman had anything to do \ with this, you would get nowhere \ fast.'; // bom const errorMessage = 'This is a super long error that was thrown because ' + 'of Batman. When you stop to think about how Batman had anything to do ' + 'with this, you would get nowhere fast.';
- 6.4 Quando construindo strings programaticamente, utilize templates.
Templates são mais legíveis, possuem sintaxe concisa e interpolação.
```javascript
// ruim
const sayHi = function(name) {
return 'Olá ' + name + '.';
}
// ruim
const sayHi = function(name) {
return ['Olá ', name, '.'].join();
}
// bom
const sayHi = function(name) {
return `Olá ${name}.`;
}
```
- 7.1 Declare funções ao invés de criar expressões
Declarações são nomeadas e são mais fáceis de identificar no call stack.
```javascript
// ruim
const foo = function() {
};
// ruim
const foo = () => {
};
// bom
function foo() {
}
```
-
7.2 Expressões:
// immediately-invoked function expression (IIFE) (() => { console.log('Welcome to the Internet. Please follow me.'); })();
-
7.3 Nunca declare a função em um bloco que não seja de função (if, while, etc). Ao invés, atribua a função a uma variável. Browsers interpretam diferentemente esse comportamento.
-
7.4 Nota: ECMA-262 define um
block
como uma lista de comandos. Uma declaração de função não é um comando. Nota ECMA-262.// ruim if (currentUser) { const test = function() { console.log('Nope.'); } } // bom let test; if (currentUser) { test = () => { console.log('Yup.'); }; }
-
7.5 Nunca nomeie um parametro
arguments
. Isso terá precedência em cima doarguments
que é dado para cada escopo de função.// ruim const nope = function(name, options, arguments) { // comandos } // bom const yup = function(name, options, args) { // comandos }
- 7.6 Nunca utilize
arguments
, escolha a sintaxe rest...
.
...
é explicito quanto quais argumentos você deseja utilizar. Argumentos rest estão em um Array, e não em um array-like object como oarguments
.
```javascript
// ruim
const concatenateAll = function() {
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
// bom
const concatenateAll = function(...args) {
return args.join('');
}
```
-
7.7 Utilize a sintaxe de parâmetro default ao invés de alterar argumentos da função.
// muito ruim const handleThings = function(opts) { // não devemos alterar argumentos de função. // se opts é falso será setado para um objeto que talvez introduza bugs opts = opts || {}; // ... } // ruim const handleThings = function(opts) { if (opts === void 0) { opts = {}; } // ... } // bom const handleThings = function(opts = {}) { // ... }
-
7.8 Use parâmetros default com cuidado.
var b = 1;
const count = function(a = b++) {
console.log(a);
}
count(); // 1
count(); // 2
count(3); // 3
count(); // 3
- 7.9 Sempre coloque parâmetros default por último.
// ruim
function createObj(opts = {}, id){
//...
}
// bom
function createObj(id, opts = {}){
//...
}
- 7.10 Nunca use o construtor Function para criar uma função.
Isso deixa o código vulnerável ( eval() );
// ruim
let add = new Function('a','b','return a + b');
- 7.11 Atenção com o espaçamento.
Consistência é bom, e não se deve adicionar ou remover espaços quando adiciona-se ou altera-se um nome.
// ruim
const f = function(){};
const g = function (){};
const h = function() {};
// bom
const x = function () {};
const y = function a() {};
- 8.1 Quando function expressions são necessárias, como por exemplo passando uma função anônima como parâmetro, utilize a sintaxe de arrow.
Se a função for razoávelmente complexa, talvez seja melhor mover essa lógica para uma declaração.
```javascript
// ruim
[1, 2, 3].map(function (x) {
return x * x;
});
// bom
[1, 2, 3].map((x) => {
return x * x;
});
// bom
[1, 2, 3].map((x) => x * x;);
```
- 8.2 Se o corpo da função tiver o tamanho de uma linha e apenas um argumento, é dispensável o uso de parênteses e chaves, e pode ser utilizado o return implícito. Se não, utilize as chaves, parentes e
return
Syntactic sugar. Muito legível.
Não utilize se a função retorna um objeto complexo.
```javascript
// bom
[1, 2, 3].map(x => x * x);
// bom
[1, 2, 3].reduce((total, n) => {
return total + n;
}, 0);
```
- [8.3](#8.3) <a name='8.3'></a> Se a expressão se estender por várias linhas, envolva-a com parênteses para melhor legibilidade.
> Mostra claramente onde a expressão começa e termina.
```javascript
// ruim
[1, 2, 3].map(number => 'As time went by, the string containing the ' +
`${number} became much longer. So we needed to break it over multiple ` +
'lines.'
);
// bom
[1, 2, 3].map(number => (
`As time went by, the string containing the ${number} became much ` +
'longer. So we needed to break it over multiple lines.'
));
```
- [8.4](#8.4) <a = name='8.4"></a> Se a função recebe apenas um argumento, não utilize parênteses.
```javascript
// bom
[1, 2, 3].map(x => x * x);
// bom
[1, 2, 3].reduce((y, x) => x + y);
```
- 9.1 Sempre utilize
class
. Evite manipular oprototype
diretamente.
class
é mais concisa e é mais familiar para C# devs.
```javascript
// ruim
function Queue(contents = []) {
this._queue = [...contents];
}
Queue.prototype.pop = function() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
// bom
class Queue {
constructor(contents = []) {
this._queue = [...contents];
}
pop() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
}
```
- 9.2 Utilize
extends
para herança.
É uma maneira simples de herdar a funcionalidade do prototype sem quebrar
instanceof
.
```javascript
// ruim
const inherits = require('inherits');
function PeekableQueue(contents) {
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function() {
return this._queue[0];
}
// bom
class PeekableQueue extends Queue {
peek() {
return this._queue[0];
}
}
```
-
9.3 Métodos podem retornar
this
para implementar method chaining.// ruim Jedi.prototype.jump = function() { this.jumping = true; return true; }; Jedi.prototype.setHeight = function(height) { this.height = height; }; const luke = new Jedi(); luke.jump(); // => true luke.setHeight(20); // => undefined // bom class Jedi { jump() { this.jumping = true; return this; } setHeight(height) { this.height = height; return this; } } const luke = new Jedi(); luke.jump() .setHeight(20);
-
9.4 É aconselhado reescrever o método toString() se necessário
class Jedi { contructor(options = {}) { this.name = options.name || 'no name'; } getName() { return this.name; } toString() { return `Jedi - ${this.getName()}`; } }
-
10.1 Utilize (
import
/export
) como padrão.// ruim const AirbnbStyleGuide = require('./AirbnbStyleGuide'); module.exports = AirbnbStyleGuide.es6; // bom import AirbnbStyleGuide from './AirbnbStyleGuide'; export default AirbnbStyleGuide.es6; // muito bom - angularjs2 syntax import { es6 } from './AirbnbStyleGuide'; export default es6;
-
10.2 Não
export
diretamente de umimport
.
Ter uma maneira de importar módulos e uma maneira para exportar deixa o código mais consistente.
```javascript
// ruim
// filename es6.js
export { es6 as default } from './airbnbStyleGuide';
// bom
// filename es6.js
import { es6 } from './AirbnbStyleGuide';
export default es6;
```
-
10.3 Não utilize wildcards
// ruim import * as PromobERPCommon from './common'; //bom import PromobERPCommon from './common;'
- 11.1 Evite iteradores. Prefira utilizar funções como
map()
,reduce()
,forEach()
ao invés defor-of
.
Isso fortalece a regra de referências imutáveis.
```javascript
const numbers = [1, 2, 3, 4, 5];
// ruim
let sum = 0;
for (let num of numbers) {
sum += num;
}
sum === 15;
// bom
let sum = 0;
numbers.forEach((num) => sum += num);
sum === 15;
// muito bom
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15;
```
- 11.2 Não utilize geradores por enquanto.
-
12.1 Use notação de ponto para acessar propriedades.
const luke = { jedi: true, age: 28, }; // ruim const isJedi = luke['jedi']; // bom const isJedi = luke.jedi;
-
12.2 Utilize a sintaxe de indexação
[]
em casos raros. Prefira criar uma interface e utilizar a notação de ponto quando possível.const luke = { jedi: true, age: 28, }; const getProp = function(prop) { return luke[prop]; } const isJedi = getProp('jedi');
-
13.1 Sempre utilize
const
/let
para declarar variáveis, dependendendo da necessidade. Prefiraconst
.// ruim superPower = new SuperPower(); // bom const superPower = new SuperPower();
-
13.2 Utilize uma declaração
const
/let
por variável.É mais fácil de ler e adicionar variáveis.
// ruim const items = getItems(), goSportsTeam = true, dragonball = 'z'; // ruim // (encontre o erro :) ) const items = getItems(), goSportsTeam = true; dragonball = 'z'; // bom const items = getItems(); const goSportsTeam = true; const dragonball = 'z';
-
13.3 Agrupe todos seus
const
s e todos seuslet
s.
Ajuda a organizar o código.
```javascript
// ruim
let i, len, dragonball,
items = getItems(),
goSportsTeam = true;
// ruim
let i;
const items = getItems();
let dragonball;
const goSportsTeam = true;
let len;
// bom
const goSportsTeam = true;
const items = getItems();
let dragonball;
let i;
let length;
```
- 13.4 Atribua os valores quando necessário, mas declare as variáveis em lugares sensatos.
Lembre-se:
let
econst
possuem escopo de bloco (block-scoped) e não escopo de função (function-scoped).
```javascript
// bom
function() {
test();
console.log('doing stuff..');
//..other stuff..
const name = getName();
if (name === 'test') {
return false;
}
return name;
}
// ruim - chamada de função desnecessária
function(hasName) {
const name = getName();
if (!hasName) {
return false;
}
this.setFirstName(name);
return true;
}
// bom
function(hasName) {
if (!hasName) {
return false;
}
const name = getName();
this.setFirstName(name);
return true;
}
```
-
14.1 Hoisting é o comportamento padrão do javascript de mover declarações para o topo. Declarações
var
sofrem com isso, mas a atribuição de um valor para uma variávelvar
não sofre. Declaraçõesconst
elet
possuem um conceito chamado Temporal Dead Zones (TDZ). É importante saber que typeof não é seguro.// isso não funcionaria se notDefined não tivesse sido declarada function example() { console.log(notDefined); // => compilador não encontra a variável } // isso funcionaria devido ao hoisting, mas o valor da váriavel não estaria setado function example() { console.log(declaredButNotAssigned); // => undefined var declaredButNotAssigned = true; } // o interpretador está aplicando o hoisting na variável, o exemplo acima poderia ser reescrito dessa maneira: function example() { let declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; } // utilizando const e let function example() { console.log(declaredButNotAssigned); // => Erro do TSC console.log(typeof declaredButNotAssigned); // => Erro do TSC const declaredButNotAssigned = true; }
-
14.2 Funções anônimas sofrem "hoist" da própria variável, mas não a atribuição do corpo da função.
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function() { console.log('anonymous function expression'); }; }
-
14.3 Funções nomeadas que são atribuídas a variáveis sofrem "hoist" do nome da variável, mas não do nome da função nem da implementação da função.
function example() { console.log(named); // => undefined named(); // => TypeError named is not a function superPower(); // => ReferenceError superPower is not defined var named = function superPower() { console.log('Flying'); }; } // o mesmo vale se o nome da função é igual ao nome da variável function example() { console.log(named); // => undefined named(); // => TypeError named is not a function var named = function named() { console.log('named'); } }
-
14.4 Declarações de funções sofrem "hoist" no nome da função e na sua implementação.
function example() { superPower(); // => Flying function superPower() { console.log('Flying'); } }
-
Mais Informações: JavaScript Scoping & Hoisting by Ben Cherry.
-
15.1 SEMPRE utilize
===
e!==
ao invés de==
e!=
. -
15.2 Comandos condicionais como o
if
avaliam a expressão utilizando coercion com o método abstratoToBoolean
e seguem as seguintes regras:- Objects são true
- Undefined é false
- Null é false
- Booleans recebem o valor do booleano
- Numbers são false se +0, -0, ou NaN, senão são true
- Strings são false se é uma string vazia
''
, senão são true
if ([0]) { // true // Array é um objeto, objeto é true }
-
15.3 Utilize atalhos.
// ruim if (name !== '') { // ...stuff... } // bom if (name) { // ...stuff... } // ruim if (collection.length > 0) { // ...stuff... } // bom if (collection.length) { // ...stuff... }
-
15.4 Para mais informações: Truth Equality and JavaScript by Angus Croll.
-
16.1 Utilize chaves para blocos multi-linhas. Pode-se omitir as chaves em blocos de uma linha.
// ruim if (test) return false; // bom if (test) return false; // muito bom if (test) { return false; } // ruim function() { return false; } // bom function() { return false; }
-
16.2 Se você está utilizando blocos multi-linhas com
if
eelse
, coloqueelse
na mesma linha do fechamento do bloco doif
.// ruim if (test) { thing1(); thing2(); } else { thing3(); } // bom if (test) { thing1(); thing2(); } else { thing3(); }
- 16.3 Não omita as chaves em blocos multi-linha.
Omitir as chaves nesse caso facilita bugs.
// ruim if (test) thing1(); thing2(); else thing3(); // bom if (test) { thing1(); thing2(); } else { thing3(); }
-
17.1 Utilize
/** ... */
para comentários multi-linha. Inclua uma descrição descrição e tente não ser redundante. Se o código está claro o suficiente para outra pessoa, reavalie se comentários são realmente necessários.// ruim // make() retorna um novo elemento // baseado na tag // const make = function(tag) { // ...stuff... return element; } // bom /** * make() retorna um novo elemento * baseado na tag */ const make = function(tag) { // ...stuff... return element; }
-
17.2 Utilize
//
para comentários de uma linha. Comente na linha imediatamente acima a linha do código, e deixe uma linha branco entre o comando anterior e o comentário.// ruim const active = true; // is current tab // bom // is current tab const active = true; // ruim const getType = function() { console.log('fetching type...'); // set the default type to 'no type' const type = this._type || 'no type'; return type; } // bom const getType = function() { console.log('fetching type...'); // set the default type to 'no type' const type = this._type || 'no type'; return type; }
-
17.3 Utilize prefixos
FIXME
ouTODO
quando necessário. -
17.4 Utilize
//FIXME:
para descrever problemas.class Calculator { constructor() { // FIXME: não utilizar variável global total = 0; } }
-
17.5 Utilize
//TODO:
para descrever soluções.class Calculator { constructor() { // TODO: total deveria ser inserido via parâmetro this.total = 0; } }
-
18.1 Utilize tabs como 4 espaços - padrão VS.
// ruim function() { ∙∙const name; } // ruim function() { ∙const name; } // bom function() { ∙∙∙∙const name; }
-
18.2 Coloque um espaço antes da chave inicial.
// ruim const test = function(){ console.log('test'); } // bom const test = function() { console.log('test'); } // ruim dog.set('attr',{ age: '1 year', breed: 'Bernese Mountain Dog', }); // bom dog.set('attr', { age: '1 year', breed: 'Bernese Mountain Dog', });
-
18.3 Coloque um espaço antes de abrir parênteses em comandos de controle (
if
,while
etc.). Não coloque espaços antes da lista de argumentos de uma função.// ruim if(isJedi) { fight (); } // bom if (isJedi) { fight(); } // ruim const fight = function () { console.log ('Swooosh!'); } // bom const fight = function() { console.log('Swooosh!'); }
-
18.4 Utilize espaço para separar operadores.
// ruim const x=y+5; // bom const x = y + 5;
-
18.5 Acabe arquivos com um caracter de nova linha.
// bad (function(global) { // ...stuff... })(this);
// bad (function(global) { // ...stuff... })(this);↵ ↵
// good (function(global) { // ...stuff... })(this);↵
-
18.5 Idente quando estiver fazendo method chaining de vários métodos. Utilize o ponto no começo da linha para demonstrar que é um método e não um comando novo.
// ruim $('#items').find('.selected').highlight().end().find('.open').updateCount(); // ruim $('#items'). find('.selected'). highlight(). end(). find('.open'). updateCount(); // bom $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount(); // ruim const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true) .attr('width', (radius + margin) * 2).append('svg:g') .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') .call(tron.led); // bom const leds = stage.selectAll('.led') .data(data) .enter().append('svg:svg') .classed('led', true) .attr('width', (radius + margin) * 2) .append('svg:g') .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') .call(tron.led);
-
18.6 Insira uma linha em branco após abrir o bloco e antes de fechar ele.
// ruim
if (foo) {
return bar;
}
// bom
if (foo) {
return bar;
}
// ruim
const baz = function(foo) {
return bar;
}
// bom
const baz = function(foo) {
return bar;
}
-
18.7 Insira uma linha em branco após o final do bloco
// ruim if (foo) { return bar; } return baz; // bom if (foo) { return bar; } return baz; // ruim const obj = { foo() { }, bar() { }, }; return obj; // bom const obj = { foo() { }, bar() { }, }; return obj;
-
19.1 Vírgulas no ínicio: Nope.
// ruim const story = [ once , upon , aTime ]; // bom const story = [ once, upon, aTime, ]; // ruim const hero = { firstName: 'Ada' , lastName: 'Lovelace' , birthYear: 1815 , superPower: 'computers' }; // bom const hero = { firstName: 'Ada', lastName: 'Lovelace', birthYear: 1815, superPower: 'computers', };
-
19.2 DISCUSS - Vírgula sobrando: Nope.
Typescript não elimina a vírgula que sobra.
```javascript
// ruim
const hero = {
firstName: 'Dana',
lastName: 'Scully',
};
const heroes = [
'Batman',
'Superman',
];
// bom
const hero = {
firstName: 'Dana',
lastName: 'Scully'
};
const heroes = [
'Batman',
'Superman'
];
```
-
20.1 Sempre.
// ruim (function() { const name = 'Skywalker' return name })() // bom (() => { const name = 'Skywalker'; return name; })(); // bom - closures não se tornam argumentos no caso de concatenação ;(() => { const name = 'Skywalker'; return name; })();
-
21.1 Faça o cast no início do comando.
-
21.2 Strings:
// => this.reviewScore = 9; // ruim const totalScore = this.reviewScore + ''; // bom const totalScore = String(this.reviewScore);
-
21.3 Utilize
parseInt
para Numbers e sempre utilize um radix para casting.const inputValue = '4'; // ruim const val = new Number(inputValue); // ruim const val = +inputValue; // ruim const val = inputValue >> 0; // ruim const val = parseInt(inputValue); // bom const val = Number(inputValue); // bom const val = parseInt(inputValue, 10);
-
21.4
parseInt
pode virar um bottleneck. Utilize Bitshift caso tenha se tornado um bottleneck por razões de performance, comente porque e o que você está fazendo.// good /** * parseInt estava deixando o código lento * Bitshifting a string para transformar-lá num Number deixou muito mais rápido */ const val = inputValue >> 0;
-
21.5 Note: Cuidado ao utilizar bitshift. Numeros são representados por 64 bits, porém operações bitshifts sempre retornam 32 bits. O Maior inteiro de 32 bits é 2.147.483.647.
2147483647 >> 0 //=> 2147483647 2147483648 >> 0 //=> -2147483648 2147483649 >> 0 //=> -2147483647
-
21.6 Booleans:
const age = 0; // ruim const hasAge = new Boolean(age); // bom const hasAge = Boolean(age); // bom const hasAge = !!age;
-
22.1 Seja sempre descritivo com o nome das suas funções.
// ruim function q() { // ...stuff... } // bom function query() { // ..stuff.. } // muito bom function queryStuffOnDataBase() { // ..stuff.. }
-
22.2 Utilize camelCase para nomear objetos, métodos, funções, campos privados e instâncias.
// ruim const OBJEcttsssss = {}; const this_is_my_object = {}; const c = function() {} // bom const thisIsMyObject = {}; const thisIsMyFunction = function() {}
-
22.3 Utilize PascalCase para nomear classes, campos públicos, modulos ou interfaces - essas sempre começando por I.
// ruim function user(options) { this.name = options.name; } const bad = new user({ name: 'nope', }); // bom module AperatureScience { class User { constructor(options) { this.name = options.name; } } } const good = new AperatureScience.User({ name: 'yup', });
-
23.1 DISCUSS Utilize a sintaxe de
get()
eset()
do Typescriptclass Foo{ private bar : number; get Bar() : number { return this.bar; } set Bar(value : number) { this.bar = value; } }
- 24.1 Placeholder de AngularJS events
-
25.1 Utilize o prefixo
$
.// ruim const sidebar = $('.sidebar'); // bom const $sidebar = $('.sidebar');
-
25.2 Faça cache de buscas do jQuery.
// ruim function setSidebar() { $('.sidebar').hide(); // ...stuff... $('.sidebar').css({ 'background-color': 'pink' }); } // bom function setSidebar() { const $sidebar = $('.sidebar'); $sidebar.hide(); // ...stuff... $sidebar.css({ 'background-color': 'pink' }); }
-
25.3 Para queries no DOM utilize cascading
$('.sidebar ul')
ou parent > child$('.sidebar > ul')
. jsPerf -
25.4 Utilize
find
com queries jQuery DISCUSS// ruim $('ul', '.sidebar').hide(); // ruim $('.sidebar').find('ul').hide(); // bom $('.sidebar ul').hide(); // bom $('.sidebar > ul').hide(); // bom $sidebar.find('ul').hide();
- 26.1 Placeholder de anotações de tipos.
- 26.2 Utilize
T
para o tipo da variável.
function identify<T>(arg: T): T {
return arg;
}
- 26.3 Se mais de um tipo é necessário, começe por
T
e siga em ordem alfabética.
function find<T, U extends Findable>(needle: T, haystack: U): U {
return haystack.find(needle)
}
- 26.4 Quando possível, utilize a inferência de tipos do Typescript.
// ruim
const output = identify<string>("myString");
// bom
const output = identity("myString");
- 26.5 Quando criar factories utilizando generics, não esqueça do construtor.
function create<t>(thing: {new(): T;}): T {
return new thing();
}
- 27.1 Nomeie a interface sempre iniciando pela letra
I
.
- 28.1 Placeholder
- 29.1 Utilize a tabela feita por Kangax da tabela de compatibilidade ES5.
- 30.1 ES6 Style Features
- Arrow Functions
- Classes
- Object Shorthand
- Object Concise
- Object Computed Properties
- Template Strings
- Destructuring
- Default Parameters
- Rest
- Array Spreads
- Let and Const
- Iterators and Generators
- Modules
- 31.1 ES6 Typescript Features
(The MIT License)
Copyright (c) 2014 Airbnb
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.