Uso adequado de const para definir funções em JavaScript

183

Estou interessado em saber se existem limites para quais tipos de valores podem ser definidos usando constJavaScript - em funções específicas. Isso é válido? Concedido que funciona, mas é considerado má prática por qualquer motivo?

const doSomething = () => {
   ...
}

Todas as funções devem ser definidas dessa maneira no ES6? Não parece que isso pegou, se sim.

Obrigado por qualquer comentário!

David Sinclair
fonte
Você parece fazer várias perguntas: 1) "Estou interessado em saber se existem limites para quais tipos de valores podem ser definidos usando const no JavaScript" No. 2) "Isso é válido? Sim. 3) "é considerado uma prática ruim por qualquer motivo" Acho que não existe há tempo suficiente para dizer algo sobre isso, mas não vejo por que isso deveria ser uma prática prática. Não é muito diferente var doSomething = <function def>;. 4) "Todas as funções devem ser definidas dessa maneira no ES6?" Parece complicado para mim. Eu gosto de declarações de função. Todo mundo é seu.
Felix Kling
1
Do jeito que eu vejo isso (opinião, não um fato), faz sentido se você deseja proibir a redefinição de funções. Seja sensato ou tenha algum uso funcional - isso é discutível. Se você acha que ele se encaixa no seu cenário de uso, não acho que alguém possa discutir sua decisão e considerá-la uma má prática.
Mjh
4
Eu acho que a questão é o que você deseja alcançar const. Deseja impedir-se de substituir a função? Eu suponho que você conhece seu código para não fazer isso de qualquer maneira. Deseja expressar a intenção de doSomething, ou seja, que ela detenha uma função e não altere seu valor? Eu acho que as declarações de função também comunicam essa intenção claramente. Portanto, se você precisar de "proteção de tempo de execução", substitua-a. Caso contrário, não vejo muitos benefícios. Claro que se você costumava usar var foo = function() {};, eu usaria em constvez de var.
Felix Kling
5
@FelixKling, "Eu diria que você conhece seu código para não fazer isso de qualquer maneira". - este é um argumento muito ruim. Caso contrário, não há sentido constalgum.
29516 meandre

Respostas:

253

Não há problema com o que você fez, mas você deve se lembrar da diferença entre declarações e expressões de função.

Uma declaração de função, ou seja:

function doSomething () {}

É içada inteiramente para o topo do escopo (e assim por diante, lete consteles também têm escopo de bloco).

Isso significa que o seguinte funcionará:

doSomething() // works!
function doSomething() {}

Uma expressão de função, ou seja:

[const | let | var] = function () {} (or () =>

É a criação de uma função anônima ( function () {}) e a criação de uma variável e, em seguida, a atribuição dessa função anônima a essa variável.

Portanto, as regras usuais sobre a elevação de variáveis ​​dentro de um escopo - variáveis ​​com escopo de bloco ( lete const) não elevam quanto undefinedao topo do escopo de seu bloco.

Isso significa:

if (true) {
    doSomething() // will fail
    const doSomething = function () {}
}

Falhará, pois doSomethingnão está definido. (Ele jogará a ReferenceError)

Se você mudar para o uso, varobterá a elevação da variável, mas ela será inicializada para undefinedque o bloco de código acima ainda não funcione. (Isso ativará uma TypeErrorvez que doSomethingnão é uma função no momento em que você a chama)

No que diz respeito às práticas padrão, você deve sempre usar a ferramenta adequada para o trabalho.

Axel Rauschmayer tem um ótimo post sobre escopo e içamento, incluindo a semântica es6: Variáveis ​​e escopo no ES6

tkone
fonte
7
Gostaria apenas de adicionar que as classes es6 usam const internamente para proteger o nome da classe de ser reatribuído dentro da classe.
user2342460
2
Uma sutil diferença entre um function a(){console.log(this);} e b const a=_=>{console.log(this);} é se você chamá-lo assim a.call(someVar);, em um , ele irá imprimir someVar, em b , ele irá imprimir window.
Qian Chen
100

Embora usar constpara definir funções pareça um hack, mas vem com algumas grandes vantagens que o tornam superior (na minha opinião)

  1. Isso torna a função imutável, para que você não precise se preocupar com a alteração dessa função por outro código.

  2. Você pode usar a sintaxe da seta gorda, que é mais curta e limpa.

  3. O uso das funções de seta cuida da thisligação para você.

exemplo com function

// define a function
function add(x, y) { return x + y; }

// use it
console.log(add(1, 2)); // 3

// oops, someone mutated your function
add = function (x, y) { return x - y; };

// now this is not what you expected
console.log(add(1, 2)); // -1

mesmo exemplo com const

// define a function (wow! that is 8 chars shorter)
const add = (x, y) => x + y;

// use it
console.log(add(1, 2)); // 3

// someone tries to mutate the function
add = (x, y) => x - y; // Uncaught TypeError: Assignment to constant variable.
// the intruder fails and your function remains unchanged

gafi
fonte
1
E você pode duas vezes declarar função add (x, y), mas você não pode declarar duas vezes const add = ...
TatianaP
33
1. A imutabilidade é um benefício real, mas é muito raro alguém substituir uma função. 2. A sintaxe da seta gorda não é mais curta, a menos que sua função possa ser uma expressão. function f(x, y) {tem 18 caracteres, const f = (x, y) => {21 caracteres e, portanto, mais 3 caracteres. 3. Manter essa ligação apenas importa se as funções forem definidas dentro de um método (ou outra função que tenha significado significativo). No script de nível superior, é inútil. Não estou dizendo que você está errado, apenas que os motivos mencionados não são terrivelmente relevantes.
Nakedible
@ Naked, então, quais são outros motivos válidos?
Anish Ramaswamy
13
Uma vantagem da sintaxe da função antiquada é que, durante a depuração, ela tem um nome.
user949300
3
Eu usaria linters para impedir a vinculação da declaração da função.
Franklin Yu
32

Já se passaram três anos desde que essa pergunta foi feita, mas agora estou me deparando com ela. Como esta resposta está tão abaixo da pilha, permita-me repeti-la:

P: Estou interessado em saber se existem limites para quais tipos de valores podem ser definidos usando const em JavaScript - em funções específicas. Isso é válido? Concedido que funciona, mas é considerado má prática por qualquer motivo?

Fiquei motivado a fazer alguma pesquisa depois de observar um prolífico codificador JavaScript que sempre usa constdeclarações functions, mesmo quando não há motivo / benefício aparente.

Em resposta a " isso é considerado uma má prática por algum motivo? ", Digamos, IMO, sim, é ou pelo menos há vantagens em usar a functiondeclaração.

Parece-me que isso é em grande parte uma questão de preferência e estilo. Existem alguns bons argumentos apresentados acima, mas nenhum tão claro como é feito neste artigo:

Confusão constante: por que ainda uso declarações de função JavaScript em medium.freecodecamp.org/Bill Sourour, guru de JavaScript, consultor e professor.

Peço a todos que leiam esse artigo, mesmo que você já tenha tomado uma decisão.

Aqui estão os principais pontos:

As instruções de função têm duas vantagens claras sobre as expressões de função [const]:

Vantagem # 1: Clareza de intenção

Ao digitalizar milhares de linhas de código por dia, é útil poder descobrir a intenção do programador da maneira mais rápida e fácil possível.

Vantagem # 2: Ordem da declaração == ordem de execução

Idealmente, quero declarar meu código mais ou menos na ordem em que espero que seja executado.

Este é o parâmetro para mim: qualquer valor declarado usando a palavra-chave const fica inacessível até que a execução o atinja.

O que acabei de descrever acima nos obriga a escrever um código que fique de cabeça para baixo. Temos que começar com a função de nível mais baixo e subir nosso caminho.

Meu cérebro não funciona assim. Eu quero o contexto antes dos detalhes.

A maioria dos códigos é escrita por humanos. Portanto, faz sentido que a ordem de entendimento da maioria das pessoas siga aproximadamente a ordem de execução da maioria dos códigos.

JMichaelTX
fonte
1
Você pode comentar um pouco mais sobre a clareza de intenção? Eu recebo o número 2, mas, até onde eu sei, o número 1 é apenas uma (pré?) Reiteração do número 2. Eu posso pensar em um caso, ou seja, funções com sua própria defaultErrorHandlerconst atribuída como uma função anônima que eu possa chamar de manipuladores de promessa. Isso me permitiria 'substituir' opcionalmente esse manipulador de erros padrão nas funções necessárias. Alguns só precisam retornar um objeto de erro e outros precisam retornar uma resposta http, variando os níveis de verbosidade. No entanto, a estrutura do código pode ser um padrão familiar, independentemente.
Jake T.
Talvez minha ideia seja muito complicada! Envolvendo minha cabeça em algumas práticas novas, ainda não gastei muito tempo implementando-as. Apenas descobrindo que eu realmente gosto .then( res.success, res.error )muito mais do que as funções anônimas que declarei apenas chamar res.success(value);. Ter um .then( ..., defaultErrorHandler)padrão comum pode ser bom, com uma função defaultErrorHandler definida de nível superior e, opcionalmente, ter um const defaultErrorHandler = error => { ... }declarado dentro de um escopo de função, conforme desejado.
Jake T.
1
@JakeT. RE "Você pode comentar um pouco mais sobre a clareza de intenção?". Bem, antes de tudo, essa afirmação não foi feita por mim, mas por freecodecamp.org/Bill Sourour, o autor desse artigo. Mas isso faz muito sentido para mim. Se eu ler "function tomorrow ()", eu imediatamente sei que é uma função. Mas se eu ler "const tomorrow = () =>", paro por um momento e analiso a sintaxe em minha cabeça para finalmente determinar: OK, sim, é uma função.
JMichaelTX
1
Outra coisa, se eu tiver um script longo escrito por outra pessoa e desejar ver todas as funções, posso fazer uma pesquisa rápida em "function" para encontrá-las. Ou melhor ainda, eu posso escrever um JS RegEx rápido para extrair todas as funções. IMO, a declaração "const" é apenas para dados (não funções) que NÃO serão alterados.
JMichaelTX
10

Existem alguns benefícios muito importantes para o uso conste alguns diriam que ele deve ser usado sempre que possível, devido à sua deliberação e indicação.

É, até onde posso dizer, a declaração mais indicativa e previsível de variáveis ​​em JavaScript, e uma das mais úteis, PORQUE o quão restrito é. Por quê? Porque elimina algumas possibilidades disponíveis vare letdeclarações.

O que você pode deduzir quando lê um const? Você sabe tudo o que se segue apenas lendo a constdeclaração e AND sem procurar outras referências a essa variável:

  • o valor está vinculado a essa variável (embora seu objeto subjacente não seja profundamente imutável)
  • não pode ser acessado fora do seu bloco imediatamente contendo
  • a ligação nunca é acessada antes da declaração, devido às regras da Zona Mortal Temporal (TDZ).

A citação a seguir é de um artigo que discute os benefícios de lete const. Também responde mais diretamente à sua pergunta sobre as restrições / limites da palavra-chave:

Restrições como as oferecidas lete constsão uma maneira poderosa de tornar o código mais fácil de entender. Tente acumular o maior número possível de restrições no código que você escreve. Quanto mais restrições declarativas que limitam o que um pedaço de código pode significar, mais fácil e rápido é para os humanos lerem, analisarem e entenderem um pedaço de código no futuro.

É verdade que existem mais regras para uma constdeclaração do que para uma vardeclaração: no escopo do bloco, TDZ, atribuir na declaração, sem reatribuição. Considerando que as varinstruções apenas sinalizam o escopo da função. A contagem de regras, no entanto, não oferece muita percepção. É melhor ponderar essas regras em termos de complexidade: a regra adiciona ou subtrai complexidade? No caso de const, o escopo do bloco significa um escopo mais restrito que o escopo da função, TDZ significa que não precisamos varrer o escopo para trás da declaração para identificar o uso antes da declaração, e as regras de atribuição significam que a ligação sempre preservará o escopo. mesma referência.

Quanto mais restritas forem as instruções, mais simples se torna um pedaço de código. À medida que adicionamos restrições ao significado de uma declaração, o código se torna menos imprevisível. Essa é uma das maiores razões pelas quais os programas tipicamente estaticamente são geralmente mais fáceis de ler do que os programas dinamicamente. A digitação estática coloca uma grande restrição no criador do programa, mas também coloca uma grande restrição em como o programa pode ser interpretado, facilitando a compreensão do código.

Com esses argumentos em mente, é recomendável que você use sempre constque possível, pois é a afirmação que nos oferece menos possibilidades de reflexão.

Fonte: https://ponyfoo.com/articles/var-let-const

mrmaclean89
fonte