| Stage | Purpose | Phase | 
|---|---|---|
| 0 | √ Allow input into the specification | N/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 | 
// declaração de variáveis pré ES6
var jedi = 'Luke Skywalker';
// sofre hoisting
jedi = 'Luke Skywalker';
var jedi;
// declaração de variáveis pós do ES6
// valor pode ser alterado
let jedi = 'Luke Skywalker';
jedi = 'yoda';
// "imutável"
const jedi = 'Luke Skywalker';
jedi = 'Anakin';
// Uncaught TypeError: Assignment to constant variable.
const jedi = {
  name: 'Luke Skywalker',
  lightsaberColor: 'azul',
}
jedi.lightsaberColor = 'vermelho';// 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
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
// 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,
}// 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
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 }]
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
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'); //60000const 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
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
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
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' },
// ]
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'); // -1const heroes = {
  hulk: 0,
  thor: 1,
  blackPanther: 2,
  drStrange: 3,
}
console.log(Object.entries(heroes));
//[
//   ["hulk", 0]
//   ["thor", 1]
//   ["blackPanther", 2]
//   ["drStrange", 3]
//]
const heroes = {
  hulk: 0,
  thor: 1,
  blackPanther: 2,
  drStrange: 3,
}
console.log(Object.values(heroes));
//[0, 1, 2, 3]// 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
// 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 Marvelconst 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
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//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
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)]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
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"}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) {}
let obj1 = { name: 'Thanos' };
let obj2 = { name: 'Magneto' };
let set = new WeakSet([obj1, obj2]);
set.delete(obj1); // true
set.has(obj2); // truefunction *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}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"}
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
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/

