estilo de programação
1. Strings em nível de bloco
1. let substitui var
ES6 propõe dois novos comandos para declarar variáveis: let
e const
. Entre eles, let pode ser totalmente substituído var
, pois os dois possuem a mesma semântica e let
não apresentam efeitos colaterais.
'use strict';
if (true) {
let x = 'hello';
}
for (let i = 0; i < 10; i++) {
console.log(i);
}
Se o código acima for var
substituído let
, duas variáveis globais serão declaradas, o que obviamente não é a intenção. As variáveis só devem ser válidas dentro do bloco de código em que são declaradas, var
os comandos não podem fazer isso.
var
Os comandos têm efeitos de elevação variáveis, let
os comandos não têm esse problema.
'use strict';
if (true) {
console.log(x); // ReferenceError
let x = 'hello';
}
Se o código acima usar var
substituição let
, console.log
essa linha não relatará um erro, mas será gerada undefined
, porque a declaração da variável é promovida ao cabeçalho do bloco de código. Isso viola o princípio de declarar variáveis antes de usá-las.
Portanto, é recomendável não usar mais var
o comando, mas usar let
o comando.
2. Constantes globais e segurança de thread
Entre let
e const
, é recomendável usá-lo primeiro const
, principalmente no ambiente global, variáveis não devem ser definidas, apenas constantes devem ser definidas.
const
é preferido let
por várias razões. Uma é const
para lembrar as pessoas que leem o programa que essa variável não deve ser alterada; a outra está const
mais de acordo com a ideia de programação funcional, a operação não altera o valor, mas apenas cria um novo valor, e isso é também propício para futuras operações distribuídas; a última razão é que JavaScript
a compilação O compilador irá const
otimizá-lo, portanto, usá-lo mais const
ajudará a melhorar a eficiência de execução do programa, ou seja, a diferença essencial entre let
e const
é realmente diferente no processamento interno do compilador.
// bad
var a = 1, b = 2, c = 3;
// good
const a = 1;
const b = 2;
const c = 3;
// best
const [a, b, c] = [1, 2, 3];
const
Declarar constantes tem dois benefícios adicionais,Uma é que as pessoas que lerem o código perceberão imediatamente que esse valor não deve ser modificado e a outra é evitar erros causados pela modificação inadvertida de valores de variáveis.
Todas as funções devem ser definidas como constantes.
A longo prazo, JavaScript
pode haver implementações multiencadeadas (como o projeto River Trail da Intel). No momento, as variáveis representadas por let devem aparecer apenas no código de encadeamento único e não podem ser compartilhadas por vários encadeamentos. Isso ajuda a garantir que o encadeamento segurança.
2. corda
Strings estáticas sempre usam aspas simples ou acentos graves, não aspas duplas. Strings dinâmicas usam backticks.
// bad
const a = "foobar";
const b = 'foo' + a + 'bar';
// acceptable
const c = `foobar`;
// good
const a = 'foobar';
const b = `foo${
a}bar`;
3. Atribuição de desestruturação
Ao usar membros de array para atribuir valores a variáveis, as atribuições de desestruturação são preferidas.
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
Se o parâmetro da função for um membro do objeto, a atribuição de desestruturação é preferida.
// bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
}
// good
function getFullName(obj) {
const {
firstName, lastName } = obj;
}
// best
function getFullName({
firstName, lastName }) {
}
Se a função retornar vários valores, use a atribuição de desestruturação de objeto em vez da atribuição de desestruturação de matriz. Isso facilita adicionar valores de retorno posteriormente e alterar a ordem dos valores de retorno.
// bad
function processInput(input) {
return [left, right, top, bottom];
}
// good
function processInput(input) {
return {
left, right, top, bottom };
}
const {
left, right } = processInput(input);
4. Objeto
Objetos definidos em uma única linha, o último membro não termina com vírgula. Para objetos definidos em várias linhas, o último membro termina com uma vírgula.
// bad
const a = {
k1: v1, k2: v2, };
const b = {
k1: v1,
k2: v2
};
// good
const a = {
k1: v1, k2: v2 };
const b = {
k1: v1,
k2: v2,
};
O objeto deve ser o mais estático possível e, uma vez definido, nenhum novo atributo pode ser adicionado à vontade. Se adicionar propriedades for inevitável, use Object.assign
métodos.
// bad
const a = {
};
a.x = 3;
// if reshape unavoidable
const a = {
};
Object.assign(a, {
x: 3 });
// good
const a = {
x: null };
a.x = 3;
Se o nome do atributo do objeto for dinâmico, ele pode ser definido pela expressão do atributo ao criar o objeto.
// bad
const obj = {
id: 5,
name: 'San Francisco',
};
obj[getKey('enabled')] = true;
// good
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true,
};
No código acima, o último nome de atributo do objeto obj precisa ser calculado. Neste momento, é melhor usar expressões de atributo e definir esse atributo junto com outros atributos ao criar um novo obj. Dessa forma, todas as propriedades são definidas em um só lugar.
Além disso, os atributos e métodos do objeto devem ser expressos da forma mais concisa possível, de modo que seja fácil descrevê-los e escrevê-los.
var ref = 'some value';
// bad
const atom = {
ref: ref,
value: 1,
addValue: function (value) {
return atom.value + value;
},
};
// good
const atom = {
ref,
value: 1,
addValue(value) {
return atom.value + value;
},
};
5. Matrizes
Arrays são copiados usando o operador spread (...)
.
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
Array.from
Converta um objeto semelhante a uma matriz em uma matriz usando o método.
const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);
6. Funções
As funções de execução imediata podem ser escritas na forma de funções de seta.
(() => {
console.log('Welcome to the Internet.');
})();
Onde funções anônimas são usadas como parâmetros, tente usar funções de seta. Porque isso é mais conciso e vincula isso.
// bad
[1, 2, 3].map(function (x) {
return x * x;
});
// good
[1, 2, 3].map((x) => {
return x * x;
});
// best
[1, 2, 3].map(x => x * x);
As funções de seta foram substituídas Function.prototype.bind
e self/_this/that
as vinculações não devem mais ser usadas this
.
// bad
const self = this;
const boundMethod = function(...params) {
return method.apply(self, params);
}
// acceptable
const boundMethod = method.bind(this);
// best
const boundMethod = (...params) => method.apply(this, params);
Para funções simples, de uma linha e não reutilizáveis, é recomendável usar as funções de seta. Se o corpo da função for complexo e o número de linhas for grande, o método tradicional de escrita de função ainda deve ser usado.
Todos os itens de configuração devem estar concentrados em um objeto e colocados no último parâmetro. Valores booleanos não podem ser usados diretamente como parâmetros.
// bad
function divide(a, b, option = false ) {
}
// good
function divide(a, b, {
option = false } = {
}) {
}
Não use variáveis dentro de corpos de função arguments
, use rest
o operador (...)
em seu lugar. Porque rest
o operador indica explicitamente que você deseja obter o parâmetro, e arguments
é um objeto semelhante a uma matriz, e rest
o operador pode fornecer uma matriz real.
// bad
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
// good
function concatenateAll(...args) {
return args.join('');
}
Use a sintaxe de valor padrão para definir valores padrão para parâmetros de função.
// bad
function handleThings(opts) {
opts = opts || {
};
}
// good
function handleThings(opts = {
}) {
// ...
}
7. Estrutura do mapa
Preste atenção à distinção entre Object
e Map
, que são usados apenas ao simular objetos de entidade do mundo real Object
. Se apenas key: value
estruturas de dados forem necessárias, use Map
structs. Porque Map
tem um mecanismo de passagem embutido.
let map = new Map(arr);
for (let key of map.keys()) {
console.log(key);
}
for (let value of map.values()) {
console.log(value);
}
for (let item of map.entries()) {
console.log(item[0], item[1]);
}
8. Classe
Sempre use Class
, em vez da prototype
operação necessária. Porque Class
está escrito de forma mais concisa e fácil de entender.
// bad
function Queue(contents = []) {
this._queue = [...contents];
}
Queue.prototype.pop = function() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
// good
class Queue {
constructor(contents = []) {
this._queue = [...contents];
}
pop() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
}
Use extends
a herança de implementação porque é mais simples e não corre instanceof
o risco de interromper as operações.
// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function() {
return this._queue[0];
}
// good
class PeekableQueue extends Queue {
peek() {
return this._queue[0];
}
}
9. Módulos
A sintaxe do módulo ES6 é a maneira padrão de escrever módulos JavaScript, siga essa maneira de escrever e substitua a sintaxe Node.js
de CommonJS
.
Primeiro, use import
substituir require()
.
// CommonJS 的写法
const moduleA = require('moduleA');
const func1 = moduleA.func1;
const func2 = moduleA.func2;
// ES6 的写法
import {
func1, func2 } from 'moduleA';
Em segundo lugar, use export em vez de module.exports.
// commonJS 的写法
var React = require('react');
var Breadcrumbs = React.createClass({
render() {
return <nav />;
}
});
module.exports = Breadcrumbs;
// ES6 的写法
import React from 'react';
class Breadcrumbs extends React.Component {
render() {
return <nav />;
}
};
export default Breadcrumbs;
Se o módulo tiver apenas um valor de saída, use-o . export default
Se o módulo tiver vários valores de saída, a menos que um dos valores de saída seja particularmente importante, é recomendável não usá export default
-lo .export default
export
Se o módulo exportar uma função por padrão, a primeira letra do nome da função deve ser minúscula, indicando que se trata de um método utilitário.
function makeStyleGuide() {
}
export default makeStyleGuide;
Se o módulo gerar um objeto por padrão, a primeira letra do nome do objeto deve ser maiúscula, indicando que este é um objeto de valor de configuração.
const StyleGuide = {
es6: {
}
};
export default StyleGuide;