36 conceitos para se tornar um Expert em JavaScript

Foto por NESA by Makers no Unsplash

Você vai ouvir muitas pessoas reclamando que JavaScript é estranho e às vezes inútil. As pessoas reclamam assim porque não entendem como as coisas funcionam nos bastidores. Embora eu concorde que alguns cenários em JavaScript sejam tratados de maneira diferente, isso não o torna estranho, mas bonito à sua própria maneira.

Para começar a amar uma linguagem de programação, você deve começar examinando profundamente e dominando seus conceitos um por um.

Aqui está uma lista de 36 conceitos de JavaScript que você precisa dominar para se tornar um especialista em JavaScript completo.

Observação: A maioria dos títulos não foram traduzidos, para o leitor se familiarizar com os termos originais.

Aqui temos um repositório do Tiago Boeing explicando 33 conceitos de JavaScript

1. Execução de Call Stack.

Todo mundo já ouviu falar do site Stack Overflow.
Mas você sabe o que significa o verdadeiro stack overflow? Stack overflow ( ou Estouro de Pilha em português literal ) é um erro associado as operações de call stack.

Entendendo a Call stack, você vai entender como uma linguaguem de alto-nivel como JavaScript é executado.

Recomendo esse artigo do MDN , para entender melhor sobre Call Stack.
Esse artigo da Thais Ribeiro é ótimo para entender o assunto

2. Tipos de dados Primitivos

const foo = "bar";
foo.length; // 3
foo === "bar"; // true

Espere!

Quando você declara o valor de bar na constante foo, ela é do tipo primitivostring. Isso está ok para todo mundo. Mas como você consegue acessar a proprieadade length de uma string primitiva?

Estranho? Não.

Essa feature se chama autoboxing. No exemplo acima, o JavaScript envolve a constante em um objeto temporário e, em seguida, acessa a propriedade length desse objeto. Depois que essa etapa for concluída, o objeto é descartado com segurança.

Tendo conhecimento profundo dos tipos de dados primitivos, você saberá como eles são armazenados na memória até o ponto de sua representação binária. Você também saberá como essas situações “estranhas” ocorrem e a razão lógica por trás delas.

Leia aqui mais sobre Tipos de Dados Primitivos no MDN ou esse ótimo artigo do Guilherme Alves

3. Tipos de Valor e Valores por Referência (Value Types e Reference Types)

Recentemente, tive alguma confusão sobre como o conceito de “passagem por referência” (pass by reference) funciona no JavaScript.
Embora eu estivesse soubesse dos conceitos de “passagem por referência” e “passagem por valor” em linguagens como C e Java, não tinha certeza de como isso funcionava no JavaScript.

Você sabia que variáveis atribuídas a valores não primitivos em JavaScript recebem uma referência a esse valor?
A referência aponta para o local da memória onde o valor está armazenado.

var arr1 = [1,2,3];
var arr2 = arr1;
arr2.push(10);
console.log(arr2);
//[1, 2, 3, 10]
console.log(arr1);
//[1, 2, 3, 10]

No exemplo acima, qualquer mudança em arr2, vai refletir em arr1também. Isso porquê ele só atribui a referência ao valor, não o valor atual.

Ao compreender este conceito de tipos de valor e tipos de referência, você terá um melhor entendimento de como as variáveis são atribuídas com valores e referências de memória.

Leia mais Aqui:
Diferença entre valor e referência em JavaScript — Brazil JS
Objetos — Referências de valores em JavaScript — Blog DA2K

4. Coerção de Tipos

Esse conceito explica principalmente a diferença entre coerção de tipo implícita e explícita. Esta é uma das poucas áreas em JavaScript em que as pessoas erram.
Isso é especialmente verdadeiro com o conceito de coerção de tipo implícita, porque ele se comporta de maneiras diferentes com tipos de dados diferentes.

Esta é uma das áreas de JavaScript mais testadas em entrevistas.

Number('789')   // explicito
+'789' // implicito
789 != '456' // implicito
9 > '5' // implicito
10/null // implicito
true | 0 // implicito

Ao compreender a coerção de tipo de forma clara, você pode ficar feliz por ter um ótimo entendimento de um dos conceitos mais complicados do JavaScript.

Leia mais Aqui:

Explicando a coerção de tipos em Javascript por Allan Ramos
Air BNB JS Style Guide — Casting e Coerção de Tipos
Coerção de tipos em Javascript — por Cristiano Gonçalves

5. Comparação de Igualdades e o operador ‘typeof’

Este conceito explica basicamente o uso de duplos iguais e triplos iguais, e quando e por que você deve usá-los. Embora pareçam iguais na superfície e forneçam os mesmos resultados na maioria das vezes, eles podem gerar bugs inesperados se você usá-los sem saber.
Você também deve ser capaz de usar o operador typeof e conhecer as possibilidades das saídas. Pode ficar confuso quando os objetos entram em jogo.

typeof 3 // "number"
typeof "abc" // "string"
typeof {} // "object"
typeof true // "boolean"
typeof undefined // "undefined"
typeof function(){} // "function"typeof [] // "object"
typeof null // "object"

6. Escopo do JavaScript

Os escopos são um dos conceitos, acredito, que deve ser aperfeiçoado no início de sua jornada JS. De acordo com Wissam, a definição simples de escopo é que é onde o compilador procura variáveis e funções quando precisa delas.

Compreender os escopos permitirá que você use o JavaScript de forma mais eficiente e eficaz.
Você deve aprender sobre o escopo global e o escopo do bloco e da função, também conhecido como escopo léxico.
O escopo JS pode parecer um tanto confuso no início, mas depois que você entender como as coisas funcionam nos bastidores, será muito emocionante trabalhar com ele.

7. Declarações e Expressões

Essas são as duas principais categorias sintáticas em JavaScript. Você deve saber a diferença entre esses dois e como as declarações são avaliadas.
Isso permitirá que você obtenha uma compreensão geral de como seu código é estruturado como expressões e instruções.
Você notará que a maior parte do seu código é composta por expressões, embora tenha um número menor de instruções, comparativamente.
Você também poderá evitar bugs resultantes do uso indevido desses dois.

8. Immediately Invoked Function Expressions e Módulos

As Expressões de Função Imediatamente Invocadas (IIFEs) são funções executadas assim que são definidas.
Eles são usados principalmente para evitar poluir o escopo global.
Mais tarde, os módulos ES6 foram introduzidos, fornecendo uma maneira padrão de evitar a poluição de escopo global — embora algumas pessoas acreditem que não seja uma substituição direta dos IIFEs.
Ao compreender os IIFEs e os módulos, você pode criar aplicativos com menos bugs devido ao manuseio incorreto do espaço global.
Com os módulos, no entanto, você pode fazer várias coisas.

9. Message Queues e Loops de Eventos

Como diz o documento MDN, o JavaScript tem um modelo de simultaneidade baseado em um loop de eventos, que é responsável por executar o código, coletar e processar eventos e executar subtarefas enfileiradas.
Este modelo é bastante diferente dos modelos em outras linguagens, como C e Java.
As messages queues são usadas no modelo de simultaneidade acima para lidar com mensagens que começam pela mais antiga.
As mensagens são adicionadas sempre que ocorre um evento e há um ouvinte de evento anexado a ele.
Ao compreender esses conceitos, você obtém um melhor entendimento de como JS funciona nos bastidores e consegue interpretar seu código.

10. Intervalos de Tempo

Para agendar uma chamada ou função em JavaScript, você usa dois métodos.

  • setTimeout nos permite executar uma função uma vez após um intervalo de tempo específico.
  • setIntervalnos permite executar uma função repetidamente, começando após um intervalo de tempo específico e, em seguida, repetindo continuamente nesse intervalo.

De certa forma, eles estão relacionados ao conceito anterior de filas de mensagens e manipuladores de eventos. Portanto, ao compreender os métodos de intervalo de tempo, podemos entender como eles funcionam e como usá-los com eficiência em nossos casos de uso.

11.Engines de JavaScript

Estamos nos aprofundando no JavaScript agora. Um motor JavaScript é um programa de computador ou um interpretador que executa o código JavaScript. Um mecanismo JavaScript pode ser escrito em uma ampla variedade de linguagens. Por exemplo, o mecanismo V8 que aciona o navegador Chrome foi escrito em C ++, enquanto o mecanismo SpiderMonkey que aciona o navegador Firefox foi escrito em C e C ++. É essencial que você entenda em qual mecanismo JavaScript está trabalhando para escrever um código eficiente. Os desenvolvedores móveis que usam um webview devem estar especialmente cientes disso.

12. Operações Bitwise

Essas operações tratam os valores como bits (0s e 1s), em vez de números decimais, hexadecimais ou octais.
Operadores bit a bit realizam suas operações em tais representações binárias, mas eles retornam valores numéricos JavaScript padrão.
Geralmente, você não usaria essas operações em seu código, mas elas têm alguns casos de uso.
Você pode usá-los para encontrar valores pares e ímpares, conversões de cores, extração de cores e sinalizadores de configuração.
Conhecendo essas operações bit a bit completamente, você pode trabalhar com tecnologias como WebGL muito bem, pois inclui muita manipulação de pixels.

Leia mais: Operador Bitwise XOR

13. DOM e a Árvore de Layout

A maioria de nós já ouviu falar sobre o Document Object Model (DOM), mas apenas alguns de nós o conhecem em profundidade. Você sabia que o que você vê no navegador não é o DOM?
É mais a árvore de renderização, que na verdade é uma combinação de DOM e CSSOM.
Ao entender como o DOM funciona, como é estruturado e como uma página é renderizada, somos capazes de manipular nossa página da web dinamicamente com a ajuda de JavaScript.
Isso é especialmente necessário para garantir que o desempenho de nosso aplicativo seja de alto padrão.

14. Classes e Factories

JavaScript não é uma linguagem orientada a objetos.
No entanto, a fim de imitar as propriedades OOP, funções construtoras foram usadas.
De acordo com Tania, “Classes em JavaScript não oferecem realmente funcionalidade adicional e são frequentemente descritas como fornecendo açúcar sintático sobre protótipos e herança, pois oferecem uma sintaxe mais limpa e elegante. Como outras linguagens de programação usam classes, a sintaxe de classe em JavaScript torna mais fácil para os desenvolvedores se moverem entre os idiomas.
“ Uma factory function é uma função que não é uma classe ou um construtor que retorna um objeto. ”
De acordo com o guru do JS Eric Elliot,
“Em JavaScript, qualquer função pode retornar um novo objeto. Quando não é uma função construtora ou classe, é chamada de factory function.”

Você deve ter um bom entendimento desses dois conceitos, especialmente quando começar a desenvolver aplicativos que são maiores em tamanho e escala.

15. ’this’ e os métodos ‘apply’, ‘call’, e ‘bind’.

Pessoalmente, acho que é crucial para um desenvolvedor JS entender a palavra-chave ‘this’. Se você não entender corretamente, encontrará vários problemas com seu aplicativo mais tarde.

Se você tiver um bom conhecimento da palavra-chave this, poderá se compreender os métodos apply , call, ebind .

Esses métodos são necessários para invocar funções com o contexto apropriado. Você precisará especialmente do método bind ao passar um retorno de chamada que usa this.

16. Funções Construtoras e o operador ‘instanceOf’

As funções construtoras são como funções comuns.
Mas elas têm algumas diferenças.
Por convenção, o nome da função começa com uma letra maiúscula e só deve ser executada com o operador new.
A palavra-chave new será familiar para programadores com experiência em OOP.
Para identificar corretamente o tipo de um objeto, usamos o operador instanceof.
Em termos simples, ele verifica se um objeto é uma instância de outro. Isso ajudará você a entender como os objetos são herdados uns dos outros.
A herança é obtida por prototypes.

MDN: Construtores e instâncias de objeto

17. Prototypes

Este é um dos conceitos mais confusos em JavaScript, mesmo para alguém com dez anos de experiência.

Prototypes em JavaScript são o mecanismo para compartilhar funcionalidades comuns entre objetos. Quase todos os objetos em JavaScript são instâncias de Object. Um objeto típico herda todas as propriedades e métodos de Object.prototype. Em termos simples, um prototype é um objeto do qual os objetos JavaScript herdam métodos e propriedades. Ao compreender melhor os prototypes, você pode construir aplicativos que sejam eficientes e rápidos.

Dominando o uso de protype com Javascript

18. Criando objetos com ‘new’, ‘Object.create’, e ‘Object.assign’

Existem muitas maneiras de criar um objeto em JavaScript. Mas há um motivo pelo qual alguém escolheria o método Object.create em vez da palavra-chave new. Ao usar o método Object.create, você pode usar um objeto existente como protótipo do objeto recém-criado. Isso permitirá que você reutilize propriedades e funções de um objeto existente, de forma semelhante ao conceito de herança em OOP.

Ao usar o método Object.assign, você pode copiar propriedades próprias enumeráveis de um ou mais objetos de origem para um objeto de destino. Nessa situação, o protótipo do objeto de destino não contém as propriedades do objeto de origem. Essa é a principal diferença entre esses dois métodos.
Ao compreender essas três formas de criação de objeto, você pode usá-las apropriadamente em seus aplicativos, de acordo com seus casos de uso, para criar programas com uso eficiente de memória.

19. Os métodos ‘map’, ‘filter’, ‘forEach, e ‘reduce’

Esses quatro métodos são muito úteis quando se trata de manipulação de array. Eles são encontrados no protótipo do Array.

Se você precisa alterar os valores de cada elemento de um Array, sem gerar um novo array, apenas alterando o array original, utilize o método forEach.

Se você tem um array e quer fazer algo para / com cada elemento e retornar um novo array, então você deve usar o método map.

O métodoreduce executa uma função redutora em todos os elementos de uma array e, finalmente, retorna um valor no final. Um exemplo perfeito seria encontrar a soma de todos os elementos em um array.

Se você tiver uma array e quiser executar uma condição em cada elemento e obter os valores que passam na condição, você deve usar o métodofilter.

Observe que os três métodos acima não modificam / alteram os valores da Array original.

Leia mais: JavaScript: Entendendo a diferença entre map x forEach — por Thiago S.Adriano

Array — MDN

20. Funções Puras, Side Effects, e State Mutations

Esses três conceitos são muito importantes para um desenvolvedor JavaScript.
A mutação de estado é especialmente importante para desenvolvedores que trabalham com React.

Uma função pura é uma função que sempre retorna um valor consistente com a entrada fornecida, sem acessar / alterar nenhuma variável fora de seu escopo. Esse tipo de função é mais fácil de ler, depurar e testar.

Os Side Effects são um trecho de código por meio do qual uma variável é criada e disponibilizada em todo o escopo quando não é necessário. Se sua função estiver acessando uma variável que está fora do escopo, há um side effect.

A mutação de estado é onde você altera o valor de uma variável. Se você alterar uma variável, existe a possibilidade de que ela afete outras funções, dependendo do valor anterior à mutação. Em um ambiente React, é recomendável não alterar seu estado.

Leia mais: Porque Imutabilidade é tão importante?

21. Closures

As Closures são difíceis de entender. Mas, uma vez compreendido, você começará a ver a beleza do JavaScript.

Uma closure forneceria acesso ao escopo de uma função externa dentro do escopo interno. Closures JavaScript são criados sempre que uma função é criada, no momento da criação da função.

Descubra por que você deve usar closures para obter uma compreensão mais profunda deles.

Mais afinal o que são closures? por Stephano Wallace

22. Higher-Order Functions

Higher-Order Functions são funções que recebem outras funções como argumentos ou retornam funções como resultado.

Você pode criar funções menores que cuidam de apenas uma tarefa e, em seguida, construir funções complexas com a ajuda dessas funções menores. Isso também resultará em um aumento na capacidade de reutilização do código.

Isso também reduz bugs e torna nosso código mais fácil de ler e entender.

const double = n => n * 2

[1, 2, 3, 4].map(double) // [ 2, 4, 6, 8 ]

Exemplo: A função map do Array é uma High Order Function.

23. Recursão

Recursão, é um conceito comum em todas as linguagens de programação. Em termos simples, recursão é o conceito de dividir um problema maior em partes menores e depois resolver os problemas menores.

Colocado em prática, isso geralmente significa escrever uma função que chama a si mesma. Embora a recursão possa ser um conceito confuso para entender, você pode entendê-lo melhor com muita prática, começando com pequenos problemas.

Mas cuidado, você pode encontrar um erro de (Estouro de pilha) stack overflow se não for cuidadoso com sua recursão. Como exercício, faça pesquisas sobre esse erro.
Você precisará revisar seu conhecimento sobre o primeiro tópico, Callback stack, para compreender totalmente o contexto desse erro.

24. Collections e Generators

Collections e generators foram introduzidos recentemente no ES6. As collections recém-introduzidas foram Map, Set, WeakSet, eWeakMap.. Essas collectionsfornecem alguns casos de uso realmente bons para você trabalhar. É essencial que você os conheça, especialmente com o JavaScript moderno.

Generators, por outro lado, às vezes são um pouco difíceis de entender, especialmente para iniciantes.
Os generators permitem que você escreva funções de código que fornecem a capacidade de pausar e reiniciar uma função sem bloquear a execução de outro código, o que é algo incomum em JavaScript.

25. Promises

Jecelyn explica Promises da seguinte forma: “Imagine que você é uma criança. Sua mãe promete que ela vai lhe dar um novo telefone na próxima semana.”
Você não saberá se receberá esse telefone até a próxima semana. Sua mãe realmente compra um telefone novo para você — ou ela não compra porque ela não está feliz.

Isso é uma promise. Uma promise tem três estados. Eles são:
Pending: você não sabe se vai conseguir esse telefone.
Fulffiled: mamãe está feliz e ela compra um telefone novo para você.
Rejected: mamãe está infeliz e não compra um telefone para você.

Esta é de longe a explicação mais simples e clara que encontrei para Promises.

26. Programação Assíncrona

Para entender o que é programação assíncrona, devemos primeiro atualizar nosso conhecimento de programação síncrona. A programação síncrona bloqueia threads e, como o JavaScript é de thread único, seu código será executado linha por linha.

Mas, com o código assíncrono, você pode realizar longas solicitações de rede sem bloquear o thread principal. Isso é especialmente útil quando você precisa realizar várias tarefas que demoram muito para serem concluídas. Mas pode haver casos em que você precise bloquear o thread, mesmo para uma tarefa longa.

Você usaria o conceito de async/awaitnaquele momento.
Aprender bem esses conceitos permitirá que você escreva programas com desempenho eficiente, mesmo com muitas tarefas em execução.

27. Arrow Functions

As arrow functions foram adicionadas ao ES6 e são uma substituição sintática das funções regulares. A diferença é que as arrow functions não se vinculam às palavras-chave this, arguments, super, ou new.target. Isso torna as arrow functions uma ótima escolha em alguns cenários, mas muito ruim em outros.
Portanto, você nunca deve criar o hábito de usar as arrow functions o tempo todo. Implemente-os de acordo com seu caso de uso.

Vale a leitura: Quando não usar Arrow Functions

28. Estrutura de Dados

As estruturas de dados são uma das peças essenciais do conhecimento que um desenvolvedor deve ter, independentemente da linguagem de programação.
“Os programadores ruins se preocupam com o código. Os bons programadores se preocupam com as estruturas de dados e seus relacionamentos.”
-Linus Torvalds, criador do Linux e Git

Por ter um conhecimento profundo de diferentes estruturas de dados, você pode criar programas eficientes que funcionam bem em diferentes circunstâncias. Você deve saber sobre linked lists, queues, stacks, árvores, grafos e hash tables.

29. Complexidade de Tempo

A análise da complexidade do tempo também é outro fundamento da programação de computadores, independentemente da linguagem de programação. Para construir melhores aplicativos, você deve escrever melhores soluções. Para fazer isso, você deve entender o conceito de complexidade do tempo. Às vezes é chamado de Big O.
A notação Big O descreve o tempo de execução necessário ou o espaço usado por um algoritmo.
A notação Big O descreve especificamente o pior cenário.
Isso permitirá que você selecione e implemente o algoritmo que terá o melhor desempenho, mesmo no pior cenário.

30. Algoritmos

Esta é uma das primeiras coisas que você aprenderá em um curso de ciência da computação. Em palavras simples, um algoritmo é um processo passo a passo de como você consegue algo.
Um programador deve ser capaz de olhar para qualquer problema de uma perspectiva algorítmica. Eles devem ser capazes de estruturar o problema e sua solução em um processo passo a passo. Este algoritmo é o que você escreverá como um programa mais tarde.
Embora existam vários algoritmos por aí para milhares de casos de uso, dois dos casos de uso são bastante comuns:

  • Search
  • Sort

Esses dois casos de uso são muito comuns aos programadores e você deve ter pelo menos um conhecimento completo dos algoritmos conhecidos disponíveis para eles. Não existe uma regra fixa afirmando que você deve usar um desses algoritmos, mas esses algoritmos são bem conhecidos e bem documentados em termos de desempenho.

Você pode até criar seu próprio algoritmo e apresentá-lo ao mundo.
Se for melhor do que os algoritmos atualmente conhecidos, você pode se tornar a próxima estrela da programação!

31. Herança, Polimorfismo e Re-uso de código

A herança em JavaScript funciona com protótipos. Isso ocorre porque o JavaScript é uma linguagem não OOP.
Ainda assim, o JavaScript fornece alguns recursos de OOP ao fornecer herança prototípica.
O polimorfismo, por outro lado, é um conceito em que um objeto, variável ou função pode assumir várias formas.
Em JavaScript, é um pouco mais difícil ver os efeitos do polimorfismo porque os tipos mais clássicos de polimorfismo são mais evidentes em sistemas estaticamente tipados.
Os dois conceitos acima nos ajudam com a reutilização de código em JavaScript. Ter um entendimento sólido dos dois conceitos acima, especialmente com JavaScript, permitirá que você escreva um código de alta qualidade e praticidade.

32. Design Patterns

Na engenharia de software, um padrão de projeto é uma solução bem conhecida e replicavel para um problema comum.
Existem vários padrões de design por aí, cada um com seu próprio caso de uso.
Os 23 padrões da Gang of Four (GoF) são geralmente considerados a base para todos os outros padrões. É muito difícil conhecê-los todos, mas você pode pelo menos tentar entender seus casos de uso.

Aqui está um ótimo repositório de Felipe que tem implementações dos 23 padrões GoF em JavaScript. Percorra os recursos mencionados no final deste artigo para se familiarizar com alguns recursos fantásticos de Leonardo, uma inspiração para este artigo.

33. Programação Funcional

De acordo com o Wiki, “a programação funcional é um paradigma de programação — um estilo de construção da estrutura e elementos de programas de computador — que trata a computação como a avaliação de funções matemáticas e evita a mudança de estado e dados mutáveis.”
Existem vários conceitos de programação funcional que você precisará dominar:

  • Funções puras
  • Imutabilidade
  • Transparência referencial
  • Higher-order functions

Compreender esses conceitos de programação funcional certamente dará a você uma vantagem.

Leia Mais: Entendendo Programação Funcional em JavaScript de uma vez

34. Clean Code

Esta é uma habilidade essencial que todo desenvolvedor deve dominar, independentemente da linguagem de programação.
Cada linguagem de programação possui um conjunto separado de boas práticas.
Embora essas “boas” práticas sejam subjetivas e difiram de local de trabalho para local de trabalho, há algumas práticas consideradas “boas”.

Seguindo esses princípios de código, você pode garantir que seu código possa ser lido e mantido por todos.
Isso ajudará você e sua equipe a trabalhar juntos sem problemas durante o desenvolvimento do aplicativo.

Leia Mais: Clean Code JavaScript em Português

35. Spread Operator

O operador de atribuição de desestruturação foi introduzido no ES6.
Ele tem vários casos de uso com os quais você definitivamente deve estar familiarizado.
Eles são mais fáceis e eficientes do que as implementações anteriores para os mesmos casos de uso.
Isso também é conhecido como o operador de propagação.

Leia Mais: MDN: Atribuição via desestruturação

36. Novas features do ES2020 e ES2021

A beleza da programação é que você nunca pode ser um especialista em uma linguagem de programação sem aprendizado contínuo. As linguagens de programação evoluem continuamente com o tempo, à medida que recursos adicionais são introduzidos em cada versão principal.

Isso significa que seu conhecimento especializado de um conceito ficará desatualizado ou obsoleto em outros dez anos, pois haveria uma alternativa melhor lançada com uma atualização de versão. Este é um cenário muito comum com qualquer linguagem de programação.

Dominar um idioma exigirá anos de experiência e tempo, mas saber o que dominar tornará as coisas mais fáceis para você.

Este repositório Github é um bom lugar para começar.

Obrigado por ler e ótima programação

Créditos

36 Concepts to become an JavaScript Expert por Mahdi Rezvi

Software Engineer | Front-end Specialist @ Grover (https://rubenmarcus.dev)

Software Engineer | Front-end Specialist @ Grover (https://rubenmarcus.dev)