O estilo que você escolher para o seu projeto deve ser o mais alto critério. Coloque -o como uma descrição em seu projeto e vincule -o a este documento como uma garantia de consistência do estilo de código, legibilidade e manutenção.
1. Blank
1. Nunca misture espaços e guias.
2. Inicie um projeto, selecione Soft Indent (Space) ou TAB (como método de indentação) antes de escrever o código e usá -lo como o critério mais alto.
um). Para uma legibilidade, eu sempre recomendo projetar o indentação de largura de 2 letras em suas edições - isso é equivalente a dois espaços ou dois espaços em vez de uma guia.
3. Se o seu editor suportar, sempre ligue a configuração "Mostrar caracteres invisíveis". Os benefícios são:
um). Garantir consistência
b). Remova os espaços no final da linha
c). Remova espaços em branco
d). Submissão e comparação são mais legíveis
2. Embeleze a gramática
A. aparelho, aparelho, quebras de linha
A cópia do código é a seguinte:
// if/else/for/while/Try geralmente tem aparelhos, aparelhos encaracolados e várias linhas
// isso ajuda a leitura
// 2.a.1.1
// Exemplo de sintaxe difícil
if (condição) doSomething ();
enquanto (condição) iterando ++;
for (var i = 0; i <100; i ++) algum literativefn ();
// 2.a.1.1
// Use espaços para melhorar a legibilidade
if (condição) {
// Declaração
}
while (condição) {
// Declaração
}
for (var i = 0; i <100; i ++) {
// Declaração
}
// Melhor prática:
var i,
comprimento = 100;
for (i = 0; i <comprimento; i ++) {
// Declaração
}
// ou...
var i = 0,
comprimento = 100;
para (; i <comprimento; i ++) {
// Declaração
}
var prop;
para (prop no objeto) {
// Declaração
}
if (true) {
// Declaração
} outro {
// Declaração
}
B. Atribuir, declaração, função (funções nomeadas, expressões de função, funções de construtor)
A cópia do código é a seguinte:
// 2.b.1.1
// variável
var foo = "bar",
num = 1,
Undef;
// Identificação literal:
var Array = [],
objeto = {};
// 2.b.1.2
// Usando apenas um `var 'em um escopo (função) ajuda a melhorar a legibilidade
// e faça sua lista de declarações ordenadamente (também economiza algumas digitação de teclado)
// não é bom
var foo = "";
var bar = "";
var qux;
// bom
var foo = "",
bar = "",
Quux;
// ou..
Var // Comentários sobre essas variáveis
foo = "",
bar = "",
Quux;
// 2.b.1.3
// A instrução `var` deve estar sempre no topo de cada escopo (função)
// também adequado para constantes do ECMAScript 6
// não é bom
function foo () {
// há uma declaração antes da variável
var bar = "",
qux;
}
// bom
function foo () {
var bar = "",
qux;
// Todas as declarações estão após a variável
}
// 2.b.2.1
// Declaração de função nomeada
função foo (arg1, argn) {
}
// Como usar
foo (arg1, argn);
// 2.b.2.2
// Declaração de função nomeada
Função quadrada (número) {
número de retorno * número;
}
// Como usar
quadrado (10);
// Estilo de passagem de continuação muito não natural
Função quadrada (número, retorno de chamada) {
retorno de chamada (número * número);
}
quadrado (10, função (quadrado) {
// conteúdo de retorno de chamada
});
// 2.b.2.3
// Expressão da função
var square = function (número) {
// retorna conteúdo valioso e relevante
número de retorno * número;
};
// Expressão da função com identificador
// Este formulário preferido possui funções adicionais que permitem se chamar
// e há um identificador na pilha
var fatorial = função fatorial (número) {
if (número <2) {
retornar 1;
}
Número de retorno * Fatorial (número 1);
};
// 2.b.2.4
// Declaração do construtor
função foobar (opções) {
this.options = opções;
}
// Como usar
var foobar = novo foobar ({a: "alfa"});
foobar.Options;
// {a: "alfa"}
C. Exceção, detalhes
A cópia do código é a seguinte:
// 2.C.1.1
// funciona com retornos de chamada
foo (function () {
// Nota: não há espaços entre colchetes e `função` da primeira chamada de função
});
// A função aceita 'Array' como um argumento, sem espaços
foo (["alfa", "beta"]);
// 2.C.1.2
// A função aceita `objeto` como um argumento, sem espaços
foo ({
A: "Alpha",
B: "Beta"
});
// A função aceita o `string` literal como um argumento, sem espaços
foo ("bar");
// Não há espaços dentro dos colchetes usados para agrupar
if (! ("foo" em obj)) {
}
D. Consistência sempre ganha
Nas seções 2.a-2.c, o espaço em branco é proposto como um método de recomendação, com base em um objetivo simples e maior: unificação. Vale ressaltar que as preferências de formatação, como "espaço em branco interno", devem ser opcionais, mas deve haver apenas um tipo de código -fonte de todo o projeto.
A cópia do código é a seguinte:
// 2.D.1.1
if (condição) {
// Declaração
}
while (condição) {
// Declaração
}
for (var i = 0; i <100; i ++) {
// Declaração
}
if (true) {
// Declaração
} outro {
// Declaração
}
E. aspas
Não importa se você escolhe cotações únicas ou duplas, elas não fazem uma diferença de análise no JavaScript. O que absolutamente precisa ser exigido é a consistência. Nunca misture duas citações no mesmo projeto, escolha uma e mantenha -o consistente.
F. Fim da linha e linha vazia
Deixar em branco quebrará a diferença e o uso de alterações são ilegíveis. Considere incluir um gancho pré-comprometido que exclua automaticamente os espaços no final da linha e linhas em branco.
3. Detecção de tipo (das diretrizes do estilo jQuery Core)
A. Tipo direto (tipo real, tipo real)
Corda:
A cópia do código é a seguinte:
TIPOOF variável === "String"
Número:
A cópia do código é a seguinte:
TIPOOF variável === "Número"
Booleano:
A cópia do código é a seguinte:
Tipo de variável === "booleano"
Objeto:
A cópia do código é a seguinte:
TIPOOF variável === "Objeto"
Variedade:
A cópia do código é a seguinte:
Array.esArray (ArrayLikeObject)
(Se possível)
Nó:
A cópia do código é a seguinte:
elem.nodetype === 1
nulo:
A cópia do código é a seguinte:
variável === NULL
nulo ou indefinido:
A cópia do código é a seguinte:
variável == NULL
indefinido:
Variáveis globais:
A cópia do código é a seguinte:
TIPOOF variável === "indefinido"
Variáveis locais:
A cópia do código é a seguinte:
variável === indefinido
propriedade:
A cópia do código é a seguinte:
object.prop === indefinido
Object.HasownProperty (Prop)
"Prop" no objeto
B. Tipo de converter (tipo coagido, tipos coagidos)
Considere o significado do seguinte ...
Dado html:
A cópia do código é a seguinte:
<input type = "text" id = "foo-input" value = "1">
// 3.b.1.1
// `foo` recebeu um valor de` 0`, tipo `número`
var foo = 0;
// typeof foo;
// "número"
...
// No código subsequente, você precisa atualizar `foo` e atribuir um novo valor obtido no elemento de entrada
foo = document.getElementById ("foo-input").
// Se você testar `typeof foo` agora, o resultado será` string`
// Isso significa que você tem lógica semelhante a isso ao detectar `foo` na instrução if:
if (foo === 1) {
importanteTask ();
}
// `importanteTask ()` nunca será executado, mesmo que 'Foo` tenha um valor de "1"
// 3.b.1.2
// Você pode usar inteligentemente o operador +/- unário para lançar o tipo para resolver o problema:
foo = +document.getElementById ("foo-input"). value;
// ^ + O operador unário converte o objeto de operação na direita em `número '
// typeof foo;
// "número"
if (foo === 1) {
importanteTask ();
}
// `importanteTask ()` será chamado
Aqui estão alguns exemplos para o elenco:
A cópia do código é a seguinte:
// 3.b.2.1
Var número = 1,
String = "1",
bool = false;
número;
// 1
número + "";
// "1"
corda;
// "1"
+string;
// 1
+string ++;
// 1
corda;
// 2
bool;
// false
+bool;
// 0
bool + "";
// "false"
// 3.b.2.2
Var número = 1,
String = "1",
bool = true;
string === número;
// false
string === número + "";
// verdadeiro
+string === número;
// verdadeiro
bool === número;
// false
+bool === número;
// verdadeiro
bool === String;
// false
bool === !! string;
// verdadeiro
// 3.b.2.3
var Array = ["A", "B", "C"];
!! ~ Array.IndexOf ("A");
// verdadeiro
!! ~ Array.IndexOf ("B");
// verdadeiro
!! ~ Array.IndexOf ("C");
// verdadeiro
!! ~ Array.IndexOf ("D");
// false
// Vale a pena notar que o exposto acima é "inteligente desnecessário"
// Use um esquema claro para comparar os valores retornados
// por exemplo, indexOf:
if (array.indexOf ("a")> = 0) {
// ...
}
// 3.b.2.3
var num = 2,5;
parseint (num, 10);
// equivalente a ...
~~ num;
num >> 0;
num >>> 0;
// Os resultados são todos 2
// Sempre lembre -se, os valores negativos serão tratados de maneira diferente ...
var neg = -2,5;
parseint (neg, 10);
// equivalente a ...
~~ neg;
neg >> 0;
// Os resultados são todos -2
// mas...
neg >>> 0;
// O resultado é 4294967294
4. Operações comparativas
A cópia do código é a seguinte:
// 4.1.1
// Ao apenas julgar se uma matriz tem um comprimento, em relação ao uso disso:
if (Array.Length> 0) ...
// ... Para determinar a autenticidade, use isso:
if (Array.length) ...
// 4.1.2
// Ao apenas julgar se uma matriz está vazia, em relação ao uso disso:
if (Array.Length === 0) ...
// ... Para determinar a autenticidade, use isso:
if (! Array.length) ...
// 4.1.3
// Ao apenas julgar se uma string está vazia, em relação ao uso disso:
if (string! == "") ...
// ... Para determinar a autenticidade, use isso:
if (string) ...
// 4.1.4
// Ao apenas julgar que uma string está vazia, em relação ao uso disso:
if (string === "") ...
// ... Para determinar a autenticidade, use isso:
if (! string) ...
// 4.1.5
// Ao apenas julgar que uma referência é verdadeira, relativa ao uso disso:
if (foo === true) ...
// ... julgue como você pensa, aproveite os benefícios dos recursos internos:
se (foo) ...
// 4.1.6
// Ao apenas julgar que uma referência é falsa, relativa ao uso disso:
if (foo === false) ...
// ... converta -o para o verdadeiro uso de exclamação
se (! foo) ...
// ... deve -se notar que isso corresponderá 0, "", nulo, indefinido, nan
// Se você _must_ é do tipo booleano false, use isto:
if (foo === false) ...
// 4.1.7
// Se você deseja calcular uma referência, pode ser nulo ou indefinido, mas não é falso "," ou 0,
// em relação ao uso disso:
if (foo === null || foo === indefinido) ...
// ... Aproveite os benefícios de == Tipo de fundição, assim:
if (foo == null) ...
// Lembre -se de que usar == fará `null` corresponder 'null` e` indefinido'
// mas não `false`" "ou 0
nulo == indefinido
Sempre julgue os melhores e mais precisos valores, o acima é um guia e não um dogma.
A cópia do código é a seguinte:
// 4.2.1
// Instruções para conversão de tipo e operações de comparação
// Primeira vez `===`, `==` seguido (a menos que seja necessária uma comparação solta)
// `===` nem sempre faz conversão de tipo, o que significa:
"1" === 1;
// false
// `==` converte o tipo, o que significa:
"1" == 1;
// verdadeiro
// 4.2.2
// booleano, verdadeiro e falso
// booleano:
Verdadeiro, falso
// real:
"Foo", 1
// pseudo:
"", 0, nulo, indefinido, nan, vazio 0
5. Estilo prático
A cópia do código é a seguinte:
// 5.1.1
// um módulo prático
(função (global) {
var módulo = (function () {
var data = "secreto";
retornar {
// Este é um valor booleano
bool: verdadeiro,
// uma string
String: "A String",
// Uma matriz
Array: [1, 2, 3, 4],
// um objeto
Objeto: {
Lang: "En-us"
},
getData: function () {
// obtenha o valor de `dados`
retornar dados;
},
setData: function (value) {
// retorna o valor atribuído de `dados '
return (dados = valor);
}
};
}) ();
// Alguns outros aparecerão aqui
// transforme seu módulo em um objeto global
global.module = módulo;
})( esse );
// 5.2.1
// uma função de construção prática
(função (global) {
função ctor (foo) {
this.foo = foo;
devolver isso;
}
Ctor.prototype.getfoo = function () {
devolver este.foo;
};
Ctor.prototype.setFoo = function (val) {
return (this.foo = val);
};
// Não use `new` para chamar a função de compilação, você pode fazer isso:
var ctor = function (foo) {
devolver o novo ctor (foo);
};
// transforma nossa função de construção em um objeto global
global.ctor = cTor;
})( esse );
6. Nomeação
R. Você não é um compilador/compressor humano, então tente se transformar em um.
O código a seguir é um exemplo de uma nomeação muito ruim:
A cópia do código é a seguinte:
// 6.a.1.1
// Código de exemplo de nomes ruim
função q (s) {
retorno document.QuerySelectorAll (s);
}
var i, a = [], els = q ("#foo");
for (i = 0; i <els.length; i ++) {a.push (els [i]);}
Não há dúvida de que você escreveu esse código - espero que não apareça novamente a partir de hoje.
Aqui está um código com a mesma lógica, mas com uma nomeação mais robusta e adequada (e uma estrutura legível):
A cópia do código é a seguinte:
// 6.a.2.1
// Código de exemplo nomeado melhorado
Função consulta (seletor) {
retornar document.QuerySelectorAll (seletor);
}
var idx = 0,
elementos = [],
Matches = Query ("#Foo"),
comprimento = matches.length;
para (; idx <comprimento; idx ++) {
elementos.push (corresponde [idx]);
}
Algumas dicas adicionais de nomeação:
A cópia do código é a seguinte:
// 6.a.3.1
// String nomeada
`Dog` é uma corda
// 6.a.3.2
// Matrizes de nome
`['cães']` é uma matriz que contém a corda de cachorro
// 6.a.3.3
// funções de nome, objetos, instâncias, etc.
camlcase; função e declarações de var
// 6.a.3.4
// Nomeie o construtor, o protótipo, etc.
Pascalcase; função de construção
// 6.a.3.5
// Nome de expressões regulares
rdesc = //;
// 6.a.3.6
// do guia de estilo da biblioteca de fechamento do Google
functionNameslikethis;
variablenameslikethis;
Constructornameslikethis;
Enumnameslikethis;
MethodNameslikethis;
Symbolic_constants_like_this;
B. Enfrente isso
Além de usar chamadas e aplicações bem conhecidas, o .Bind (this) ou um funcionalmente equivalente a ela é sempre preferido. Crie uma declaração de função de limite para chamadas subsequentes, usando alias quando não houver uma opção melhor.
A cópia do código é a seguinte:
// 6.B.1
dispositivo de função (opts) {
this.value = null;
// Crie um novo fluxo assíncrono, isso será chamado continuamente
Stream.read (opts.Path, function (Data) {
// Use Stream para retornar o valor mais recente dos dados e atualizar o valor da instância
this.value = dados;
} .bind (this));
// Controle a frequência do acionamento do evento
setInterval (function () {
// Publique um evento controlado
this.emit ("Evento");
} .bind (this), opts.freq || 100);
}
// Suponha que herdamos o EventEmitter;)
Quando não pode ser executado, o equivalente a .bind está disponível nas bibliotecas JavaScript mais modernas.
A cópia do código é a seguinte:
// 6.B.2
// Exemplo: lodash/subscore, _.bind ()
dispositivo de função (opts) {
this.value = null;
stream.read (opts.path, _.bind (function (dados) {
this.value = dados;
}, esse) );
setInterval (_. bind (function () {
this.emit ("Evento");
}, este), opts.freq || 100);
}
// Exemplo: jQuery.proxy
dispositivo de função (opts) {
this.value = null;
Stream.read (opts.path, jquery.proxy (function (dados) {
this.value = dados;
}, esse) );
setInterval (jQuery.proxy (function () {
this.emit ("Evento");
}, este), opts.freq || 100);
}
// Exemplo: Dojo.hitch
dispositivo de função (opts) {
this.value = null;
stream.read (opts.path, dojo.hitch (this, function (dados) {
this.value = dados;
}));
setInterval (dojo.hitch (this, function () {
this.emit ("Evento");
}), opts.freq || 100);
}
Forneça um candidato para criar um alias para isso, com o identificador. É muito provável que isso tenha erros e deve ser evitado o máximo possível.
A cópia do código é a seguinte:
// 6.B.3
dispositivo de função (opts) {
var self = this;
this.value = null;
Stream.read (opts.Path, function (Data) {
self.value = dados;
});
setInterval (function () {
self.emit ("Evento");
}, opts.freq || 100);
}
C. Use thisArg
Vários métodos de protótipo no ES 5.1 têm uma etiqueta especial ThisArg incorporada, use -a o máximo possível
A cópia do código é a seguinte:
// 6.C.1
var obj;
obj = {f: "foo", b: "bar", q: "qux"};
Object.Keys (OBJ) .ForEach (function (key) {
// | this | Agora é `obj`
console.log (esta [chave]);
}, obj); // <- o último parâmetro é `thisArg`
// Imprima ...
// "foo"
// "bar"
// "qux"
ThisArg pode ser usado em Array.prototype.avery, Array.prototype.ForEach, Array.prototype.ome, Array.prototype.map e Array.prototype.filter.
7. Misc
As idéias e idéias que esta parte explicará não são dogmáticas. Em vez disso, é mais incentivado a ficar curioso sobre as práticas existentes para tentar fornecer uma solução melhor para concluir as tarefas gerais de programação do JavaScript.
A. Evite usar o switch. O rastreamento do método moderno funções da lista negra com expressões de switch.
Parece que o Firefox e o Chrome fizeram melhorias significativas para alternar as declarações. http://jsperf.com/switch-vs-object-literal-vs-module
Vale a pena notar que a melhoria pode ser vista aqui: https://github.com/rwldrn/idiomatic.js/issues/13
A cópia do código é a seguinte:
// 7.a.1.1
// Exemplo de declaração de switch
Switch (foo) {
caso "alfa":
alfa();
quebrar;
caso "beta":
beta();
quebrar;
padrão:
// ramificação padrão
quebrar;
}
// 7.a.1.2
// Um método que pode suportar combinação e reutilização é usar um objeto para armazenar "casos".
// Use uma função para fazer delegação:
casos de var, delegador;
// O valor de retorno é apenas para explicação
casos = {
alfa: function () {
// Declaração
// Um valor de retorno
retornar ["alfa", argumentos.length];
},
beta: function () {
// Declaração
// Um valor de retorno
retornar ["beta", argumentos.length];
},
_default: function () {
// Declaração
// Um valor de retorno
return ["padrão", argumentos.length];
}
};
Delegator = function () {
var args, chave, delegado;
// converter `argumento` em uma matriz
args = [] .slice.call (argumentos);
// extraia o último valor do `argumento '
chave = args.shift ();
// Ligue para a filial padrão
delegado = casos._default;
// delegar o método do objeto
if (case.hasownProperty (key)) {
delegado = casos [chave];
}
// O escopo do ARG pode ser definido como um valor específico,
// Neste caso, | nulo | está bem
retornar delegate.apply (null, args);
};
// 7.a.1.3
// Use a API em 7.a.1.2:
Delegador ("Alpha", 1, 2, 3, 4, 5);
// ["alfa", 5]
// Claro, o valor da tecla `case` pode ser facilmente alterado para qualquer valor
var caseKey, algumuserinput;
// Existe alguma entrada possível de alguma forma?
algumuserinput = 9;
if (algumuserinput> 10) {
casekey = "alfa";
} outro {
casekey = "beta";
}
// ou...
CaseKey = algumuserinput> 10? "alfa": "beta";
// Então...
delegador (CaseKey, algumusserinput);
// ["beta", 1]
// Claro, isso pode ser feito ...
delegador ();
// ["padrão", 0]
B. Retornar os valores com antecedência para melhorar a legibilidade do código sem muita diferença de desempenho
A cópia do código é a seguinte:
// 7.B.1.1
// não é bom:
função returnlate (foo) {
var ret;
if (foo) {
ret = "foo";
} outro {
RET = "TOUX";
}
retornar retorno;
}
// bom:
função returnEarly (foo) {
if (foo) {
retornar "foo";
}
retornar "Quux";
}
8. Objetos nativos e host (Nota: Eu sempre pensei que os objetos host não deveriam ser traduzidos, então traduzi de acordo com o método de escrita geral)
O princípio mais básico é:
Não faça nada estúpido, as coisas sempre melhorarão.
Para fortalecer esse conceito, assista a esta demonstração:
"Tudo é permitido: Extensão nativa", de Andrew Dupont (JSConf2011, Portland, Oregon)
http://blip.tv/jsconf/jsconf2011-andrew-dupont-everything-is-permitt-alextending-built-ins-5211542
9. Comentários
Comentários de linha única são colocados acima do código como a primeira escolha
Várias linhas estão ok
Os comentários no final da linha devem ser evitados!
O método JSDOC também é bom, mas leva mais tempo
10. Use um idioma sozinho
Independentemente do idioma que o mantenedor (ou equipe) estipula que o programa seja usado, o programa deve ser escrito apenas no mesmo idioma.
apêndice
Vírgula primeiro
Todos os projetos que usam este documento como um guia de estilo básico não permitem formatos de código pré-comomma, a menos que explicitamente especificado ou exigido pelo autor.