Por que usar `const foo = () => {}` em vez de `function foo () {}`

12

Por exemplo, neste vídeo Redux , o instrutor sempre usa sintaxe como

const counter = (state=0, action) => {
   ... function body here
}

onde eu usaria apenas o "tradicional"

function counter(state=0, action) {
   ... function body here
}

O que é realmente mais curto e, na IMO, mais claro. É mais fácil digitalizar a borda esquerda da página, razoavelmente uniforme e estruturada, para a palavra "função" do que digitalizar a borda direita irregular por um pequeno "=>".

Além de this, e tentando ser objetivo, não opinião, existe alguma diferença ou vantagem útil na sintaxe nova?

user949300
fonte
3
Esta pergunta no StackOverflow pode lhe interessar: stackoverflow.com/questions/34361379/…
Vincent Savard
3
Não sou especialista em JavaScript, mas acho que constajuda a garantir que a função não seja redefinida mais tarde.
MetaFight
Obrigado @VincentSavard, isso é perfeito, e basicamente o que eu esperava: Além de "this" e coisas de protótipo / classe, parece não haver diferença real.
user949300
3
@ user949300 Não é uma diferença, o MetaFight menciona. Além disso, protype / "essas coisas" rapidamente se tornam distinções críticas também.
precisa saber é
11
Resumindo a história: você deve valorizar de forma clara e concisa um benefício de ponta.
Wayne Bloss

Respostas:

11

As instruções de função (funções nomeadas, segunda sintaxe mostrada) são levantadas no topo do escopo lexical completo, mesmo aquelas atrás de blocos arbitrários e de controle, como ifinstruções. O uso de const(like let) para declarar uma variável fornece a ela o escopo do bloco, interrompe a elevação completa (elevação para o mero bloco) e garante que ela não possa ser declarada novamente.

Ao concatenar scripts juntos, ou alguns usando outras ferramentas de criação de pacotes, a função de elevação pode interromper scripts conflitantes de maneiras difíceis de depurar, pois falham silenciosamente. Um re-declarado constlançará uma exceção antes que o programa possa ser executado, portanto é muito mais fácil depurar.

dandavis
fonte
Obrigado. boa resposta. Trabalhei principalmente em projetos JS menores ou em servidores node.js, onde eles têm um bom sistema de módulos para namespacing. Mas apenas iniciar um projeto mais do lado do cliente usando bundlers e isso é uma boa ideia.
user949300
2
Apenas uma observação de que o eslint no-func-assign pode pegar esse problema de redeclaração.
user949300
2
Escrever código com sinais confusos para obter os benefícios de uma linguagem de tipo estaticamente é um motivo para usar o Typecript, não const. É um pouco míope, IMO, começar a usar em constqualquer lugar por esse motivo na era do eslint, webpack, babel e assim por diante. Ninguém mais concatena arquivos manualmente manualmente há pelo menos uma década.
Wayne Bloss
2

Eis por que você deve usar function:

  1. A sinalização é clara e concisa. Isso é muito mais benéfico do que qualquer uma das preocupações de içamento da borda listadas na outra resposta.

  2. Você realmente deseja içar dentro dos módulos porque, como você pode ver no código abaixo, a constdeclaração de tryDoTheThingfalha falha silenciosamente e não será capturada até que você tente chamá-la.

  3. A maioria dos juniores com quem eu entrei em contato começa consta declarar todas as funções porque é uma moda passageira no momento, como usar espaços sobre guias ou criar tudo functional!!!porque "OOP está ruim". Não faça isso. Você não quer ser aquele cara que segue modismos sem entender completamente as implicações.

via https://gist.github.com/stephenjfox/fec4c72c7f6ae254f31407295dc72074


/*
This shows that, because of block-scoping, const function references must be
invoked in-order or else things will fail silently.
const's are added the name space serially (in the order in which they appear)
and much of the body isn't declared when we first try to invoke or functions
*/


const tryDoTheThing = () => {
  console.log(`This is me trying to be awesome ${getAwesome()}`)
}


// "getAwesome is not defined", because it is referenced too early
tryDoTheThing() // comment to see the rest work


const getAwesome = () => (+((Math.random() * 10000).toString().split('.')[0]))


const doTheThing = () => {
  console.log(`This is awesome! ${getAwesome()}`)
}

doTheThing() // prints

vs

/*
Function declarations are given two passes, where the first lifts them to
the top of the namespace, allowing "out of order" usage
*/

doTheThing();


function doTheThing() {
  console.log(`This is awesome number ${getAwesome()}`)
}

function getAwesome() {
  return (+((Math.random() * 10000).toString().split('.')[0]))
}
Wayne Bloss
fonte