ES6, 7, 8 e contando

Icaro Caldeira Carreira / @icarcal

Icaro Caldeira Carreira

ECMA SCRIPT

StagePurposePhase
0√ Allow input into the specificationN/A
1√ Make the case for the addition
√ Describe the shape of a solution
√ Identify potential challenges
Polyfills / demos
2√ Precisely describe the syntax and semantics
using formal spec language
Experimental
3√ Indicate that further refinement will require
feedback from implementations and users
Spec compliant
4√ Indicate that the addition is ready for inclusion
in the formal ECMAScript standard
Shipping

ES1 - 1997

ES2 - 1998

ES3 - 1999

ES4 - Abandoned

ES5 - 2009 - 2011

ES6 - 2015

ES7 - 2016

ES8 - 2017

ES9 - 2018 (?)

VAR, LET, CONST

VAR

// declaração de variáveis pré ES6
var jedi = 'Luke Skywalker';

// sofre hoisting
jedi = 'Luke Skywalker';
var jedi;

LET

// declaração de variáveis pós do ES6
// valor pode ser alterado
let jedi = 'Luke Skywalker';

jedi = 'yoda';

CONST

// "imutável"
const jedi = 'Luke Skywalker';
jedi = 'Anakin';
// Uncaught TypeError: Assignment to constant variable.

const jedi = {
  name: 'Luke Skywalker',
  lightsaberColor: 'azul',
}

jedi.lightsaberColor = 'vermelho';

TEMPLATE LITERALS

&

TAGGED TEMPLATES

Concatenação de variáveis

// pré ES6
var jedi = {
  name: 'Yoda',
  lightsaberColor: 'verde',
}

console.log(
  'O ' + jedi.name ' possui um sabre de luz '
       + jedi.lightsaberColor
);
// O Yoda possui um sabre de luz verde
// pós ES6
const jedi = {
  name: 'Yoda',
  lightsaberColor: 'verde',
}

console.log(
  `O ${jedi.name} possui um sabre de luz
      ${jedi.lightsaberColor}`
);
// O Yoda possui um sabre de luz verde

TAGGED TEMPLATE

function comeToTheDarkSide(strings, ...values) {
  console.log(strings);
  // ["O ", " possui um sabre de luz ", ""]
  console.log(values);
  // ["Yoda", "verde"]

  return `O ${values[0]} agora é do lado negro da força`;
}
const jedi = {
  name: 'Yoda',
  lightsaberColor: 'verde',
}
console.log(
  comeToTheDarkSide `O ${jedi.name} possui um sabre de luz
    ${jedi.lightsaberColor}`
);
// O Yoda agora é do lado negro da força

Object Shorthand Properties

// pré ES6
var name = 'Yoda';
var lightsaberColor = 'verde';
var darkSide = false;

var jedi = {
  name: name,
  lightsaberColor: lightsaberColor,
  darkSide: darkSide,
}
// pós ES6
const name = 'Yoda';
const lightsaberColor = 'verde';
const darkSide = false;

const jedi = {
  name,
  lightsaberColor,
  darkSide,
}

FUNCTIONS

DEFAULT PARAMETERS

// antes
function jediAttack(name, lightsaberColor) {
  name = name || 'Yoda';
  lightsaberColor = lightsaberColor || 'verde';

  console.log(
    `${this.name} utilizou seu sabre de luz
      ${this.lightsaberColor}`
  );
}

jediAttack();
// Yoda utilizou seu sabre de luz verde

jediAttack('Anakin', 'vermelho');
// Anakin utilizou seu sabre de luz vermelho
// depois
function jediAttack(name = 'Yoda', lightsaberColor = 'verde') {
  console.log(
    `${this.name} utilizou seu sabre de luz
      ${this.lightsaberColor}`
  );
}

jediAttack();
// Yoda utilizou seu sabre de luz verde

jediAttack('Anakin', 'vermelho');
// Anakin utilizou seu sabre de luz vermelho

ARROW FUNCTIONS

const jedis = [
  { name: 'Luke', darkSide: false },
  { name: 'Anakin', darkSide: true },
]

const darkSide = jedis.filter(function filterJedis(jedi) {
  return jedi.darkSide;
});

console.log(darkSide);
// [{ name: 'Anakin', darkSide: true }]
const jedis = [
  { name: 'Luke', darkSide: false },
  { name: 'Anakin', darkSide: true },
]

const darkSide = jedis.filter((jedi) => {
  return jedi.darkSide;
});

console.log(darkSide);
// [{ name: 'Anakin', darkSide: true }]

const jedis = [
  { name: 'Luke', darkSide: false },
  { name: 'Anakin', darkSide: true },
]

const darkSide = jedis.filter(jedi => jedi.darkSide);

console.log(darkSide);
// [{ name: 'Anakin', darkSide: true }]

Não devemos usar sempre!

Cuidado com o this

const jedi = {
  name: 'Luke',
  darkSide: false,
  lightsaberColor: 'azul',

  attack: function() {
    setTimeout(function() {
      console.log(
        `${this.name} utilizou seu sabre de luz
          ${this.lightsaberColor}`
        );
    }, 1000);
  }
}

jedi.attack();
// utilizou seu sabre de luz
// this.name e this.lightsaberColor = undefined
const jedi = {
  name: 'Luke',
  darkSide: false,
  lightsaberColor: 'azul',

  attack: function() {
    let self = this;
    setTimeout(() => {
      console.log(
        `${self.name} utilizou seu sabre de luz
          ${self.lightsaberColor}`
      );
    }, 1000);
  }
}

jedi.attack();
// Luke utilizou seu sabre de luz azul
const jedi = {
  name: 'Cat Vader',
  darkSide: true,
  lightsaberColor: 'vermelho',

  attack: function() {
    setTimeout(() => {
      console.log(
        `${this.name} utilizou seu sabre de luz
          ${this.lightsaberColor}`
        );
    }, 1000);
  }
}

jedi.attack();
// Cat Vader utilizou seu sabre de luz vermelho

STRINGS

const hero = 'The Flash';

//ES6
hero.startsWith('The') // true;
hero.endsWith('sh') // true;
hero.includes('Fla') // true;

'huebr'.repeat('5') //huebrhuebrhuebrhuebrhuebr

//ES8
'6'.padStart(5, '0'); //00006
'6'.padEnd(5, '0'); //60000

ARRAYS

Array.from()

const hero = Array.from('Batman');

console.log(hero);
// ["B", "a", "t", "m", "a", "n"]

console.log(hero.join(''));
// 'Batman'

// é possível utilizar todas as funçoes
// presentes em um array

Array.of()

const array = Array.of('Batman', 'Dark Knight', 1, 2, {});

console.log(array);
// ["Batman", "Dark Knight", 1, 2, {}]

console.log(hero.join(''));
// "BatmanDark Knight12[object Object]"

// é possível utilizar todas as funçoes
// presentes em um array

Array.find() & Array.findIndex()

const heroes = [
  { name: 'Hulk', publisher: 'Marvel' },
  { name: 'Spiderman', publisher: 'Marvel' },
  { name: 'Thor', publisher: 'Marvel' },
  { name: 'Iron Man', publisher: 'Marvel' },
];

console.log(heroes.find(hero => hero.name === 'Thor'));
// { name: 'Thor', publisher: 'Marvel' }

console.log(heroes.findIndex(hero => hero.name === 'Thor'));
// 2

Array.fill()

let heroes = [
  { name: 'Hulk', publisher: 'Marvel' },
  { name: 'Spiderman', publisher: 'Marvel' },
  { name: 'Thor', publisher: 'Marvel' },
  { name: 'Iron Man', publisher: 'Marvel' },
];

heroes.fill('hueBR', 1, 3);
console.log(heroes);
// [
//  { name: 'Hulk', publisher: 'Marvel' },
//  "hueBR",
//  "hueBR",
//  { name: 'Iron Man', publisher: 'Marvel' },
// ]

Array.includes()

Substitui o Array.indexOf()

let heroes = [
  'Hulk',
  'Spiderman',
  'Thor',
  'Iron Man'
];

heroes.includes('Hulk'); // true
heroes.includes('Black Panther'); // false
heroes.indexOf('Hulk'); // 0
heroes.indexOf('Black Panther'); // -1

OBJECTS

Object.entries()

const heroes = {
  hulk: 0,
  thor: 1,
  blackPanther: 2,
  drStrange: 3,
}

console.log(Object.entries(heroes));
//[
//   ["hulk", 0]
//   ["thor", 1]
//   ["blackPanther", 2]
//   ["drStrange", 3]
//]

Object.values()

const heroes = {
  hulk: 0,
  thor: 1,
  blackPanther: 2,
  drStrange: 3,
}

console.log(Object.values(heroes));
//[0, 1, 2, 3]

DESTRUCTURING

Objects

// pré ES6
var vilan = {
  name: 'Magneto',
  power: 'Manipulação de campos magnéticos',
  hasCape: true,
  hasHelmet: true,
};

var name = vilan.name;
var power = vilan.power;
var hasCape = vilan.hasCape;
var hasHelmet = vilan.hasHelmet;

console.log(name, power, hasCape, hasHelmet);
// Magneto Manipulação de campos magnéticos true true
// pós ES6
const vilan = {
  name: 'Magneto',
  power: 'Manipulação de campos magnéticos',
  hasCape: true,
  hasHelmet: true,
};

const { name, power, hasCape, hasHelmet } = vilan;

console.log(name, power, hasCape, hasHelmet);
// Magneto Manipulação de campos magnéticos true true
// pós ES6
const vilan = {
  name: 'Magneto',
  power: 'Manipulação de campos magnéticos',
  hasCape: true,
  hasHelmet: true,
};

const { name, power: superPower, hasCape, hasHelmet,
  publisher = 'Marvel' } = vilan;

console.log(name, superPower, hasCape, hasHelmet, publisher);
// Magneto Manipulação de campos magnéticos true true Marvel

Arrays

// pós ES6
const vilan = [
  'Magneto',
  'Manipulação de campos magnéticos',
  true,
  true
];

const [ name, power, hasCape, hasHelmet,
  publisher = 'Marvel'] = vilan;

console.log(name, power, hasCape, hasHelmet, publisher);
// Magneto Manipulação de campos magnéticos true true Marvel

SPREAD & REST OPERATORS

Spread

const heroes = ['Hulk', 'Thor', 'Iron Man'];

console.log(heroes);
// ['Hulk', 'Thor', 'Iron Man']

console.log(...heroes);
// Hulk Thor Iron Man
const heroes = ['Hulk', 'Thor', 'Iron Man'];
const vilans = ['Thanos', 'Mandarim', 'Apocalipse'];

const heroesAndVilans = [...heroes, 'Ultron', ...vilans];

console.log(heroesAndVilans);
// ["Hulk", "Thor", "Iron Man", "Ultron", "Thanos", "Mandarim",
//  "Apocalipse"]
function logVilans(vilan1, vilan2, vilan3) {
  console.log(
    `${vilan1}, ${vilan2}, ${vilan3}, são vilões da Marvel`
  );
}

const vilans = ['Thanos', 'Mandarim', 'Apocalipse'];

logVilans(...vilans);
// Thanos, Mandarim, Apocalipse, são vilões da Marvel

Rest

function logVilans(hero, ...vilans) {
  console.log(
    `${vilans.join(', ')}, são vilões da Marvel e o
      ${hero} é o herói`
  );
}

logVilans('Hulk', 'Thanos', 'Mandarim', 'Apocalipse');
// Thanos, Mandarim, Apocalipse, são vilões da Marvel
//  e o Hulk é o herói

CLASSES

Sintatic sugar

//pré ES6
function Hero(name, power) {
  this.name = name;
  this.power = power;
}

Hero.prototype.usePower = function() {
  console.log(
    `${this.name} utilizou o seu poder ${this.power}`
  )
}

const hulk = new Hero('Hulk', 'Smash');
const mercurio = new Hero('Mercúrio', 'Velocidade');

hulk.usePower();
// Hulk utilizou o seu poder Smash

mercurio.usePower();
// Mercúrio utilizou o seu poder Velocidade
//pós ES6
class Character {
  constructor(name, power) {
    this.name = name;
    this.power = power;
  }
}

class Hero extends Character {
  constructor(name, power) {
    super(name, power);
    this.type = 'Herói';
  }

  usePower() {
    console.log(
      `O ${this.type} ${this.name} utilizou o seu poder
        ${this.power}`
    )
  }
}

const hulk = new Hero('Hulk', 'Smash');
const mercurio = new Hero('Mercúrio', 'Velocidade');

hulk.usePower();
// O Herói Hulk utilizou o seu poder Smash

mercurio.usePower();
// O Herói Mercúrio utilizou o seu poder Smash

SYMBOLS

let symbol = Symbol('Identificador');
let symbolCopia = Symbol('Identificador');

console.log(symbol === symbolCopia) // false

let a = 'a';
let b = 'a';
console.log(a === b) // true
let obj = {
  [Symbol('identifier')]: '1' ,
  name: 'Objeto com identificador'
};

console.log(Object.keys(obj));
// { name: "Objeto com identificador",
//  Symbol(Identificador): "1" }

console.log(Object.keys(obj));
// ["name"]

console.log(Object.getOwnPropertySymbols(obj));
// [Symbol(Identificador)]

MAP & WEAKMAP

Map

let map = new Map();

map.set('Magneto', 1);
map.set('Apocalipse', 2);
map.set('Thanos', 3);

console.log(map);
// Map(2) {"Magneto" => 1, "Apocalipse" => 2, "Thanos" => 3}
map.size
// 3
map.delete('Magneto');
// true
console.log(map);
// Map(2) {"Apocalipse" => 2, "Thanos" => 3}
map.has('Apocalipse');
// true

WeakMap

let obj1 = { name: 'Thanos' };
let obj2 = { name: 'Magneto' };
let map = new WeakMap();

map.set(obj1, 'Descrição do Thanos');
map.set(obj2, 'Descrição do Magneto');

console.log(map);
// WeakMap {, {…} => "Descrição do Thanos",
//  {…} => "Descrição do Magneto"}

obj1 = null;

console.log(map);
// WeakMap {{…} => "Descrição do Magneto"}

SET & WEAKSET

Set

let set = new Set(['Magneto', 'Apocalipse', 'Thanos']);

set.add('Red Skull');

console.log(set);
Set(4) {"Magneto", "Apocalipse", "Thanos", "Red Skull"}
set.size
// 4
set.delete('Magneto');
// true
console.log(set);
// Set(3) {"Apocalipse", "Thanos", "Red Skull"}
set.has('Apocalipse');
// true
set.clear();
//Set(0) {}

WeakSet

let obj1 = { name: 'Thanos' };
let obj2 = { name: 'Magneto' };

let set = new WeakSet([obj1, obj2]);

set.delete(obj1); // true
set.has(obj2); // true

GENERATORS

function *generatorSteps() {
  console.log('first');
  yield 'first yield';
  console.log('second');
  yield 'second yield';
  console.log('third');
  yield 'third yield';
}

const iterator = generatorSteps();

iterator.next();
// first
// {value: "first yield", done: false}

iterator.next();
// fisecondrst
// {value: "second yield", done: false}

iterator.next();
// third
// {value: "third yield", done: false}

iterator.next();
// third
// {value: undefined, done: true}

ASYNC / AWAIT

const sleepAndResolve = async function() {
  return new Promise((resolve, reject)=>{
    setTimeout(() => {
      resolve({ status: 'resolved :D' });
    }, 2000);
  });
};

async function demoAsyncAwait() {
  console.log('Iniciando a função');
  const data = await sleepAndResolve();
  console.log('Finalizando a função');
  console.log(data);
}

demoAsyncAwait();
// Iniciando a função
// APÓS 2 SEGUNDOS...
// Finalizando a função
// {status: "resolved :D"}

Tratamento de erros feito com try / catch

PROXY

let hero = {
  name: 'Hulk',
  attack: 'Smash',
};

let proxy = new Proxy(hero, {
  get(target, name) {
    console.log(target, name);
    console.log('proxy get');
    return target[name];
  },
  set(target, name, value) {
    console.log(target, name);
    console.log('proxy set');
    target[name] = value.toUpperCase();
  },
});

proxy.name
// {name: "Hulk", attack: "Smash"} "name"
// proxy get
// Hulk
proxy.name = 'Magneto';
// {name: "Hulk", attack: "Smash"} "name"
// proxy set
hero.name
// MAGNETO

ESNext

Template Literals Revision

A New “s” Flag for Regex

Referências

https://github.com/tc39/proposals

https://www.ecma-international.org/publications/standards/Ecma-262-arch.htm

https://tc39.github.io/process-document/

https://www.udemy.com/js-com-tdd-na-pratica

http://nitayneeman.com/posts/a-taste-from-ecmascript-2018/

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/template_strings

https://node.green/

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects

https://braziljs.org/blog/async-await-js-assincronamente-sincrono/

Dúvidas?

@icarcal

Obrigado