15 dicas e truques da linguagem JavaScript

No artigo de hoje vou apresentar a você 15 dicas muito boas da linguagem JavaScript, geralmente atalhos de codificação, mas além disso também recursos da linguagem que poucas pessoas conhecem e algumas ‘manhas’ que podem ser muito úteis para programadores JS em geral mas principalmente aos meus alunos do curso de Node.js e MongoDB.

Atenção: nem todas dicas, especialmente os atalhos de código, vão agradar a todo mundo. A intenção é lhe mostrar possibilidades interessantes, mas saber quando é o melhor momento para usar cada uma delas fica à critério do programador (levando em conta a legibilidade do código, por exemplo).

A lista de dicas é composta por:

  1. Testes de Null ou Undefined
  2. Atribuição de Arrays
  3. Operador Ternário
  4. Declarando variáveis
  5. Auto-atribuição de Variáveis
  6. Uso de RegExp
  7. Atalho do charAt()
  8. Exponenciais base-10
  9. ES6 Template Literals
  10. ES6: Arrow Functions
  11. ES6: Argument Destructuring
  12. ES6: Key-Value Names
  13. ES6: Map
  14. ES6: Filter
  15. ES6: Reduce

#1 – Testes de Null ou Undefined

Uma das coisas que logo aprendemos em JavaScript é que nem tudo é o que parece ser e que existem diversas maneiras de uma variável lhe causar problemas em uma linguagem dinâmica como essa. Um teste muito comum de ser feito é para verificar se uma variável está null ou undefined, ou ainda ‘vazia’, como abaixo:

Um jeito bem mais simples de fazer o mesmo teste seria:

Se não acredita, pode testar!

#2 – Atribuição de Arrays

Então você tem de criar um objeto Array e depois popular ele com seus elementos, certo? Provavelmente seu código irá se parecer com isso:

Que tal fazer a mesma coisa em apenas uma linha?

Bacana, hein!

#3 – Operador Ternário

O famoso ‘if/else em uma linha’, o operador ternário já é um velho conhecido de diversos programadores de linguagens C-like como Java e C#. Pois é, ele existe em JS também e pode facilmente transformar blocos de código como esse:

Nisso aqui:

Entendeu agora porque muita gente chama o ternário de ‘if/else em uma linha’?

Mas será que funciona com chamadas de funções também? Se eu tenho duas functions diferentes e quero chamar uma no caso do if ser verdadeiro e outra no caso do if ser falso, corriqueiramente você faria algo assim:

Mas…segure-se na cadeira, talvez você não goste do que vai ver…você pode fazer a mesma chamada de função usando o ternário:

Wow! Aqui no RS temos uma expressão para quando ficamos espantados com algo que é: “me caiu os butiá do bolso“.

Vale uma menção honrosa também aos ifs que testam se uma variável é verdadeira, onde alguns programadores ainda fazem assim:

Quando podem fazer assim:

Ou a versão negada:

Que pode facilmente ser resumida com:

#4 – Declarando Variáveis

Sim, mesmo a declaração de variáveis possui os seus melindres. Embora isso não seja exatamente um segredo, ainda se vê muito programador fazendo declarações como essa:

Quando podia estar fazendo assim:

#5 – Auto-Atribuição de Variáveis

Também outra dica bem comum, ao menos em meus cursos, para, ao invés de auto atribuir valores em variáveis numéricas desta forma:

Os programadores usem versões mais enxutas, como essas:

E se você não conseguiu entender o terceiro exemplo (*=) considere que x=10 e y=5 para as seguintes expressões, verificando o resultado manualmente no seu caderno:

#6 – Uso de RegExp

Expressões Regulares já são, por si só, uma baita ferramenta para criar códigos mais elegantes e poderosos quando o assunto é análise e validações textual, além de extração de dados no caso de alguns tipos de webcrawlers.

No entanto, em JS muitas vezes os programadores usam o objeto RegExp desta maneira:

Quando poderiam estar usando desta maneira:

Eu sei, não é o código mais legível do mundo, mas em situações em que o tamanho do arquivo JS importa, essa é uma excelente dica de minificação de código.

#7 – Atalho do charAt()

Então você quer pegar um caracter apenas de uma String, em uma posição específica, certo? Aposto que a primeira coisa que lhe vem em mente é usar a função charAt, como abaixo:

Mas veja só, você consegue o mesmo resultado lembrando-se daquela analogia da String ser um Array de chars:

#8 – Exponenciais Base-10

Esta é apenas uma notação mais enxuta para números exponenciais na Base-10 ou os famosos ‘números cheios de zeros’. Para quem é mais chegado em matemática não vai se surpreender muito ao ver um desses, mas um número 10.000 pode ser facilmente substituído em JS por 1e4, ou seja, 1 seguido de 4 zeros, como abaixo:

As dicas a seguir são todas da versão 6 do padrão JavaScript, chamada ECMAScript. Essa é a versão de JavaScript que mais utilizo no meu curso de Node.js e MongoDB, e além de mostrá-las na prática durante o curso, registro aqui para quem ainda não é aluno.

#9 – ES6: Template Literals

Essa funcionalidade semântica é exclusiva da versão ECMAScript 6 ou superior e simplifica bastante a leitura de concatenação de strings em conjunto de variáveis. Por exemplo, a concatenação abaixo:

Essa até é simples e provavelmente você já fez concatenações piores. A partir do ES6, podemos fazer esta concatenação usando template literals:

Note que ${} delimitam que dentro vai uma variável que deve ser concatenada, sendo number a mesma, ok? Note também o uso de crase na string ao invés das tradicionais aspas.

#10 – ES6: Arrow Functions

Arrow Functions são formas abreviadas de declarar funções. Sim, mais formas de fazer a mesma coisa que funciona desde a primeira versão do JavaScript. Por exemplo, abaixo uma função de soma:

Também podemos declarar esta function desta forma:

Mas com Arrow Functions podemos levar essa declaração a outro patamar como abaixo:

E se for usar anonymous functions, fica mais fácil ainda, como nos callbacks do Node! Note que o return ficou implícito nessa declaração também, pois ela tem apenas uma linha, então é óbvio o que ela deve retornar.

#11 – ES6: Argument Destructuring

Essa dica é para aquelas functions que são cheias de parâmetros e você decidiu substituir todos por um objeto. Ou então para aquelas functions que realmente exigem um objeto de configuração por parâmetro.

Até aí nenhum problema, afinal quem nunca passou por isso? O problema é ter que ficar acessando o objeto que foi passado por parâmetro seguido de cada propriedade que queremos ler, certo? Tipo isso:

O recurso de argument destructuring (desestruturação de argumentos) serve justamente pra simplificar isso e ao mesmo tempo ajudar na legibilidade de código, substituindo a declaração anterior por essa:

E para completar, ainda podemos deixar valores default em propriedades do nosso objeto-parâmetro:

Dessa forma, o valor de s será “1”, mas o de t será o default para essa propriedade que será “def2”.

#12 – ES6: Key-Value Names

Um recurso muito viciante é a forma abreviada de se atribuir propriedades para objetos. Imagine que você tem um objeto person que tem uma propriedade name que vai ser atribuída através de uma variável name. Isso ficaria assim:

Enquanto que em ES6 você pode fazer assim:

Ou seja, se sua variável possui o mesmo nome da propriedade, não precisa chamar a mesma, apenas passe a variável. O mesmo vale para múltiplas propriedades:

#13 – ES6: Map

Esse operador é muito bacana, me lembra um dos principais motivos pelos quais eu usava JQuery em meus projetos web e desde o ES6 é um recurso nativo do JavaScript!

Para os exemplos de código, considere o array de objetos a seguir:

Imagine agora que queremos pegar apenas os nomes dos animais para, por exemplo, adicionar em outro array. Normalmente faríamos isso:

Mas com o Map, podemos fazer assim:

Note que o map espera uma function por parâmetro com três argumentos: o primeiro é o objeto atual (como em um foreach), o segundo é o índice da iteração atual e o terceiro é o array inteiro. Obviamente esta função será chamada uma vez para cada objeto no array animais.

#14 – ES6: Filter

E se queremos iterar através do mesmo array de objetos animais da dica anterior, mas desta vez retornando apenas aqueles cujo tamanho seja “pequeno”?

Como faríamos isso com JS regular?

No entanto, usando o operador filter, podemos fazê-lo de uma maneira bem menos verbosa e mais clara:

O filter espera uma function por parâmetro com o argumento que é o objeto da iteração atual (como em um foreach) e ela deve retornar um booleano indicando se este objeto fará parte do array de retorno ou não (true indica que ele passou no teste e fará parte).

#15 – ES6: Reduce

Outro recurso importantísimo dessa geração do ECMAScript, o Reduce permite que façamos agrupamentos e cálculos em cima de coleções de maneira muito fácil e poderosa. Por exemplo, se quisermos somar o peso de todos os animais do nosso array de objetos animais, como faríamos?

Mas com reduce podemos fazer assim:

O reduce espera uma function por parâmetro com os seguintes argumentos:

  • o primeiro é o valor atual da variável acumuladora (ao término de todas iterações, ele conterá o valor final);
  • o segundo argumento é o objeto da iteração atual;
  • o terceiro argumento é o índice da iteração atual;
  • o quarto argumento é o array com todos objetos que serão iterados;

Esta function será executada uma vez sobre cada objeto do array, retornando o valor agregado ao término de sua execução.

E você, tem alguma dica para adicionar à esta lista? Deixe nos comentários!

Se você quer aprender a ser um programador Node.js e MongoDB, não deixe de conhecer o meu curso clicando no banner abaixo!

Curso Node.js e MongoDB
Curso Node.js e MongoDB

Como fazer upload de arquivos em Node.js

Eventualmente alguém me pergunta como fazer upload de arquivos em Node.js. Não sei exatamente o motivo que me perguntam isso, uma vez que não é algo exatamente difícil, mas como é um assunto que já está na minha pauta de tanto que pedem, resolvi fazer este tutorial pra ajudar o pessoal.

Parto do princípio aqui que você já sabe o básico de Node.js, JavaScript e de HTML, conhecimentos estes que podem ser obtidos em outros artigos aqui do blog, em meu livro, em meu curso ou até mesmo no meu canal do Youtube.

Vamos começar instalando o express-generator, pacote que nos ajuda a criar aplicações web com ExpressJS, o mais famoso web framework para Node.js (talvez você precise de permissão de administrador):

Agora mande criar um novo projeto Express usando o comando abaixo, onde chamo o projeto de fileupload:

Após entrar na pasta e instalar as dependências com npm install, instale a dependência formidable, que utilizaremos para lidar com o upload de arquivos em Node.js, dentre tantas alternativas existentes na Internet.

Agora vá na pasta views e abra o arquivo index.ejs para editarmos o HTML do projeto, deixando-o como abaixo:

Note que não tem nada demais aqui, apenas um formulário com um campo de upload de arquivo. Se você executar esta aplicação com npm start verá algo como abaixo:

Formulário de Upload
Formulário de Upload

Agora vamos programar o comportamento desta página. Fazemos isso indo na pasta routes e abrindo o arquivo index.js, onde temos as rotas da tela inicial.

Adicione a nova rota abaixo dentro deste arquivo:

O que fazemos aqui? Carregamos a extensão formidable que instalamos há pouco, recebemos o form POSTado pelo usuário e salvamos o arquivo através da função form.parse. Se você testar agora já deve estar funcionando.

File Uploaded
File Uploaded

Mas…onde que o arquivo foi salvo?

Por padrão ele fica salvo em uma pasta temporária no seu computador. Para mudar isso, vamos modificar nosso código anterior para que usando a biblioteca fs (file system) do Node possamos mover o arquivo que fizemos upload para uma outra pasta da sua máquina (minha máquina é Unix, logo adapte o caminho de pastas para sua máquina):

Note que carreguei o módulo fs lá no início do código e que depois uso este módulo para mover o arquivo de lugar no sistema operacional usando a função rename. O arquivo que fiz upload é facilmente encontrado usando o argumento files, que é o terceiro da função form.parse. O resultado na tela é esse:

File Moved
File Moved

Mas no seu computador o arquivo que você fez o upload estará disponível na pasta que você mandou salvar.

Fácil, não é?!

Curtiu este tutorial? Conheça o meu curso online de Node.js e MongoDB para fazer aplicações web e APIs incríveis com esta fantástica plataforma. Basta clicar no banner abaixo!

Curso Node.js e MongoDB

Autenticação em Node.js com Passport – Parte 2

Atualizado em 26/08/2018!

Este post é uma continuação do tutorial de como implantar um mecanismo de autenticação completo em Node.js usando o middleware Passport. No tutorial passado fizemos funcionar a autenticação através de uma tela de login e impedimos que usuários anônimos entrem na tela de chat.

Nesta segunda parte vamos criar a tela de cadastro de usuário (Sign Up) e a tela de recuperação de senha (Forget Password), além que aprenderemos a enviar emails em Node.js.

  1. Criando o cadastro de usuário
  2. Aprendendo a enviar emails
  3. Criando a recuperação de senha

Se quiser ver este mesmo tutorial em formato de video aula, confira o meu curso online de Node.js e MongoDB. Caso prefira apenas o texto mesmo, vamos lá!

#1 – Criando o cadastro de usuário

No tutorial anterior deixamos nosso banco preparado e a conexão compartilhada em uma variável global.db. Usaremos esta conexão global para fazer as operações de banco necessárias. Também usaremos o mesmo módulo bcrypt para criptografar as senhas no banco.

Para começar, vamos criar a nossa tela de cadastro de usuário que pedirá username, password e email, chamei ela de views/signup.ejs:

Note que este form faz um POST para uma rota /users/signup e que ele já espera uma message no model para exibir erro, caso dê algum problema. Faremos isso tudo funcionar depois.

Para que essa view possa ser exibida, primeiro vamos criar um novo arquivo de rotas em routes/users.js. Aqui colocaremos todas as rotas relacionadas a usuários, a começar pela rota que exibe a view que acabamos de criar via GET:

Note que já fiz o teste para passar ou não uma mensagem de falha para a tela no model, pra não dar erro na minha view. Agora para que essa rota passe a funcionar, temos de configurar nosso app.js, como abaixo:

Salve tudo e mande rodar sua aplicação para ver ela funcionando no navegador (use o link de “Não possui cadastro?” que deixamos prontos na tela de login):

Cadastro de Usuário
Cadastro de Usuário

Note que para acessar essa tela a rota é /users/signup. Isso porque definimos no app.js que rotas ‘/’ são tratadas pela index.js e rotas ‘/users’ são tratadas pela users.js, ou seja, há um roteamento inicial com ‘/users’ e depois o outro roteamento com ‘/signup’, virando ‘/users/signup’ a rota completa.

Agora, antes de sair programando a rota POST /users/signup que está em nosso HTML FORM, devemos criar a função JS que vai salvar um novo usuário no MongoDB. Para armazenar não apenas essa mas outras funções relacionadas a banco de dados (que não são de autenticação, pois estas deixamos no arquivo auth.js), vamos criar um arquivo db.js na raiz do nosso projeto. Dentro dele, vamos criar e expor uma função createUser, como abaixo:

Aqui eu pego a senha plain-text enviada pela view e gero o hash dela usando um salt de 10 rounds, que foi o que achei como sendo seguro atualmente, embora esta resposta dê um panorama mais completo de como calcular isso se seu sistema realmente precisar de uma segurança acima da média (bancos?). Ao final do processo, chamo uma função de callback que a createUser espera como último parâmetro.

Com esse módulo db.js pronto, programar essa rota de /users/signup será bem simples! Vá em routes/users.js e adicione uma rota POST para /signup, como abaixo (lembrando que o path /users já é tratado no app.js):

Aqui eu carrego o módulo ‘db’ que acabamos de criar e com ele chamo a função createUser, passando os dados enviados no corpo da requisição HTTP: username, password e email. Como último parâmetro, passo uma arrow function como callback, que apenas vai redirecionar para a tela de login em caso de sucesso e para a própria tela de signup em caso de fracasso, onde uma mensagem de erro será exibida.

Execute novamente sua aplicação e teste a criação de usuário. Se tudo deu certo, após a criação você poderá se autenticar na tela de login usando esse novo usuário.

Mas o que você acha de mandarmos um email de boas vindas para esse usuário que recém se cadastrou?

Curso Node.js e MongoDB
Curso Node.js e MongoDB

#2 – Aprendendo a enviar emails

Após o usuário se cadastrar, vamos enviar um email de boas vindas para ele. Além de ser algo interessante, fazer a lógica de envio de emails será útil na próxima etapa do tutorial, que é reset de senha por email.

Para fazer o envio de emails vamos usar um módulo chamado Nodemailer, que deve ser instalado via linha de comando usando o NPM:

Depois, vamos criar um módulo mail.js na raiz do nosso projeto, com o seguinte código:

Nosso módulo mail.js apenas expõe uma função que espera o destinatário da mensagem (to), o assunto (subject) e o texto (text). Por fim, a função sendMail faz o serviço propriamente dito.

Note que as configurações de SMTP para envio de email estão definidas em variáveis de ambiente, assim como fizemos na parte 1 deste tutorial para guardar a connection string do MongoDB.

Não esqueça que para que essas variáveis de ambiente funcionem, você deve adicionar o modelo delas no arquivo .env.example (é um arquivo oculto, você só vai conseguir ver ele com VS Code ou no terminal):

E com os valores finais no arquivo .env:

Aqui usei minha conta de email na Umbler para enviar os emails (você pode criar sua conta lá e ganhar créditos de graça para gastar com um email que custa centavos por mês). Como é uma aplicação de teste que vai enviar poucos emails, não vamos ter problemas. No entanto, caso queira usar o nodemailer para enviar muitos emails, você rapidamente será bloqueado em qualquer provedor de hospedagem. O certo é usar serviços de SMTP Gateway como Amazon SES, Mandrill e SendGrid.

Agora, para usarmos este módulo e finalmente fazer o envio de email de boas vindas funcionar, adicione apenas uma linha a mais em nossa rota POST em users.js:

Obviamente você pode personalizar essa mensagem livremente, ao invés do “email espartano” que deixei configurado. Soluções mais profissionais geralmente envolvem criar templates HTML que são lidos usando o módulo ‘fs’, algumas variáveis dentro do template são trocadas e depois a string resultante é enviada como HTML.

Rode novamente sua aplicação com ‘npm start’ e realize o cadastro de um novo usuário, mas informando um email válido, para que a mensagem chegue e você possa ver o resultado no seu webmail.

Email enviado via Node.js
Email enviado via Node.js

#3 – Criando a recuperação de senha

Agora a próxima parte é a de recuperação de senha. Lembra que deixamos um link pra isso lá na tela de login?

Vamos começar criando uma nova view, a views/forgot.ejs, com um formulário bem simples que pede a confirmação de seu email para envio de uma nova senha:

E para que essa tela seja acessível, vamos criar uma nova rota GET em routes/users.js:

Rodando sua aplicação e acessando no navegador, já deve ser possível navegar até esta página usando o link na tela de login:

Esqueceu a senha
Esqueceu a senha

Para fazer funcionar este formulário, vamos começar criando duas funções em nosso arquivo db.js: uma que busca um usuário pelo seu email e outra que muda a senha de um usuário:

A primeira função é bem simples, um findOne por email, que executa um callback após encontrar (ou não) o usuário. A segunda recebe uma senha, criptografa ela e sobrescreve o hash de senha do usuário cujo id foi passado por parâmetro. O module.exports no final do db.js também foi atualizado de acordo.

Note que não estou criando as devidas validações em nenhum formulário para os artigos não ficarem gigantescos. Nem de campos obrigatórios, nem validações de regras de negócio como não permitir usuários e emails duplicados. Tenha em mente que você deverá implementar essas questões se for usar esses códigos em produção.

Antes de sairmos fazendo a rota POST, vamos criar um arquivo utils.js na raiz do nosso projeto e colocar dentro dele uma função de geração de senha aleatória:

Esta função é bem simples e talvez você até queira usar alguma mais avançada. Aqui eu crio e retorno uma senha aleatória de 10 caracteres alfanuméricos (maiúsculas, minúsculas e números).

Agora que temos estas funções podemos criar a nossa rota POST que vai receber os dados do formulário de “esqueci minha senha”. Abra o arquivo routes/users.js e crie a nova rota:

Aqui começamos com o findUser que criamos anteriormente, que busca usuário por email. Caso não encontre, vamos jogar o usuário para a tela de login mesmo assim, embora você possa pensar em algo mais criativo para fazer.

Caso encontre, mandamos gerar uma nova senha usando a função que criei há pouco e uso o changePassword para mudar a senha do usuário que possui o email especificado (em um sistema de produção, para evitar problemas, além do email, peça alguma informação pessoal do usuário para confirmar esse processo de troca de senha). Por fim, um email é enviado com a senha que acabou de ser gerada, como na imagem abaixo.

Nova senha
Nova senha

Se você tentar se autenticar com a senha antiga, notará que ela não funciona mais, somente a nova.

É uma boa prática guardar o hash das últimas senhas do usuário e não deixar que ele use senhas antigas (mesmo senhas aleatórias podem conflitar ocasionalmente). Outra boa prática seria no primeiro login com a nova senha ele ser solicitado a cadastrar uma senha pessoal ao invés dessa aleatória. Enfim, sempre há margem para melhorar quando o assunto é segurança.

Não é exatamente uma parte 3, mas este tutorial sobre JSON Web Token ajuda a preencher a lacuna de autorização (visto que até o momento vimos apenas autenticação). No caso de estar utilizando arquitetura microservices, é uma boa colocar sua autenticação vinculada a regras de autorização no seu API Gateway.

Até a próxima!

Curtiu o post? Então clica no banner abaixo e dá uma conferida no meu livro sobre programação web com Node.js ou clique neste link para conhecer o meu curso online!