O que TODO desenvolvedor JavaScript precisa saber

Nos últimos anos o JS passou por uma grande revolução, apesar disso, existe uma parte fundamental da linguagem que todos deveríamos saber.

por Matheus Lima 06/08/2017 ~ 6 min. / 1217 palavras

Nos últimos anos o JavaScript vem passado por uma grande revolução: uma enorme adoção por partes das empresas, polêmicas e algumas rivalidades:

  • ES6/ES7 x TypeScript
  • Angular x React
  • Gulp x Grunt
  • Functional Programming x OOP

Apesar disso, existe uma parte fundamental da linguagem que todos deveríamos saber.

1) Call x Apply

As funções call e apply nos deixam invocar métodos como se estivéssemos no contexto de um outro objeto:

O primeiro parâmetro tanto de call quanto de apply é o próprio contexto, ou seja: o valor de this será exatamente o que você passar como parâmetro. Então qual a diferença entre eles? O segundo parâmetro.

Enquanto apply aceita um array, call requer parâmetros divididos por vírgulas:

Qual a importância?

A importância desses dois métodos e o porquê deles serem tão usados (principalmente em libs) é bem simples: apply e call nos permitem pegar métodos emprestados reduzindo assim a quantidade total de código gerada e seguindo o DRY.

2) Closures

A combinação de uma função e a referência ao seu estado externo é uma closure. Uma aplicação comum de closures são os IIFEs:

A variável a é privada por ficar em uma closure. Já a b, é uma variável global.

Uma outra abordagem para a criação de uma closure, é basicamente criar uma função dentro de outra, dessa forma:

A função de dentro (hello) tem acesso ao escopo externo dela (init). Porém, ao sairmos de init, perdemos a visibilidade da função hello.

Qual a importância?

A capacidade de esconder informações também conhecida como: data privacy. Isso é essencial para que possamos esconder informações que deveriam ser privadas e programar para uma interface e não para uma implementação.

3) This

A palavra-chave this no JavaScript funciona de uma maneira um pouco diferente das outras linguagens. Em linguagens OO comuns o this se refere a instância da classe corrente. Porém, no JavaScript o valor de this é determinado pelo contexto de invocação da função e onde elas foram chamadas.

Escopo Global

No escopo global (em um browser) o this se refere ao objeto window, tanto dentro quanto fora de uma função:

Método de objeto

Quando usado dentro de um método de um objeto, o this se refere ao próprio objeto:

E no caso de objetos aninhados, o this vai se referir ao objeto pai mais próximo:

É bem comum esquecermos a regra acima, principalmente no uso de loops:

Uma forma fácil de corrigir esse problema é simplesmente guardar o valor do this em uma variável e ao invés de chamar o this, chamar essa variável:

Função sem contexto

Quando usamos o **this **numa função invocada sem contexto então o bind é feito no contexto global, mesmo se a função for definida dentro de um objeto:

Função na Prototype Chain

Quando um método está na prototype chain de um objeto, o this desse método vai se referir ao objeto que o está chamando, mesmo se o método não estiver definido nesse objeto:

Qual a importância?

O this é um dos maiores responsáveis por erros para quem está iniciando com o JavaScript. Portanto entender como ele funciona é de extrema importância para quem quer dominar a linguagem e gerar menos bugs.

4) Bind

Agora que já entendemos o this em JavaScript e os métodos call e apply, podemos estudar o método bind.

O bind é muito semelhante ao call e apply: serve para passarmos um contexto para uma função, que não é dela, e podermos executá-la. A diferença é que call e apply invocam a função imediatamente:

Enquanto bind retorna uma nova função que quando for executada terá o contexto que passamos.

É comum usarmos o bind para o disparo de eventos:

E também no mundo React:

Qual a importância?

Basicamente a mesma de apply e call.

5) Map, Filter e Reduce

Você provavelmente já passou por alguma situação em que era necessário por exemplo iterar sobre um array, ou então verificar se existe alguma propriedade nele ou mesmo simplesmente gerar um novo array com base no primeiro. Os métodos map, filter e reduce nos ajudam nessas situações além de começarmos a pensar mais em termos de programação funcional.

**Map:**Dado um array qualquer, como podemos fazer para transformá-lo, ou mapeá-lo, em um outro array? Existe a forma difícil (sem map):

E existe a forma fácil (com map):

**Filter:**Dado o mesmo array, como podemos gerar um novo filtrando apenas os 6 primeiros meses do ano?

Com o filter é bem fácil fazer isso:

Reduce: Dado o array de meses que temos trabalhado até então, como podemos fazer para gerar uma acumulação de valores, ou reduzi-lo, em algum valor específico?

Com o reduce seria mais ou menos assim:

Pra quem conhece o Redux (um state container muito comum em aplicações que usam o React), uma curiosidade é que a ideia dele está basicamente resumida na ideia de uma função reduce: a Reducer Function.

Qual a importância?

Os métodos map, filter e reduce são a base da programação funcional não só em JavaScript, mas em diversas outras linguagens. E sem saber programação funcional não há como tirar 100% de proveito de JavaScript e do seu ecossistema.

6) Prototype

A herança em JavaScript é feita através dos prototypes. Ela funciona de uma maneira um pouco diferente da herança clássica, o que pode gerar um pouco de confusão mesmo para os mais desenvolvedores mais experientes em JavaScript.

Podemos pensar em objetos em JavaScript como agregadores de propriedades dinâmicas. E quando um objeto tenta acessar qualquer propriedade sua e não a encontrar, ela procurará no seu prototype. E se não estiver lá, no prototype de seu prototype até que a propriedade seja encontrada ou então essa corrente, chamada de Prototype Chain, se acabe:

Animal consegue invocar o método walk porque o mesmo pertence a ele. Dog também consegue invocar porque apesar do mesmo não pertencer a ele pertence a seu prototype. No caso de Airplane porém, nem ele e nenhum prototype seu encontrou o método walk até o fim da Prototype Chain.

Qual a importância?

Um dos conceitos mais usados em qualquer linguagem de programação é a Herança e com JavaScript ela é feita através do Prototype. Entender bem não apenas o Prototype como também o Prototype Chain é fundamental para dominar o JavaScript.

7) Hoisting

A tradução de hoist é içar, levantar ou suspender. E é isso que acontece em JavaScript quando declaramos uma variável: ela é levantada até o topo do escopo.

Qual o retorno da função abaixo?

As respostas mais comuns são 1 ou 2, mas a resposta correta é undefined. A declaração de variáveis em JavaScript é hoisted (ou elevada), mas não sua inicialização. Portanto o código acima é equivalente a esse:

Para evitar problemas inesperados, tente sempre declarar todas a variáveis no topo do escopo, mesmo que você não as tenha inicializado ainda. Ou então atualize para o ES6 e passe a usar as keywords let e const. Elas funcionam da maneira esperada:

Qual a importância?

Evitar futuros bugs ao entender uma das partes mais problemáticas da linguagem.

Para aprender mais

É difícil encontrar conteúdo bom e atualizado em português. Com isso em mente criamos o JSCasts, onde você vai se manter em dia com o JavaScript e todo o seu ecossistema de forma fácil e interativa.

Cursos:


Esse artigo foi escrito originalmente no canal do Tableless no Medium!