Ok, Ok… Eu sei que disse no meu último post que eu estava iniciando uma série sobre como criar uma aplicação em ReactJS do zero. Mas como o meu objetivo é utilizar vários recursos do ES6, enquanto escrevia o próximo artigo da série eu vi que estava parando demais para explicar as novas funcionalidades da linguagem. Por isso preferi dar uma breve pausa na série para fazer um Guia Definitivo sobre o ES6!
O EcmaScript 6 (ou ES2015) não é exatamente novo, mas muitos desenvolvedores ainda têm uma certa dificuldade em utilizá-lo em seus projetos, seja por falta de conhecimento ou por Bocardia Mental mesmo. Como são muitas as novidades vindas com a versão, vou tentar conter minha mão nervosa e ser o mais breve possivel, mas me perdoem se eu não conseguir.
Por que tanta mudança?
Quem trabalha com desenvolvimento Web à um pouco mais de 5 anos, deve se lembrar do quão penoso era fazer um site que funcionasse bem em todos os navegadores. Isso por que, desde a chamada Guerra dos Navegadores, criou-se a cultura de que cada browser deveria criar suas próprias implementações e padrões para a utilização de recursos frontend e obrigar todos os desenvolvedores a seguirem suas diretivas “soberanas”. Com isso, quando saia uma nova versão do Javascript, cada browser implementava da sua própria maneira as especificações e BUM!! Explosão de IF/ELSE
por todo lado para tratar as peculiaridades dos navegadores.
Esse foi o principal motivo para o Javascript não ter evoluido como se esperava por um longo período de tempo. Afinal, como iriam liberar uma nova release se os browsers ainda estavam brigando para ver quem implementava os recursos da versão atual da maneira mais bizarra possível?
Para resolver o problema foi criado o TC39, um comitê formado principalmente por membros das principais desenvolvedoras de browsers, que ficaria responsável pela implementação das novas versões do Javascript, que a partir de então teriam releases anuais. Com isso, foi adotada uma nova nomenclatura baseada no ano da versão (como ES2017), ao invés de números (como ES6).
Porém, quando esta nova abordagem foi anunciada, muitos já conheciam a nova versão do Javascript como ES6, talvez por isso ainda hoje essa nomenclatura seja a mais utilizada.
Como usar?
O TC39 pode estar ajudando bastante no crescimento padronizado do Javascript, facilitando a implementação de suas especificações por parte das desenvolvedoras, mas ainda assim, o ES6 trouxe consigo um conjunto gigantesco de mudanças, fazendo com que o ES2015 ainda não tenha suporte total em todos os browsers. Hoje, as maiorias das especificações já foram implementadas (a lista completa e atualizada de compatibilidade pode ser vista aqui), mas infelizmente ainda temos que considerar os navegadores mais antigos que ainda são bem utilizados (como o Internet Explorer 11).
Mas calma, nem tudo está perdido. Existem várias bibliotecas que prometem implementar “na mão” as funcionalidades do ES6, mas a maneira mais interessante de se trabalhar é com a utilização de um transpiler como o Babel, em conjunto com o Webpack. Podemos abordar como configurar o Webpack+Babel em um próximo post, mas para testar os recursos abordados neste artigo, vocês poderão utilizar o Babel Online.
Recursos da nova versão
Eu prometi que não iria me estender muito, então vamos partir finalmente para as novidades do ES6.
Let e Const
Para entender os benefícios de se declarar variáveis utilizando let
e const
, precisamos primeiro entender como funciona a forma original, com o uso de var
.
Primeiramente, as variáveis declaradas com var
possuem um escopo de função ao invés de um escopo de bloco. Para entender, vejamos esse exemplo:
1
2
3
4
5
6
7
8
9
10
11
function xpto(){ //cria um escopo de função
var a = 1;
console.log(a); //exibe o número 1
if(true){
var a = 2;
console.log(a); //exibe o número 2
}
console.log(a); //exibe o número 2
}
O comportamento esperado pela maioria dos desenvolvedores é que todas as variáveis criadas dentro de blocos (como if
, for
ou while
) estivessem disponíveis apenas dentro de seus respectivos blocos. Mas com o Javascript não é tão simples assim.
Como os escopos pertencem às funções e não aos blocos, qualquer variável declarada dentro dentro delas irá ser “içada” para o topo de seu escopo, graças ao conceito de Hoisting.
No ES5, quando queríamos criar uma variável pertencente apenas à um escopo restrito, precisávamos utilizar IIFEs (Immediately Invoked Function Expression ou Funções Imediatas), como no exemplo a seguir:
1
2
3
4
5
6
7
8
9
10
11
12
13
function xpto(){ //cria um escopo de função
var a = 1;
console.log(a); //exibe o número 1
if(true){
(function(){ //cria um escopo de função
var a = 2;
console.log(a); //exibe o número 2
})();
}
console.log(a); //agora sim exibe o número 1 =D
}
Mas no ES6 podemos utilizar as diretivas let
e const
para declarar variáveis com escopo de bloco, onde const
declara uma constante e let
declara uma variável propriamente dita. Então o código acima ficaria assim em ES6:
1
2
3
4
5
6
7
8
9
10
11
function xpto(){ //cria um escopo de bloco
const a = 1;
console.log(a); //exibe o número 1
if(true){ //cria um escopo de bloco
const a = 2;
console.log(a); //exibe o número 2
}
console.log(a); //exibe o número 1
}
Mas existe um pequeno problema ao se declarar constantes com const
. Naturalmente, você imagina que o valor nunca vai poder ser alterado posteriormente, como toda boa constante deveria ser. E isso pode ser verdade quando estamos trabalhando com tipos simples de constantes, como números e strings, mas não podemos dizer o mesmo sobre os objetos.
Veja o exemplo a seguir:
1
2
3
4
5
6
7
8
9
10
const pessoa = {
nome: "John",
sobrenome: "Doe"
}
console.log(pessoa.sobrenome); //exibe Doe
pessoa.sobrenome = "Smith";
console.log(pessoa.sobrenome); //exibe Smith
Como você viu, podemos alterar livremente as propriedades de um objeto, mesmo tendo sido declarado como constante. Mas antes de você se desesperar, existem alternativas para lidar com o problema, como o Object.freeze e o Immutable.js.
Default parameters
Nas versões anteriores ao ES6, quando queríamos tratar um parâmetro opcional, precisávamos fazer isso manualmente, como no exemplo à seguir:
1
2
3
4
5
6
7
function incrementar(numero, incremento){
incremento = incremento || 1;
return numero + incremento;
}
console.log(incrementar(10)); //exibe o número 11
Agora, conseguimos especificar o valor padrão de um parâmetro já na declaração da função, aumentando a legibilidade do código escrito:
1
2
3
4
5
6
function incrementar(numero, incremento=1){
return numero + incremento;
}
console.log(incrementar(10)); //exibe o número 11
Rest parameters
Para criar uma função que pode receber um quantidade indeterminada de parâmetros, teríamos que usar a variável arguments
e fazer o seguinte:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function adicionaDependentes(pessoa){
var i = 1;
var count = arguments.length;
while(i < count){
pessoa.dependentes.push(arguments[i]);
i++;
}
return pessoa;
}
var pessoa = {nome: "John Doe", dependentes: []};
adicionaDependentes(pessoa, "Jack", "Mary", "James");
Note que precisamos fazer muita coisa manual, como controlar a posição inicial do array arguments
, incrementar o contador dentro do loop (ou utilizar o loop for
), e vamos combinar que esse não é o código mais bonito de se ver. Com o ES6 podemos especificar um rest parameter através do uso de ...
antes do nome do parâmetro. Veja a seguir:
1
2
3
4
5
6
7
8
9
10
function adicionaDependentes(pessoa, ...dependentes){
for(const dependente of dependentes){
pessoa.dependentes.push(dependente);
}
return pessoa;
}
var pessoa = {nome: "John Doe", dependentes: []};
adicionaDependentes(pessoa, "Jack", "Mary", "James");
Bem melhor, não?
BÔNUS: Reparem que no código acima foi utilizado o loop for...of
, que é bem parecido com o for...in
, porém o resultado da iteração é o objeto propriamente dito dentro do array, e não o seu índice. Assim, no exemplo, nós não precisamos acessar um dependente como dependente[i]
, e sim acessando diretamente a variável.
Bom, não tem como falar de todos os recursos que a versão ES6 trouxe ao Javascript sem me estender demais, por isso eu vou voltar em um próximo artigo para trazer mais novas funcionalidades. Ainda vamos falar sobre Classes, Arrow Functions, Destructuring e Muito Mais!!!
Então é isso galera. Nos vemos no próximo artigo, e se vocês estão gostando (ou não) dos temas, didática e a forma de escrita dos artigos, não deixe de comentar.
EDIT: Continue aprendendo mais sobre ES6 lendo o artigo ES6: O Guia Definitivo - Parte 2.
Até a próxima!