Focusnetworks JavaScript code styleguide.
- Disclaimer
- Ponto e vírgula
- Strict mode
- Context e closures
- Variáveis
- Objetos
- Arrays
- Strings
- Funções
- Convenções de nomenclatura
- Propriedades
- Expressões condicionais e de igualdade
- Blocos
- Comentários
- Espaços em branco
- Verificação de tipo
- Melhores práticas
- Links
Esse documento foi inspirado por jQuery Style Guide, idiomatic.js e Airbnb JavaScript Style Guide.
- Sempre, por favor! ASI é muito complicado, não confie nele.
// Bad
(function() {
var name = 'John'
return name
})()
// Good
(function() {
var name = 'John';
return name;
})();
- Você pode usar o strict mode. Basta estar atento para não usá-lo em modo global!
// Bad
'use strict';
function doSomething() {
}
function doSomethingElse() {
}
// Good
function doSomething() {
'use strict';
// stuff
}
// Good
(function() {
'use strict';
function doSomething() {
}
function doSomethingElse() {
}
})();
- Sempre envolva seus módulos em closures (fechamentos) criando um contexto (context) único de execução. Jogar coisas no escopo global pode levar a todos os tipos de comportamentos estranhos.
// Bad
function doAwesomeStuff() {
$('.js-item').fadeIn();
}
function doEvenCoolerStuff() {
$('.js-item').animate({top: 100}, 'fast');
}
// Good
(function($) {
function doAwesomeStuff() {
$('.js-item').fadeIn();
}
function doEvenCoolerStuff() {
$('.js-item').animate({top: 100}, 'fast');
}
})(jQuery);
// Good
var Module = (function() {
function Module() {
// magic happens here
}
return Module;
})();
- Use
var
simples na definição de variáveis.
// Bad
var foo = 'Foo';
var bar = 'Bar';
var baz = 'Baz';
// Good
var foo = 'Foo',
bar = 'Bar',
baz = 'Baz';
- Variáveis sem valor de inicialização deve vir em primeiro lugar.
// Bad
var name = 'John',
surname = 'Doe',
country,
age = 42,
email;
// Good
var country,
email,
name = 'John',
surname = 'Doe',
age = 42;
- Não siga o estilo "comma first"!
// Bad (OMG, really bad!)
var once
, upon
, aTime;
// Good
var once,
upon,
aTime;
// Bad
var user = {
name: 'John'
, surname: 'Doe'
, age: 42
};
// Good
var user = {
name: 'John',
surname: 'Doe',
age: 42
};
- Use a sintaxe literal para criar objetos.
// Bad
var foo = new Object();
// Good
var bar = {};
- Evite usar palavras reservadas como chaves. Elas podem causar problemas em versões mais antigas do IE se não estiverem dentro de aspas.
// Bad
var foo = {
class: 'Foo'
};
// Good
var bar = {
klass: 'Bar'
};
// Good
var baz = {
type: 'Baz'
};
- Use 🐫 camelCase ao nomear chaves de objetos, sempre quando possível.
// Bad
var user = {
'name': 'John',
'has-children': false,
'is-underage': false,
'age': 42
};
// Good
var user = {
name: 'John',
hasChildren: false,
isUnderage: false,
age: 42
};
- Se você precisar usar aspas para envolver suas chaves, por qualquer motivo, use-o de maneira consistente:
// Bad
var config = {
development: true,
'markdown-plugin': true,
shouldIgnoreManifest: false,
PersistData: true,
enforcenamespace: true
};
// Good
var config = {
'development': true,
'markdown-plugin': true,
'should-ignore-manifest': false,
'persist-data': true,
'enforce-namespace': true
};
// Good
var config = {
development: true,
markdownPlugin: true,
shouldIgnoreManifest: false,
persistData: true,
enforceNamespace: true
};
- Use sintaxe literal para criação de arrays.
// Bad
var foo = new Array();
// Good
var bar = [1, 2, 3];
- Se você não sabe a quantidade de itens do array use
Array.push
.
var groceries = [];
// Bad
groceries[groceries.length] = 'tomato';
// Good
groceries.push('oreo');
- Para limpar um array, defina a quantidade como zero.
// Bad
var foo = [1, 3, 5];
foo = null;
// Good
var bar = [2, 4, 6];
bar.length = 0;
- Para converter um objeto de matriz semelhante a uma matriz, use
Array.slice
. - Você pode querer fazer isso porque objetos array-like (por exemplo,
{'0': 'Olá', '1': 'lá'}
) não têm métodos como.join()
, para mais informações nesse assunto leia esse artigo
function argsToArray() {
var args = Array.prototype.slice.call(arguments);
}
- Use aspas simples
''
para strings.
// Bad
var morada = "Márcio Moradei";
// Good
var danilo = 'Danilo Vaz';
- Concatene strings utilizando o operador mais
+
.
var name = 'Danilo';
// Bad
name.concat('Vaz');
// Good
name += ' Vaz';
- Prefira concatenação de long strings, sempre adicionando quebras de linha depois de um operador. Long strings podem afetar o desempenho (referências e discussão).
// Bad
var 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.';
// Bad
var 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.';
// Good
var 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.';
-
Para converter objetos em strings, use o método
toString()
. -
A conversão com
toString()
não funciona com valoresnull
eundefined
. Para converter qualquer valor para string, concatene esse valor com uma string vazia. Isso é útil quando você não se importa com o valor da conversão (ex: em um logging ou tracking system). No caso de você converter um valornull
, ele será transformado em um"null"
. A mesma regra é aplicada para valoresundefined
.
var value = 42;
// Good
value += '';
var empty;
empty += ''; // "undefined"
- Sempre que você tem mais de 3 argumentos sendo passados para uma função, é preferível você usar um objeto em seu lugar.
// Bad
// Muitos argumentos
function setUser(firstName, lastName, age, gender, occupation) {
// faz alguma coisa
}
setUser('Jon', 'Snow', 25, 'Male', 'Nights-watcher');
// Good
// Ao invés disso, use uma config/opções de objetos
function setUser(user) {
// faz alguma coisa
}
setUser({
firstName: 'Jon',
lastName: 'Snow',
age: 25,
gender: 'Male',
occupation: 'Nights-watcher'
});
- Use camelCase quando nomear objetos, funções e instancias.
// bad
var foo_bar = 'I am messed up';
// good
var fooBar = 'I am alright!';
- Use PascalCase quando nomear construtores e "classes".
// Bad
function crewMember(name, role) {
this.name = name;
this.role = role;
}
var danilo = new crewMember('Danilo', 'Desenvolvedor');
// Good
function CrewMember(name, role) {
this.name = name;
this.role = role;
}
var alan = new CrewMember('Alan', 'Designer');
- Evite nomes com uma única letra. Seja descritivo e claro.
// Bad
function f() {
// What the hell is this?
}
// Good
function bootstrapFoo() {
// Ah, ok!
}
// Bad
function stuff() {
// "stuff" is too generic
}
// Good
function doAnimationStuff() {
// Now we're talking
}
- Sempre envolva as invocações de construtores entre brackets. Será mais fácil de passar novos valores no futuro.
// Bad
var foo = new FooBar;
// Good
var bar = new FooBar();
var baz = new FooBar(1, 'lorem');
- Utilize sempre um sublinhado inicial
_
ao nomear propriedades privadas e métodos.
// Bad
var $name = 'Foo';
var __name = 'Bar';
// Good
var _name = 'Baz';
- Quando fizer um referência ao
this
nomei-o comself
.
// Bad
function() {
var that = this;
return function() {
console.log(that);
}
}
// Bad
function() {
var _this = this;
return function() {
console.log(this);
}
}
// Good
function() {
var self = this;
return function() {
console.log(self);
}
}
- Quando nomear variáveis booleanas, deve começar com "is", "has", "should" ou "was".
// Bad
var ready = true,
animate = true,
started = false,
animation = true;
// Good
var isReady = true,
shouldAnimate = true,
wasStarted = true,
hasAnimation = true;
- Quando nomear funções booleanas, deve começar com "is".
// Bad
function ready() {
return false;
}
// Good
function isReady() {
return true;
}
- Quando nomear um acessor, tente começar com "get" or "set". Também nomeie explicitamente
value
como parâmetro getters.
var currentStatus;
// Bad
function status(val) {
if (val) {
currentStatus = val;
}
return currentStatus;
}
// Good
function setStatus(value) {
currentStatus = value;
}
function getStatus() {
return currentStatus;
}
- Quando nomear um event handler (manipulador de evento), combine sua ação com o tipo de evento.
// Bad
$('.button').click(click);
function click() {
console.log('meh');
}
// Good
$('.button').click(toggleColorOnClick);
function toggleColorOnClick() {
console.log('should toggle color on click!');
}
- Ao nomear seletores de elementos nas classes DOM que terá qualquer tipo de comportamento, adicione o prefixo
js
para o nome do seu componente separando palavras usando um hífen-
.
<ul class="js-navigation-menu">
<li>Foo</li>
<li>Bar</li>
</ul>
var menu = $('.js-navigation-menu');
- Use o
.
para acessar as propriedades.
var user = {
name: 'John',
age: 42
};
// Bad
var userName = user['name'];
// Good
var userAge = user.age;
- Use colchetes
[]
para acessar propriedades dinâmicas.
var user = {
name: 'John',
age: 42
};
function getUserInfo(info) {
return user[info];
}
var userName = getUserInfo('name');
- Use
===
e!==
ao invés de==
e!=
.
- Sempre envolva blocos dentro de chaves e use novas linhas.
// Bad
if (false)
return;
// Bad
if (false) { return false; }
// Good
if (true) {
return true;
}
// Good
if (true) {
return true;
} else {
return false;
}
-
Não faça comentários insignificantes e óbvios, seja conciso sobre ele.
-
Sinta-se livre para utilizar sintaxe markdown nos comentários.
-
Não há necessidade de usar a sintaxe JSDoc uma vez que não geramos a documentação automaticamente.
-
Usando tags
FIXME
,TODO
eNOTE
poderá ajudar outros desenvolvedores a entender e manter seu código. Você pode usar isso como quiser. -
Utilize sintaxe de bloco de documentação seguido por uma nova linha de comentários de várias linhas. Existem ferramentas disponíveis para tornar isso realmente fácil.
// Bad
// Usado para casar um `RegExp` de caracteres especiais.
// Veja esse [artigo sobre caracteres `RegExp`](http://www.regular-expressions.info/characters.html#special)
// para mais detalhes.
var matchSpecialChars = /[.*+?^${}()|[\]\/\\]/g;
// Bad
/*
Usado para casar um `RegExp` de caracteres especiais.
Veja esse [artigo sobre caracteres `RegExp`](http://www.regular-expressions.info/characters.html#special)
para mais detalhes.
*/
var matchSpecialChars = /[.*+?^${}()|[\]\/\\]/g;
// Good
/**
* Usado para casar um `RegExp` de caracteres especiais.
* Veja esse [artigo sobre caracteres `RegExp`](http://www.regular-expressions.info/characters.html#special)
* para mais detalhes.
*/
var matchSpecialChars = /[.*+?^${}()|[\]\/\\]/g;
- Use
//
para comentários de linha única. Coloque comentários de linha única sobre uma nova linha acima do assunto do comentário e adicione uma linha em branco antes do comentário.
// Bad
var active = true; // is current tab
// Good
// is current tab
var active = true;
// Bad
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
var type = this._type || 'no type';
return type;
}
// Good
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
var type = this._type || 'no type';
return type;
}
- Use soft tabs definido para 2 espaços e nunca misture espaços com tabs.
// Bad
function() {
∙∙∙∙var name;
}
// Bad
function() {
∙var name;
}
// Bad
function() {
⇥var name;
}
// Good
function() {
∙∙var name;
}
- Sempre adicione uma linha em branco ao final do seu documento.
// Bad
(function() {
document.write('Hello World!');
})();
// Good
(function() {
document.write('Hello World!');
})();
↵
- Coloque 1 espaço antes e depois de uma declaração de condição ou loop.
// Bad
if(false){return false;}
// Good
if (true) {
return true;
}
// Bad
while(false){console.log('whatever');}
// Good
while (false) {
console.log('alright!');
}
- Separe os operadores com espaços.
// Bad
var x=y+5;
// Good
var x = y + 5;
- Coloque 1 espaço depois das etapas do loop e argumentos de função.
// Bad
for(var i=0;i<10;++i) {
console.log(i);
}
// Good
for (var i = 0; i < 42; ++i) {
console.log(i);
}
// Bad
function setUser(name,surname,age){
// sets user
}
// Good
function setUser(name, surname, age) {
// sets user
}
- Em objetos que têm mais do que uma única propriedade você deve quebrar todas as propriedades em novas linhas.
// Bad
var user = {name: 'John', surname: 'Doe', age: 42};
// Good
var user = {
name: 'John',
surname: 'Doe',
age: 42
};
- Adicionar espaços internos quando declarar objetos embutidos.
// Bad
var app = {locale: 'pt-br'};
// Good
var app = { locale: 'pt-br' };
- Use identação quando fizer longos encadeamentos de método.
// Bad
$('#items').find('.selected').highlight().end().find('.open').updateCount();
// Good
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();
typeof variable === 'string';
typeof variable === 'number';
typeof variable === 'boolean';
typeof variable === 'object';
Array.isArray(arrayLikeObject);
elem.nodeType === 1;
variable === null;
variable == null;
typeof variable === 'undefined';
variable === undefined;
object.prop === undefined;
object.hasOwnProperty(prop);
'prop' in object;
-
Não comece fechamentos com ponto e vírgula.
-
Nós encorajamos você a registrar eventos da aplicação e mudanças importantes apenas no modo de desenvolvimento. Siga o formato de
Module/ClassName :: method() :: message
.
function App() {
console.log('App :: App instance created');
}
App.prototype.bootstrap = function() {
console.log('App :: bootstrap() :: App was initialized');
};
- Cacheie consultas de jQuery sempre que possível.
- Prefira
remove()
ao invés deempty()
.
- It’s time to start using JavaScript strict mode
- Why is it recommended to have empty line in the end of file?
- Multiple var statements in JavaScript, not superfluous
- Naming methods, properties and objects