O que é ES6+?
Em junho de 2015, o JavaScript recebeu a sua maior atualização de todos os tempos. O ECMAScript 2015, mais conhecido como ES6, adicionou block scoping, arrow functions, classes, modules, promises e muito mais. O comitê que mantém a linguagem comprometeu-se, então, a lançar uma nova edição a cada ano, e “ES6+” tornou-se a abreviação para toda essa era moderna.
Você não precisa aprender cada recurso. Um pequeno grupo deles representa a vasta maioria do código escrito no dia a dia, e é neles que este guia foca. O tema central de todos eles é simples: diga o que você quer com menos cerimônia.
let e const
O recurso mais antigo é também o mais importante. var possui escopo de função e sofre hoisting de maneiras que surpreendem as pessoas. let e const possuem escopo de bloco, portanto, existem apenas dentro do { } mais próximo.
// scope.js
if (true) {
let message = "inside";
const limit = 10;
}
// message and limit are not defined out here
const evita a reatribuição do binding, o que torna sua intenção óbvia: este nome não apontará para outro lugar. Ele não congela o valor, então um array const ainda pode ser mutado. Use const por padrão, let quando a reatribuição for necessária, e trate var como história.
Arrow functions
Arrow functions são uma sintaxe mais curta com uma diferença comportamental importante: elas não possuem seu próprio this. Elas herdam o this do escopo ao redor, que é quase sempre o que você deseja em callbacks.
// arrows.js
const add = (a, b) => a + b;
const square = (n) => {
return n * n;
};
const names = ["Ada", "Grace", "Linus"];
const upper = names.map((name) => name.toUpperCase());
Quando o corpo é uma única expressão, as chaves e o return podem ser omitidos. Parênteses em volta de um único parâmetro são opcionais. Como arrow functions capturam o this, elas são ideais para event handlers e métodos de array, mas não são adequadas para métodos de objeto que precisam de seu próprio this.
Template literals
As crases criam strings que abrangem múltiplas linhas e interpolam expressões com ${ }.
// message.js
const name = "Ada";
const role = "engineer";
const greeting = `Hello, ${name}!
You are logged in as a ${role}.`;
Template literals também suportam tagged templates, onde uma função recebe as partes literais e os valores interpolados separadamente. Esse mecanismo serve de base para muitas bibliotecas de estilização e templating.
Destructuring
O destructuring desempacota valores de arrays e objetos em variáveis, o que elimina grande parte do acesso repetitivo a propriedades.
// destructure.js
const user = { name: "Ada", age: 36, city: "London" };
const { name, age, city = "Unknown" } = user;
const coords = [51.5, -0.12];
const [lat, lng] = coords;
function greet({ name }) {
return `Hello, ${name}`;
}
Você pode renomear variáveis durante o destructuring (const { name: userName } = user), definir valores padrão e fazer o destructuring diretamente na lista de parâmetros de uma função — um padrão utilizado constantemente com props do React e objetos de configuração.
Spread e rest
Os mesmos três pontos desempenham duas funções complementares, dependendo de onde aparecem.
// spread.js
const a = [1, 2, 3];
const b = [4, 5];
const combined = [...a, ...b]; // spread: expand
const copy = { ...user, age: 37 }; // shallow clone + override
function sum(...numbers) { // rest: collect
return numbers.reduce((t, n) => t + n, 0);
}
O Spread copia elementos para um novo array ou objeto, sendo a base para atualizações imutáveis. O Rest agrupa os argumentos ou elementos restantes em um único array. Juntos, eles tornam o trabalho com coleções muito mais agradável.
Parâmetros padrão e shorthand
Funções podem declarar valores padrão, e literais de objeto podem usar shorthand quando o nome da propriedade coincide com o de uma variável.
// config.js
function connect({ host = "localhost", port = 8080 } = {}) {
return `${host}:${port}`;
}
const name = "Ada";
const user = { name, greet() { return `Hi, ${this.name}`; } };
Os valores padrão são avaliados apenas quando o argumento é undefined, que geralmente é o comportamento desejado. Propriedades e métodos shorthand reduzem o ruído em códigos com uso intenso de objetos.
Optional chaining e nullish coalescing
Esses dois operadores, adicionados em 2020, eliminaram montanhas de verificações defensivas.
// safe.js
const city = user?.address?.city;
const name = input ?? "anonymous";
user?.profile?.onLogin?.();
?. faz um short-circuit para undefined se o valor à sua esquerda for null ou undefined. ?? fornece um fallback apenas quando o lado esquerdo é null ou undefined — ao contrário de ||, ele não trata 0, "" ou false como valores ausentes.
Métodos de Array
O protótipo de array é repleto de métodos que descrevem a intenção em vez da mecânica de repetição.
// arrays.js
const products = [
{ name: "Keyboard", price: 80, inStock: true },
{ name: "Mouse", price: 40, inStock: false },
{ name: "Cable", price: 10, inStock: true },
];
const names = products.map((p) => p.name);
const cheap = products.filter((p) => p.price < 50);
const total = products.reduce((sum, p) => sum + p.price, 0);
const available = products.some((p) => p.inStock);
const allCheap = products.every((p) => p.price < 100);
const mouse = products.find((p) => p.name === "Mouse");
map transforma, filter seleciona, reduce reduz uma lista a um único valor, find retorna a primeira correspondência, e some/every testam uma condição. Eles podem ser encadeados, não mutam o array original e a leitura parece a descrição do que você deseja alcançar.
Módulos
Os ES modules permitem que você divida o código entre vários arquivos e compartilhe apenas o que desejar.
// math.js
export function add(a, b) {
return a + b;
}
export const PI = 3.14159;
export default function subtract(a, b) {
return a - b;
}
// app.js
import subtract, { add, PI } from "./math.js";
As named exports podem ser várias por arquivo e são importadas pelo nome. Já a default export é um único valor principal. Os módulos possuem seu próprio escopo, são avaliados apenas uma vez e permitem que os bundlers removam código não utilizado através de tree-shaking.
Classes
Classes fornecem uma sintaxe clara para código orientado a objetos, construída sobre o sistema de protótipos existente do JavaScript.
// user.js
class User {
#secret = "hidden"; // private field
constructor(name) {
this.name = name;
}
get greeting() {
return `Hello, ${this.name}`;
}
static create(name) {
return new User(name);
}
}
class Admin extends User {
constructor(name) {
super(name);
this.role = "admin";
}
}
extends e super lidam com a herança, static define métodos na própria classe e # marca campos verdadeiramente privados. Por baixo dos panos, ainda são protótipos, mas a sintaxe é muito mais fácil de ler.
Outros recursos que valem a pena conhecer
- Map e Set para coleções com chaves e valores únicos, com semânticas melhores do que objetos e arrays comuns para essas tarefas.
- for…of para iterar sobre arrays, strings, maps, sets e qualquer iterável.
- Exponenciação com
**, portanto2 ** 10substituiMath.pow(2, 10). - Iterators e generators para sequências preguiçosas (lazy sequences), iterações customizadas e funções pausáveis.
- Object.entries / fromEntries para converter entre objetos e arrays de pares.
Melhores práticas
- Use
constpor padrão; utilizeletapenas quando houver reatribuição. - Prefira arrow functions para callbacks e funções regulares para métodos que precisem de
this. - Utilize desestruturação nos parâmetros para tornar a estrutura necessária explícita.
- Use o operador spread para atualizações imutáveis em vez de mutar dados compartilhados.
- Utilize
?.e??antes de escrever guards aninhados. - Prefira métodos de array em vez de loops manuais ao transformar dados.
- Mantenha os módulos pequenos e exporte a menor superfície possível.
Erros comuns
- Assumir que
consttorna um objeto imutável — ele apenas impede a reatribuição (rebinding). - Usar uma arrow function como método de um objeto e perder o
this. - Usar
||para valores padrão quando0ou""são valores válidos; use??. - Fazer o spread de apenas um nível e esperar um deep clone.
- Misturar
requireeimportno mesmo sistema de módulos sem entender a interoperabilidade. - Encadear métodos de array em excesso, criando um pipeline ilegível.
Próximos passos
A sintaxe moderna é o vocabulário; o DOM e o JavaScript assíncrono são onde você coloca esse conhecimento em prática. Assim que as promises e os módulos se tornarem naturais, a Fetch API transformará essas habilidades em aplicações reais.