Executando verificação de segurança...
3

Declarativo vs Imperativo (Javascript)

Funções declarativas informam oque deve ser feito e não como. Como podemos ver no exemplo a função map() aplica a função anônima (arrow function) (numero) => numero * numero a cada elemento do array numeros. O resultado é um novo array quadrados, que contém os quadrados dos elementos do array original.

const numeros = [1, 2, 3, 4, 5];
const quadrados = numeros.map((numero) => {
  return numero * numero;
});
console.log(quadrados); // Output: [1, 4, 9, 16, 25]

Já funções imperativas é necessário informar como deve ser feito. O loop for controla explicitamente o fluxo do programa, percorrendo cada elemento do array numeros, calculando o quadrado do elemento atual e adicionando-o ao array quadrados. O resultado é o mesmo que no exemplo declarativo, mas a abordagem imperativa descreve mais detalhadamente como o programa deve realizar a tarefa.

const numeros = [1, 2, 3, 4, 5];
const quadrados = [];

for (let i = 0; i < numeros.length; i++) {
  const numero = numeros[i];
  const quadrado = numero * numero;
  quadrados.push(quadrado);
}

console.log(quadrados); // Output: [1, 4, 9, 16, 25]
Carregando publicação patrocinada...
2

Tem vantagens e desvantagens em fazer quaisquer dos dois e muitas vezes é mais questão de gosto.

Uma grande desvantagem do jeito mais declarativo é que em problemas complexos pode ficar bem complicado fazer, até por não ter tanto controle de como o fluxo anda, por exemplo quando tem uma situação de break. E quando muda o estado interno pode ser muito fácil cometer erros porque o jeito de captura de variável em uma closure não é entendido por todo mundo, e mesmo quem entende precisa tomar muito mais cuidado. Para problemas simples só a performance do declarativo sempre bem pior é o problema. Se precisa ou não dela é outra questão.

Para problemas simples a desvantagem do modo imperativo é só que você tem que fazer o controle na mão, mas nem fica tão longo qunto pode parecer, se fizer da forma mais idiomática:

const numeros = [1, 2, 3, 4, 5];
const quadrados = [];
for (let i = 0; i < numeros.length; i++) quadrados.push(numeros[i] * numeros[i]);
console.log(quadrados); // Output: [1, 4, 9, 16, 25]

Dá para fazer em menos linhas, mas não acho que fica legal e não deve ser a prioridade. Em caracteres dá quase o mesmo. De qualquer forma mais curto não é o mesmo que mais legível.

Legibilidade é algo contextual, para algumas pessos um pode ser mais legível que o outro, não é algo universal. Em casos mais complexos é difícil alguém achar o funcional mais legível, mas tem alguns.

Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente. Para saber quando, me segue nas suas plataformas preferidas. Quase não as uso, não terá infindas notificações (links aqui).

1

Realmente é mais rápido o código imperativo. Mas particularmente prefiro o Declarativo, pois consegui aprender de forma mais acertiva com ele. Sou desenvolvedor há 3 anos por isso acho que tenho essa visão. Geralmente devs mais experientes gostam da forma imperativa.

Obs: Fui clicar achando que estava mudando de comentario, mas era o botão de avaliação e acabei selecionando o "não achei relevante", mas foi muito. Eles poderiam colocar icones mais usuais sobre gostar ou não. Após as 72h irei avaliar novamente para positivo

2

Só pra constar (e desviando um pouco do assunto principal), quando uma arrow function só tem um parâmetro, os parênteses podem ser omitidos. E quando ela só tem uma única expressão, as chaves e a própria palavra return também podem ser omitidas. Ou seja, poderia ser apenas:

const numeros = [1, 2, 3, 4, 5];
const quadrados = numeros.map(numero => numero * numero);

E para fazer um loop pelos elementos, caso você não precise do índice (e somente dos valores), pode usar for..of:

const numeros = [1, 2, 3, 4, 5];
const quadrados = [];
for (const numero of numeros) {
    quadrados.push(numero * numero);
}

Por fim, outra solução é criar o array com o tamanho correto e só ir setando os índices um a um:

const numeros = [1, 2, 3, 4, 5];
const quadrados = Array(numeros.length);
for (let i = 0; i < numeros.length; i++)
    quadrados[i] = numeros[i] * numeros[i];

Fazendo um teste rápido aqui com o Benchmark.js, esta solução se mostrou a mais rápida de todas (e a diferença aumenta ainda mais conforme o array cresce).

Claro que para poucos arrays pequenos não importa, a diferença será irrisória (para poucos dados, tudo é rápido), mas se precisar processar muitos arrays grandes, pode começar a fazer diferença e é importante saber desses detalhes.

E aí a escolha vai muito além de "imperativo vs declarativo", tem muito mais a ver com saber como cada solução funciona. O map (e seus "amigos funcionais" reduce, filter, forEach, etc) recebe como parâmetro uma função de callback. Ou seja, para cada elemento do array, haverá uma chamada de função, e isso tem o seu custo. Com o loop simples, essas chamadas não ocorrem e daí a diferença (mas for..of, por sua vez, usa o protocolo de iteradores, que nas implementações atuais não está tão eficiente e dependendo do caso fica pior que map).

Sobre "devs mais experientes gostam da forma imperativa", acho que é mais o seu viés. Já vi pessoas experientes que gostam mais de um ou do outro, ou de ambos (e escolhem qual usar conforme as circunstâncias, analisando o contexto - como aliás deveria ser para qualquer coisa na nossa área).

1
1

É, uma pena que seja tão fácil cometer o erro do voto, já aconteceu comigo, e acho ruim não poder desfazer o voto. É um erro do sistema o limite de 1 voto por 72 horas valer para votos diferentes, mas enfim. Obrigado por justificar.