ECMAScript 6(ES6) é a sexta versão padronizada do JavaScript, agora conhecida oficialmente como ECMAScript 2015 (ES2015), foi finalizada em Junho de 2015, foi o maior update do JavaScript, arrumando bugs da linguagem, trazendo novos recursos e algumas novas sintaxes.
Hoje em dia já é utilizado por muitos projetos e é fundamental conhecer esses novos recursos do JavaScript.
Neste post irei comentar apenas alguns dos novos recursos, existem muito mais recursos :).
Irei comentar sobre seguintes recursos:

  • Escopo let/const
  • Template Literals
  • Parâmetros com valores padrões
  • Parâmetros Rest
  • Operador Spread
  • Arrow Functions (( ) => { })
  • Novos recursos para Objetos Literais
  • Object Destructuring
  • Array Destructuring
  • Rest Item
  • Parâmetros com 'Destructuring'
  • Classes "Class"
  • Módulos

Escopo let/const

Agora temos escopo por bloco, igual a algumas linguagens tipo o C, C#, Java etc..., para ter acesso a variáveis de escopo, precisamos utilizar ao invés de var temos que utilizar a palavra reservada let para variáveis e const para constantes.

Exemplo:

Variáveis ou constantes não podem ser declaradas mais de uma vez no mesmo escopo.

Exemplo:

Mas este não causa erro:

Com escopo por bloco, agora podemos fazer coisas tipo isso:

Sem escopo por bloco temos que criar um escopo a cada iteração:

Outra característica é que let/const não poluem o objeto global (window no caso de browser) caso declarado num escopo global.

Template Literals

Nova maneira de criar strings e com novos recursos, como strings multiline e formatação por substituições de variáveis (Interpolação de Expressões).
Para criar esse tipo de string devemos utilizar o caracter ` (acento craseado).
Podemos ter quebras de linhas(multiline) sem a necessidade de concatenar.

Exemplo:

Também podemos fazer substituições utilizando ${}. Sendo que entre {} podemos ter qualquer variável ou expressão que retorne algum valor.

Exemplo:

Tagged Template Literals

'Tagged template' é uma função que é executada na string "Template". Esta função recebe no primeiro parâmetro um array que é a string sem as substituições, sendo que cada posição do array é uma parte da string sem a substituição, o segundo parâmetro são as substituições.O retorno da string será o retorno desta função. (Obs: o modo de chamar esta função é assim: funcTag`aaaaaaaaa`, sem os parênteses mesmo)

Exemplo:

Parâmetros com valores padrões

São valores que são atribuídos para os parâmetros que não são informados na chamada da função.

Exemplo:

Parâmetros Rest

Um parâmetro Rest é indicado com 3 pontos (...) antes do nome do parâmetro. O parâmetro Rest é uma array contendo todos os valores restantes passados para a função.
Só deve existir apenas 1 parâmetro Rest numa função e este deve ser o último parâmetro.

Exemplo:

Operador Spread

Operador Spread transforma um array em argumentos individuais numa chamada de função. São indicados também por 3 pontos (...) mas nas chamadas de função.

Exemplo:

Arrow Functions (( ) => { })

Uma nova sintaxe de criar funções e com algumas caracteristicas:

  • Não podem ser funções construtoras (não pode utilizar new para instanciação)
  • Não possuem prototype
  • O contexto (this) é do contexto da função (não arrow) mais próxima (a função pai)
  • Não possuem o objeto arguments
  • Seu contexto não pode ser alterado por call(), apply(), ou bind()

A sintaxe da Arrow function é a seguinte: (parâmetros) => {corpo da função}

Exemplo:

Outra caracterisca da arrow function é quando a função de apenas uma instrução retorna um objeto literal, neste caso devemos envolver o corpo da funcão entre parênteses.

Outros exemplos de arrow function:

Novos recursos para Objetos Literais

  • Inicializador de propriedades: é uma maneira curta de atribuir valores para propriedades de um objeto. para variaveis que possuem o mesmo nome da propriedade

    Exemplo:
  • Criar método:

    Novo modo de criar métodos em objetos literais, eliminando ':' e a palavra 'function'.

    Exemplo:
  • Nome de propriedades computadas( definidas com o resultado de uma expressão) Agora podemos definir uma propriedade dinamicamente, para isso é necessário usar [(expressão)] : valor sendo que a expressão pode ser qualquer variavel ou expressão que retorne algum valor que será o nome da propriedade.

    Exemplo:

Object Destructuring

É uma maneira mais simples e econômica de criar variáveis com valores das propriedades de um objeto.

Exemplo:

Array Destructuring

Possui a mesma idéia do Object Destructuring, mas com Arrays, ou seja você cria variavés extraindo valores de um Array. Ao invés de nomes de propriedades ele utiliza a posição do item do Array para atribuir valor a variável.

Exemplo:

Rest Item

No contexto de atribuição 'Destructuring' utiliza-se Rest Item para atribuir os valores restantes do array para uma variável. É indicado também usando 3 pontos (...), mas na atribuição.

Exemplo:

Parâmetros com 'Destructuring'

Podemos usar toda a ideia de 'Destructuring' nos parâmetros de uma função.

Classes "Class"

Agora temos uma nova sintaxe para criar "classes", mas internamente ainda é tudo baseado em prototype. Para cria função construtora ("classe"), utilizamos a palavra reservada class.

Exemplo:

Seria basicamente o mesmo que:

Algumas características das classes criadas com class:

  • Não podemos criar propriedades no corpo da 'class'. Para criar propriedades devemos usar o construtor ou via métodos set/get.
  • Não sofrem 'hoisting' pela engine Javascript, diferente das funções que sofrem 'hoisting'.
  • Executam em modo strict.
  • Só podem ser chamadas com new.
  • Os métodos não devem ser chamados com new, e eles não são enumerable (não vão aparecer no Object.keys por exemplo).
  • O nome da classe não pode ser sobrescrito dentro dos métodos

Se fosse criar uma classe sem class seguindo estas caracteristicas poderíamos fazer o seguinte:

Herança "extends"

No JavaScript a 'Herança' ocorre por prototype, existem algumas maneiras de fazer isso, uma delas é a seguinte:

Agora com o ECMAScript 6 foi adicionada a palavra reservada extends para realizar herança de uma maneira mais simples.
Também criada a palavra super para acessar a classe base
Veja como ficaria o exemplo anterior:

Algumas considerações:

  • No construtor, osuper deve ser chamado antes de qualquer acesso à this
  • Caso a classe que está realizando extends não defina o constructor ele será definido e chamado implicitamente passando todos os parâmetros.
  • Podemos sobrescrever um método com mesmo nome da classe base, e também podemos ter acesso ao método base usando o super, por exemplo super.getNome()

Métodos estáticos

Para criar um método estático utilizamos a palavra static antes do nome do método.
Obs:Classes que usam herança também herdam os métodos estáticos da classe base.

Exemplo:

Módulos

Enfim agora temos oficialmente um sistema de módulos no JavaScript, por muitos anos os desenvolvedores veêm utilizando módulos AMD, CommonJS, UMD, e etc... atráves de algumas ferramentas como require.js, webpack, browserify etc... ou no Node nativamente com padrão CommonJS . Mas agora temos um padrão oficial de módulos na linguagem.

O que são Módulos?

Um módulo é um arquivo JavaScript "isolado"(as váriaveis declaradas só ficam visíveis dentro do módulo) que podemos exportar alguma função, variável, ou objeto. Para exportar utilizamos a palavra export e para que podemos acessar algum recurso de algum módulo devemos importar-lo utilizando a palavra import.

Export

Em um módulo podemos exportar mais de uma variável, veja alguns exemplos:

Import

Para utilizar um módulo devemos importá-lo, podemos importar de várias formas, sendo que a sintaxe básica de importar é a seguinte: import { algumIdentificador } from 'caminho-do-modulo'
Entre {} colocamos os nomes das variáveis(identificadores) que vamos 'importar' do módulo, no from devemos especificar o caminho do módulo, sendo que nos browsers o "caminho-do-modulo" deve ter a extensão '.js'. Para modulos que são exportados com 'default' não precisamos de {}.
Veja os exemplos:

Obs: o módulo é executado apenas no primeiro import, mesmo se você tiver outro import ele não irá executar o módulo, pois ele utilizará a referência do modulo que já estará em memória.

import/export módulos default

Podemos utilizar a palavra default para exportar apenas uma variável que pode ser anônima, o módulo só pode ter apenas um default, por exemplo:

Para importar algum modulo default, devemos fazer o seguinte:

Já podemos usar ECMAScript 6 ?

Sim, já podemos utilizar, veja a tabela abaixo que mostra percentual de recursos do ES6 que já foram implementados em cada ambiente:



Para dar suporte a ambientes antigos podemos utilizar um transpiler que transforma nosso código ES6 para ES5. O Babel é a ferramenta adequada para fazer isso. Podemos usá-lo com o gulp, webpack etc...
Acesse http://babeljs.io/repl/ e escreva algum código ES6 para ver como fica o código compilado para ES5.

Conclusão

O ES6 foi realmente o maior update do JavaScript, trazendo muitas facilidades e mais poder para a linguagem, sem dúvida nenhuma foi uma grande melhoria, mas não para ai, agora todo ano terá uma nova especificação para o ECMAScript, lógico que não tão grande igual a ES6. Já temos a ES7(ES 2016) e a ES8(ES2017) por exemplo.

Referências