Skip to content

AlexGalhardo/Learning-JavaScript

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Async Await JS

Screen.Recording.2024-04-25.at.15.21.18.mov

console.

Comando Descrição Exemplo
assert(expression, message) Envia uma mensagem quando expression é avaliado como falso. console.assert((x == 1), "assert message: x != 1");
clear() Limpa as mensagens da janela do console, incluindo mensagens de erro de script, e limpa também o script exibido na janela do console. Não limpa o script inserido no prompt de entrada do console. console.clear();
count(title) Envia o número de vezes que o comando count foi chamado para a janela do console. Cada chamada do comando count é identificada exclusivamente pelo titleopcional.

A entrada existente na janela do console é identificada pelo parâmetro title (se presente) e atualizada pelo comando count. Não é criada uma nova entrada.
console.count();

console.count("inner loop");
debug(message) Envia message para a janela do console.

Esse comando é idêntico a console.log.

Os objetos transmitidos usando o comando são convertidos em um valor de cadeia de caracteres.
console.debug("logging message");
dir(object) Envia o objeto especificado para a janela do console e o exibe em um visualizador de objetos. Você pode usar o visualizador para inspecionar propriedades na janela do console. console.dir(obj);
dirxml(object) Envia o nó XML object especificado para a janela do console e o exibe como uma árvore de nós XML. console.dirxaml(xmlNode);
error(message) Envia message para a janela do console. O texto da mensagem está em vermelho e antecedido por um símbolo de erro.

Os objetos transmitidos usando o comando são convertidos em um valor de cadeia de caracteres.
console.error("error message");
group(title) Inicia um agrupamento das mensagens enviadas à janela do console e envia o title opcional como um rótulo de grupo. Os grupos podem ser aninhados e aparecer em um modo de exibição de árvore na janela do console.

Os comandos group* podem facilitar a exibição da saída da janela do console em alguns cenários, como quando um modelo de componente está em uso.
console.group("Level 2 Header");
console.log("Level 2");
console.group();
console.log("Level 3");
console.warn("More of level 3");
console.groupEnd();
console.log("Back to level 2");
console.groupEnd();
console.debug("Back to the outer level");
groupCollapsed(title) Inicia um agrupamento das mensagens enviadas à janela do console e envia o title opcional como um rótulo de grupo. Os grupos enviados usando groupCollapsed aparecem em uma exibição recolhida por padrão. Os grupos podem ser aninhados e aparecer em um modo de exibição de árvore na janela do console. O uso é o mesmo do comando group.

Consulte o exemplo do comando group.
groupEnd() Encerra o grupo atual.

Requisitos:

Visual Studio 2013
Consulte o exemplo do comando group.
info(message) Envia message para a janela do console. A mensagem é prefaciada por um símbolo de informação. console.info("info message");

Para obter mais exemplos, confira Formatando a saída do console.log mais adiante neste tópico.
log(message) Envia message para a janela do console.

Se você transmitir um objeto, este comando o enviará para a janela do console e o exibirá num visualizador de objeto. Você pode usar o visualizador para inspecionar propriedades na janela do console.
console.log("logging message");
msIsIndependentlyComposed(element) Usado em aplicativos da Web. Sem suporte em aplicativos UWP usando JavaScript. Não há suporte.
profile(reportName) Usado em aplicativos da Web. Sem suporte em aplicativos UWP usando JavaScript. Não há suporte.
profileEnd() Usado em aplicativos da Web. Sem suporte em aplicativos UWP usando JavaScript. Não há suporte.
select(element) Seleciona o HTML especificado element no Explorador do DOM. console.select(element);
time (name) Inicia um temporizador que é identificado pelo parâmetro name opcional. Quando usado com console.timeEnd, calcula o tempo decorrido entre time e timeEnd e envia o resultado (medido em ms) ao console usando a cadeia de caracteres name como prefixo. Usado para habilitar a instrumentação de código do aplicativo para medir o desempenho. console.time("app start"); app.start(); console.timeEnd("app start");
timeEnd(name) Interrompe um temporizador que é identificado pelo parâmetro name opcional. Consulte o comando time do console. console.time("app start"); app.start(); console.timeEnd("app start");
trace() Envia um rastreamento de pilha à janela do console. O rastreamento inclui a pilha de chamadas completa e informações como o nome do arquivo, o número da linha e o número da coluna. console.trace();
warn(message) Envia message para a janela do console, prefaciada por um símbolo de aviso.

Os objetos transmitidos usando o comando são convertidos em um valor de cadeia de caracteres.
console.warn("warning message");

Comandos variados

Esses comandos também estão disponíveis na janela do Console do JavaScript (não estão disponíveis no código).

Comando Descrição Exemplo
$0, $1, $2, $3, $4 Retorna o elemento especificado para a janela do console. $0 retorna o elemento selecionado atualmente no Explorador do DOM, $1 retorna o elemento selecionado anteriormente no Explorador do DOM e assim por diante, até o quarto elemento selecionado anteriormente. U$3
$(id) Retorna um elemento por ID. Este é um comando de atalho para document.getElementById(id), em que id é uma cadeia de caracteres que representa a ID do elemento. $("contenthost")
$$(selector) Retorna uma matriz de elementos que correspondem ao seletor especificado usando a sintaxe do seletor de CSS. Este é um comando de atalho para document.querySelectorAll(). $$(".itemlist")
cd()

cd(window)
Permite que você altere o contexto de avaliação da expressão, da janela de nível superior padrão da página para a janela do quadro especificado. Chamar cd() sem parâmetros reverte o contexto para a janela de nível superior. cd();

cd(myframe);
select(element) Seleciona o elemento especificado no Explorador do DOM. select(document.getElementById("element"));

select($("element"));

select($1);
dir(object) Retorna um visualizador para o objeto especificado. Você pode usar o visualizador para inspecionar propriedades na janela do console. dir(obj);

Cookies, LocalStorage, SessionStorage

storage

localSotrage.setItem('name', 'alex')
localSotrage.getItem('name') // alex
localStorage.removeItem('name')
localStorage.clear()

sessionStorage.setItem('name', 'John')
sessionStorage.getItem('name') // John
sessionStorage.removeItem('name')
sessionStorage.clear()

document.cookie = `name=Bob; expires=${new Date(2021, 0, 1).toUTCString()}`
console.log(document.cookie)

Stackoverflow

function f () {
  return f()
}

f()

Async Event Loop

console.log('script start')

const interval = setInterval(() => {
    console.log('setInterval')
}, 0)

setTimeout(() => {
    console.log('setTimeout 1')
    Promise.resolve()
        .then(() => console.log('promise 3'))
        .then(() => console.log('promise 4'))
        .then(() => {
            setTimeout(() => {
                console.log('setTimeout 2')
                Promise.resolve().then(() => console.log('promise 5'))
                    .then(() => console.log('promise 6'))
                    .then(() => clearInterval(interval))
            }, 0)
        })
}, 0)

Promise.resolve()
    .then(() => console.log('promise 1'))
    .then(() => console.log('promise 2'))

// OUTPUTS
script start
promise 1
promise 2
setInterval
setTimeout 1
promise 3
promise 4
setInterval
setTimeout 2
promise 5
promise 6

Arrays (under the hood) Fast Reference

function forEach(array, cb) {
  for (let i = 0; i < array.length; i++) {
    cb(array[i], i, array)
  }
}

function map(array, cb) {
  const newArray = []
  for (let i = 0; i < array.length; i++) {
    newArray.push(cb(array[i], i, array))
  }

  return newArray
}

function filter(array, cb) {
  const newArray = []
  for (let i = 0; i < array.length; i++) {
    const element = array[i]
    if (cb(element, i, array)) newArray.push(element)
  }

  return newArray
}

function reduce(array, cb, initialValue) {
  let currentValue = initialValue
  for (let i = 0; i < array.length; i++) {
    const element = array[i]
    if (initialValue == null && i === 0) {
      currentValue = element
    } else {
      currentValue = cb(currentValue, element, i, array)
    }
  }

  return currentValue
}

function some(array, cb) {
  for (let i = 0; i < array.length; i++) {
    if (cb(array[i], i, array)) return true
  }

  return false
}

function every(array, cb) {
  for (let i = 0; i < array.length; i++) {
    if (!cb(array[i], i, array)) return false
  }

  return true
}

function flat(array, depth = 1) {
  const newArray = []
  for (let i = 0; i < array.length; i++) {
    const element = array[i]
    if (Array.isArray(element) && depth > 0) {
      newArray.push(...flat(element, depth - 1))
    } else {
      newArray.push(element)
    }
  }
  return newArray
}

function find(array, cb) {
  for (let i = 0; i < array.length; i++) {
    const element = array[i]
    if (cb(element, i, array)) return element
  }
}

Typescript

JavaScript Básico

  • VARIÁVEIS
    • Responsáveis por guardar dados na memória.
    • Inicia com a palavra var, let ou const
var nome = 'André';
let idade = 28;
const possuiFaculdade = true;
COPIAR
EVITAM REPETIÇÕES
DRY (Don't repeat yourself)

var preco = 20;
var totalComprado = 5;
var precoTotal = preco * totalComprado;
  • SINTAXE
    • Palavra chave var seguida do nome, sinal de igual e o valor.
var nome = 'André';
var idade = 28;
var possuiFaculdade = true;
  • VÍRGULA
    • Utilizei a vírgula para criar mais de uma variável, sem repetir a palavra chave var.
var nome = 'André',
    idade = 28,
    possuiFaculdade = true;
  • SEM VALOR
    • Pode declarar ela e não atribuir valor inicialmente.
var precoAplicativo;
// retorna undefined
  • NOME
    • Os nomes podem iniciar com $, _, ou letras.
    • Podem conter números mas não iniciar com eles
    • Case sensitive
      • nome é diferente de Nome
    • Não utilizar palavras reservadas
    • https://www.w3schools.com/js/js_reserved.asp
    • Camel case
      • É comum nomearmos assim: abrirModal
NOME
// Inválido
var §nome;
var function;
var 1possuiFaculdade;

// Válido
var $selecionar;
var _nome;
var possuiFaculdadeNoExterior;
  • DECLARAR
    • Erro ao tentar utilizar uma variável que não foi declarada.
console.log(nome);
// retorna nome is not defined
  • HOISTING
    • São movidas para cima do código, porém o valor atribuído não é movido.
console.log(nome);
var nome = 'André';
// Retorna undefined

var profissao = 'Designer';
console.log(profissao);
// Retornar Designer
  • MUDAR O VALOR ATRIBUÍDO
    • É possível mudar os valores atribuídos a variáveis declaradas com var e let. Porém não é possível modificar valores das declaradas com const
var idade = 28;
idade = 29;

let preco = 50;
preco = 25;

const possuiFaculdade = true;
possuiFaculdade = false;
// Retorna um erro
  • 7 TIPOS DE DADOS
    • Todos são primitivos exceto os objetos.
var nome = 'André'; // String
var idade = 28; // Number
var possuiFaculdade = true; // Boolean
var time; // Undefined
var comida = null; // Null
var simbolo = Symbol() // Symbol
var novoObjeto = {} // Object
  • Primitivos são dados imutáveis.
VERIFICAR TIPO DE DADO
var nome = 'André';
console.log(typeof nome);
// retorna string
  • typeof null retorna object

  • STRING

    • Você pode somar uma string e assim concatenar as palavras.
var nome = 'André';
var sobrenome = 'Rafael';
var nomeCompleto = nome + ' ' + sobrenome;
  • STRING
    • Você pode somar números com strings, o resultado final é sempre uma string.
var gols = 1000;
var frase = 'Romário fez ' + gols + ' gols';
COPIAR
ASPAS DUPLAS, SIMPLES E TEMPLATE STRING
'JavaScript é "super" fácil';
"JavaScript é 'super' fácil";
"JavaScript é \"super\" fácil";
`JavaScript é "super" fácil"`;
"JavaScript é "super" fácil"; // Inválido
  • Não necessariamente precisamos atribuir valores a uma variável

  • TEMPLATE STRING

var gols = 1000;
var frase1 = 'Romário fez ' + gols + ' gols';
var frase2 = `Romário fez ${gols} gols`; // Utilizando Template String
  • Você deve passar expressões / variáveis dentro de ${}

JavaScript Assíncrono

  • SÍNCRONO VS ASSÍNCRONO

    • Síncrono
      • Espera a tarefa acabar para continuar com a próxima.
    • Assíncrono
      • Move para a próximo tarefa antes da anterior terminar. O trabalho será executado no 'fundo' e quando terminado, será colocado na fila (Task Queue).
      • Exemplos
        • setTimeout, Ajax, Promises, Fetch, Async.
  • NEW PROMISE()

    • Promise é uma função construtora de promessas.
    • Existem dois resultados possíveis de uma promessa, ela pode ser resolvida, com a execução do primeiro argumento, ou rejeitada se o segundo argumento for ativado.
const promessa = new Promise(function(resolve, reject) {
  let condicao = true;
  if(condicao) {
    resolve();
  } else {
    reject();
  }
});

console.log(promessa); // Promise {<resolved>: undefined}
  • RESOLVE()
    • Podemos passar um argumento na função resolve(), este será enviado junto com a resolução da Promise.
const promessa = new Promise(function(resolve, reject) {
  let condicao = true;
  if(condicao) {
    resolve('Estou pronto!');
  } else {
    reject();
  }
});

console.log(promessa); // Promise {<resolved>: "Estou pronto!"}
  • REJECT()
    • Quando a condição de resolução da promise não é atingida, ativamos a função reject para rejeitar a mesma.
    • Podemos indicar no console um erro, informando que a promise foi rejeitada.
const promessa = new Promise(function(resolve, reject) {
  let condicao = false;
  if(condicao) {
    resolve('Estou pronto!');
  } else {
    reject(Error('Um erro ocorreu.'));
  }
});

console.log(promessa); // Promise {<rejected>: Error:...}
  • THEN()
    • O poder das Promises está no método then() do seu protótipo.
    • O Callback deste método só será ativado quando a promise for resolvida.
    • O argumento do callback será o valor passado na função resolve.
const promessa = new Promise(function(resolve, reject) {
  let condicao = true;
  if(condicao) {
    resolve('Estou pronto!');
  } else {
    reject(Error('Um erro ocorreu.'));
  }
});

promessa.then(function(resolucao) {
  console.log(resolucao); // 'Estou pronto!'
});
  • ASSÍNCRONO
    • As promises não fazem sentido quando o código executado dentro da mesma é apenas código síncrono.
    • O poder está na execução de código assíncrono que executará o resolve() ao final dele.
const promessa = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Resolvida');
  }, 1000);
});

promessa.then(resolucao => {
  console.log(resolucao); // 'Resolvida' após 1s
});
  • THEN().THEN()
    • O método then() retorna outra Promise. Podemos colocar then() após then() e fazer um encadeamento de promessas.
    • O valor do primeiro argumento de cada then, será o valor do retorno anterior.
const promessa = new Promise((resolve, reject) => {
  resolve('Etapa 1');
});

promessa.then(resolucao => {
  console.log(resolucao); // 'Etapa 1';
  return 'Etapa 2';
}).then(resolucao => {
  console.log(resolucao) // 'Etapa 2';
  return 'Etapa 3';
}).then(r => r + 4)
.then(r => {
  console.log(r); // Etapa 34
});
  • CATCH()
    • O método catch(), do protótipo de Promises, adiciona um callback a promise que será ativado caso a mesma seja rejeitada.
const promessa = new Promise((resolve, reject) => {
  let condicao = false;
  if(condicao) {
    resolve('Estou pronto!');
  } else {
    reject(Error('Um erro ocorreu.'));
  }
});

promessa.then(resolucao => {
  console.log(resolucao);
}).catch(reject => {
  console.log(reject);
});
  • THEN(RESOLVE, REJECT)
    • Podemos passar a função que será ativada caso a promise seja rejeitada, direto no método then, como segundo argumento.
const promessa = new Promise((resolve, reject) => {
  let condicao = false;
  if(condicao) {
    resolve('Estou pronto!');
  } else {
    reject(Error('Um erro ocorreu.'));
  }
});

promessa.then(resolucao => {
  console.log(resolucao);
}, reject => {
  console.log(reject);
});
  • FINALLY()
    • finally() executará a função anônima assim que a promessa acabar.
    • A diferença do finally é que ele será executado independente do resultado, se for resolvida ou rejeitada.
const promessa = new Promise((resolve, reject) => {
  let condicao = false;
  if(condicao) {
    resolve('Estou pronto!');
  } else {
    reject(Error('Um erro ocorreu.'));
  }
});

promessa.then(resolucao => {
  console.log(resolucao);
}, reject => {
  console.log(reject);
}).finally(() => {
  console.log('Acabou'); // 'Acabou'
});
  • PROMISE.ALL()
    • Retornará uma nova promise assim que todas as promises dentro dela forem resolvidas ou pelo menos uma rejeitada.
    • A reposta é uma array com as respostas de cada promise.
const login = new Promise(resolve => {
  setTimeout(() => {
    resolve('Login Efetuado');
  }, 1000);
});
const dados = new Promise(resolve => {
  setTimeout(() => {
    resolve('Dados Carregados');
  }, 1500);
});

const tudoCarregado = Promise.all([login, dados]);

tudoCarregado.then(respostas => {
  console.log(respostas); // Array com ambas respostas
});
  • PROMISE.RACE()
    • Retornará uma nova promise assim que a primeira promise for resolvida ou rejeitada. Essa nova promise terá a resposta da primeira resolvida.
const login = new Promise(resolve => {
  setTimeout(() => {
    resolve('Login Efetuado');
  }, 1000);
});
const dados = new Promise(resolve => {
  setTimeout(() => {
    resolve('Dados Carregados');
  }, 1500);
});

const carregouPrimeiro = Promise.race([login, dados]);

carregouPrimeiro.then(resposta => {
  console.log(resposta); // Login Efetuado
});
  • FETCH API
    • Permite fazermos requisições HTTP através do método fetch(). Este método retorna a resolução de uma Promise. Podemos então utilizar o then para interagirmos com a resposta, que é um objeto do tipo Response.
fetch('./arquivo.txt').then(function(response) {
  console.log(response); // Response HTTP (Objeto)
});
  • RESPONSE
    • O objeto Response, possui um corpo com o conteúdo da resposta. Esse corpo pode ser transformado utilizando métodos do protótipo do objeto Response. Estes retornam outras promises.
fetch('./arquivo.txt').then(function(response) {
  return response.text();
}).then(function(corpo) {
  console.log(corpo);
});
  • SERVIDOR LOCAL
    • O fetch faz uma requisição HTTP/HTTPS. Se você iniciar um site local diretamente pelo index.html, sem um servidor local, o fetch não irá funcionar.
fetch('c:/files/arquivo.txt')
.then((response) => {
  return response.text();
})
.then((corpo) => {
  console.log(corpo);
}); // erro
  • Se dermos um espaço após o objeto ou pularmos linha, o método continua funcionando.

  • .JSON()

    • Um tipo de formato de dados muito utilizado com JavaScript é o JSON (JavaScript Object Notation), pelo fato dele possuir basicamente a mesma sintaxe que a de um objeto js. .json() transforma um corpo em json em um objeto JavaScript.
fetch('https://viacep.com.br/ws/01001000/json/')
.then(response => response.json())
.then(cep => {
  console.log(cep.bairro, cep.logradouro);
});
  • .TEXT()
    • Podemos utilizar o .text() para diferentes formatos como txt, json, html, css, js e mais.
const styleElement = document.createElement('style');

fetch('./style.css')
.then(response => response.text())
.then(style => {
  styleElement.innerHTML = style;
  document.body.appendChild(styleElement);
});
  • HTML E .TEXT()
    • Podemos pegar um arquivo inteiro em HTML, transformar o corpo em texto e inserir em uma div com o innerHTML. A partir dai podemos manipular esses dados como um DOM qualquer.
const div = document.createElement('div');

fetch('./sobre.html')
.then(response => response.text())
.then(htmlBody => {
  div.innerHTML = htmlBody;
  const titulo = div.querySelector('h1');
  document.querySelector('h1').innerText = titulo.innerText;
});
  • .BLOB()
    • Um blob é um tipo de objeto utilizado para representação de dados de um arquivo. O blob pode ser utilizado para transformarmos requisições de imagens por exemplo. O blob gera um URL único.
const div = document.createElement('div');

fetch('./imagem.png')
.then(response => response.blob())
.then(imgBlob => {
  const blobUrl = URL.createObjectURL(imgBlob);
  console.log(blobUrl);
});
  • .CLONE()
    • Ao utilizarmos os métodos acima, text, json e blob, a resposta é modificada. Por isso existe o método clone, caso você necessite transformar uma resposta em diferentes valores.
const div = document.createElement('div');

fetch('https://viacep.com.br/ws/01001000/json/')
.then(response => {
  const cloneResponse = response.clone();
  response.json().then(json => {
    console.log(json)
  });
  cloneResponse.text().then(text => {
    console.log(text)
  });
});
  • .HEADERS
    • É uma propriedade que possui os cabeçalhos da requisição. É um tipo de dado iterável então podemos utilizar o forEach para vermos cada um deles.
const div = document.createElement('div');

fetch('https://viacep.com.br/ws/01001000/json/')
.then(response => {
  response.headers.forEach(console.log);
});
  • .STATUS E .OK
    • Retorna o status da requisição. Se foi 404, 200, 202 e mais. ok retorna um valor booleano sendo true para uma requisição de sucesso e false para uma sem sucesso.
const div = document.createElement('div');

fetch('https://viacep.com.br/ws/01001000/json/')
.then(response => {
  console.log(response.status, response.ok);
  if(response.status === 404) {
    console.log('Página não encontrada')
  }
});
  • .URL E .TYPE
    • .url retorna o url da requisição. .type retorna o tipo da reposta.
const div = document.createElement('div');

fetch('https://viacep.com.br/ws/01001000/json/')
.then(response => {
  console.log(response.type, response.url);
});

//types
// basic: feito na mesma origem
// cors: feito em url body pode estar disponível
// error: erro de conexão
// opaque: no-cors, não permite acesso de outros sites
  • JSON
    • JavaScript Object Notation (JSON) é um formato de organização de dados, compostos por um conjunto de chave e valor. As aspas duplas são obrigatórias, tanto na chave quanto no valor quando este for uma string.
{
  "id": 1,
  "nome": "Andre",
  "email": "[email protected]"
}
  • VALORES
    • Os valores podem ser números, strings, boolean, arrays, objetos e null.
{
  "id": 1,
  "faculdade": true,
  "pertences": [
    "lapis",
    "caneta",
    "caderno"
  ],
  "endereco": {
    "cidade": "Rio de Janeiro",
    "pais": "Brasil"
  },
  "casado": null
}
  • ARRAYS E OBJETOS
    • É comum possuirmos array's com objetos em cada valor da array. Cuidado para não colocar vírgula no último item do objeto ou array.
[
  {
    "id": 1,
    "aula": "JavaScript",
    "tempo": "25min"
  },
  {
    "id": 2,
    "aula": "HTML",
    "tempo": "15min"
  },
  {
    "id": 3,
    "aula": "CSS",
    "tempo": "10min"
  }
]
  • JSON.PARSE() E JSON.STRINGIFY()
    • JSON.parse() irá transformar um texto JSON em um objeto JavaScript. JSON.stringify() irá transformar um objeto JavaScript em uma string no formato JSON.
const textoJSON = '{"id": 1, "titulo": "JavaScript", "tempo": "25min"}';
const textoOBJ = JSON.parse(textoJSON);

const enderecoOBJ = {
  cidade: "Rio de Janeiro",
  rua: "Ali Perto",
  pais: "Brasil",
  numero: 50,
}
const enderecoJSON = JSON.stringfy(enderecoOBJ);
  • EXEMPLO REAL
    • Podemos guardar por exemplo no localStorage, uma string como valor de uma propriedade.
    • E retornar essa string como um objeto.
const configuracoes = {
  player: "Google API",
  tempo: 25.5,
  aula: "2-1 JavaScript",
  vitalicio: true,
}

localStorage.configuracoes = JSON.stringify(configuracoes);
const pegarConfiguracoes = JSON.parse(localStorage.configuracoes);

APIs

  • Um servidor, aplicativo, objeto JavaScript ou qualquer outra coisa que você interaja através de comandos. Ao digitar uma URL, estamos utilizando a API do browser para se comunicar com a API do servidor.

  • Programação, isso significa que um comando irá encadear uma cadeia de eventos pré-definidos. O resultado esperado é geralmente o mesmo.

  • A interface são os comandos criados para permitir a interação com a aplicação. Ex: 'VIOLAO'.toLowerCase() é um método que faz parte da interface do objeto String. A interação com a interface retorna um efeito / resposta.

  • EXEMPLOS DE API'S

  • HTTP

    • Hypertext Transfer Protocol é o protocolo utilizando para enviarmos/recebermos arquivos e dados na Web.
fetch('https://pokeapi.co/api/v2/pokemon/')
.then(r => r.json())
.then(pokemon => {
  console.log(pokemon);
});
  • URL E METHOD
    • Uma requisição HTTP é feita através de uma URL. O método padrão é o GET, mas existem outros como POST, UPDATE, DELETE, HEADER.
const url = 'https://jsonplaceholder.typicode.com/posts/';
const options = {
  method: 'POST',
  headers: {
    "Content-Type": "application/json; charset=utf-8",
  },
  body: '"aula": "JavaScript"';
}

fetch(url, options);
.then(response => response.json())
.then(json => {
  console.log(json);
});
  • METHOD

    • GET
      • Puxa informação, utilizado para pegar posts, usuários e etc.
    • POST
      • Utilizado para criar posts, usuários e etc.
    • PUT
      • Geralmente utilizado para atualizar informações.
    • DELETE
      • Deleta uma informação.
    • HEAD
      • Puxa apenas os headers.
  • GET

    • GET irá puxar as informações da URL. Não é necessário informar que o método é GET, pois este é o padrão.
const url = 'https://jsonplaceholder.typicode.com/posts/';
fetch(url, {
  method: 'GET'
})
.then(r => r.json())
.then(r => console.log(r))
  • POST
    • POST irá criar uma nova postagem, utilizando o tipo de conteúdo especificado no headers e utilizando o conteúdo do body.
const url = 'https://jsonplaceholder.typicode.com/posts/';

fetch(url, {
  method: 'POST',
  headers: {
    "Content-Type": "application/json; charset=utf-8",
  },
  body: '{"titulo": "JavaScript"}'
})
.then(r => r.json())
.then(r => console.log(r))
  • PUT
    • PUT irá atualizar o conteúdo do URL com o que for informado no conteúdo do body.
const url = 'https://jsonplaceholder.typicode.com/posts/1/';

fetch(url, {
  method: 'PUT',
  headers: {
    "Content-Type": "application/json; charset=utf-8",
  },
  body: '{"titulo": "JavaScript"}'
})
.then(r => r.json())
.then(r => console.log(r))
  • HEAD
    • HEAD puxa apenas os headers. É uma requisição mais leve pois não puxa o body.
const url = 'https://jsonplaceholder.typicode.com/posts/1/';

fetch(url, {
  method: 'HEAD',
})
.then(response => {
  response.headers.forEach(console.log);
  console.log(response.headers.get('Content-Type'));
});
  • HEADERS

    • Cache-Control
      • Tempo que o arquivo deve ficar em cache em segundos. Ex: public, max-age=3600
    • Content-Type
      • Tipo de conteúdo. Ex: text/html; charset=utf-8. Indicar o tipo de arquivo principalmente em métodos POST e PUT.
    • Lista de Headers
  • CORS

    • Cross-Origin Resource Sharing, gerencia como deve ser o compartilhamento de recursos entre diferente origens.
    • É definido no servidor se é permitido ou não o acesso dos recursos através de scripts por outros sites.
    • Utilizando o Access-Control-Allow-Origin.
    • Se o servidor não permitir o acesso, este será bloqueado.
    • É possível passar por cima do bloqueio utilizando um proxy.
    • CORS é um acordo entre browser / servidor ou servidor / servidor.
    • Ele serve para dar certa proteção ao browser, mas não é inviolável.
const url = 'https://cors-anywhere.herokuapp.com/https://www.google.com/';
const div = document.createElement('div');

fetch(url)
.then(r => r.text())
.then(r => {
  div.innerHTML = r;
  console.log(div);
});
  • ASYNC / AWAIT
    • A palavra chave async indica que a função possui partes assíncronas e que você pretende esperar a resolução da mesma antes de continuar. O await irá indicar a promise que devemos esperar. Faz parte do ES8.
async function puxarDados() {
  const dadosResponse = await fetch('./dados.json');
  const dadosJSON = await dadosResponse.json();
  
  document.body.innerText = dadosJSON.titulo;
}

puxarDados();
  • THEN / ASYNC
    • A diferença é uma sintaxe mais limpa.
function iniciarFetch() {
  fetch('./dados.json')
  .then(dadosResponse => dadosResponse.json())
  .then(dadosJSON => {
    document.body.innerText = dadosJSON.titulo;
  })
}
iniciarFetch();

async function iniciarAsync() {
  const dadosResponse = await fetch('./dados.json');
  const dadosJSON = await dadosResponse.json();
  document.body.innerText = dadosJSON.titulo;
}
iniciarAsync();
  • TRY / CATCH
    • Para lidarmos com erros nas promises, podemos utilizar o try e o catch na função.
async function puxarDados() {
  try {
    const dadosResponse = await fetch('./dados.json');
    const dadosJSON = await dadosResponse.json();
    document.body.innerText = dadosJSON.titulo;
  }
  catch(erro) {
    console.log(erro);
  }
}
puxarDados();
  • INICIAR FETCH AO MESMO TEMPO
    • Não precisamos esperar um fetch para começarmos outro. Porém precisamos esperar a resposta resolvida do fetch para transformarmos a response em json.
async function iniciarAsync() {
  const dadosResponse = fetch('./dados.json');
  const clientesResponse = fetch('./clientes.json');

  // ele espera o que está dentro da expressão () ocorrer primeiro
  const dadosJSON = await (await dadosResponse).json();
  const clientesJSON = await (await clientesResponse).json();
}
iniciarAsync();
  • PROMISE
    • O resultado da expressão à frente de await tem que ser uma promise.
      -E o retorno do await será sempre o resultado desta promise.
async function asyncSemPromise() {
  // Console não irá esperar.
  await setTimeout(() => console.log('Depois de 1s'), 1000);
  console.log('acabou');
}
asyncSemPromise();

async function iniciarAsync() {
  await new Promise(resolve => {
    setTimeout(() => resolve(), 1000)
  });
  console.log('Depois de 1s');
}
iniciarAsync();
  • HISTORY
    • É possível acessarmos o histórico de acesso do browser em uma sessão específica através do window.history. O objeto history possui diferentes métodos e propriedades.
window.history;
window.history.back(); // vai para a anterior
window.history.forward(); // vai para a próxima
  • PUSHSTATE()
    • A parte interessante de manipularmos o history é que podemos modificar o histórico e adicionar um novo item. ``js window.history.pushState(obj, title, url).

// Em obj podemos enviar um objeto com dados // mas o seu uso é restrito por isso geralmente utilizamos // null. O title ainda é ignorado por alguns browsers, também // utilizamos null nele. O url que é parte importante.

window.history.pushState(null, null, 'sobre.html'); ``

  • POPSTATE

    • O evento popstate pode ser adicionado ao objeto window. Assim podemos executar uma função toda vez que o usuário clicar no botão de voltar ou próximo. js window.addEventListener('popstate', () => { fetchPage(window.location.pathname); });
  • FETCH E HISTORY

    • Ao puxarmos dados via fetch api, o url da página continua o mesmo. Ao combinar fetch com a history api conseguimos simular uma navegação real entre páginas, sem a necessidade de recarregamento da mesma. js async function fetchPage(url) { const pageReponse = await fetch(url); const pageText = await pageReponse.text(); window.history.pushState(null, null, url); }

Classes e Objetos

  • CONSTRUCTOR FUNCTION
    • Funções responsáveis pela criação de objetos. O conceito de uma função construtora de objetos é implementado em outras linguagens como Classes.
function Button(text, background) {
  this.text = text;
  this.background = background;
}

Button.prototype.element = function() {
  const buttonElement = document.createElement('button');
  buttonElement.innerText = this.text;
  buttonElement.style.background = this.background;
  return buttonElement;
}

const blueButton = new Button('Comprar', 'blue');
  • CLASS
    • O ES6 trouxe uma nova sintaxe para implementarmos funções construtoras. Agora podemos utilizar a palavra chave class. É considerada syntactical sugar, pois por baixo dos panos continua utilizado o sistema de protótipos de uma função construtora para criar a classe.
class Button {
  constructor(text, background) {
    this.text = text;
    this.background = background;
  }
  element() {
    const buttonElement = document.createElement('button');
    buttonElement.innerText = this.text;
    buttonElement.style.background = this.background;
    return buttonElement;
  }
}

const blueButton = new Button('Comprar', 'blue');
  • CLASS VS CONSTRUCTOR FUNCTION
class Button {
  constructor(propriedade) {
    this.propriedade = propriedade;
  }
  metodo1() {}
  metodo2() {}
}

function Button(propriedade) {
  this.propriedade = propriedade;
}
Button.prototype.metodo1 = function() {}
Button.prototype.metodo1 = function() {}
  • CONSTRUCTOR
    • O método constructor(args) {} é um método especial de uma classe. Nele você irá definir todas as propriedades do objeto que será criado. Os argumentos passados em new, vão direto para o constructor.
class Button {
  constructor(text, background, color) {
    this.text = text;
    this.background = background;
    this.color = color;
  }
}

const blueButton = new Button('Clique', 'blue', 'white');
// Button {text: 'Clique', background: 'blue', color: 'white'}
  • CONSTRUCTOR RETURN
    • Por padrão a classe retorna this. Ou seja, this é o objeto criado com o new Class. Podemos modificar isso alterando o return do constructor, o problema é que perderá toda a referência do objeto.
class Button {
  constructor(text) {
    this.text = text;
    return this.element(); // não fazer
  }
  element() {
    document.createElement('button').innerText = this.text;
  }
}

const btn = new Button('Clique');
// <button>Clique</button>
  • THIS
    • Assim como em uma função construtora, this faz referência ao objeto criado com new. Você pode acessar as propriedades e métodos da classe utilizando o this.
class Button {
  constructor(text) {
    this.text = text;
  }
  element() {
    const buttonElement = document.createElement('button')
    buttonElement.innerText = this.text;
    return buttonElement;
  }
  appendElementTo(target) {
    const targetElement = document.querySelector(target);
    targetElement.appendChild(this.element());
  }
}

const blueButton = new Button('Clique');
blueButton.appendElementTo('body');
  • PROPRIEDADES
    • Podemos passar qualquer valor dentro de uma propriedade.
class Button {
  constructor(options) {
    this.options = options;
  }
}

const blueOptions = {
  backgroundColor: 'blue',
  color: 'white',
  text: 'Clique',
  borderRadius: '4px',
}

const blueButton = new Button(blueOptions);
blueButton.options;
  • STATIC VS PROTOTYPE
    • Por padrão todos os métodos criados dentro da classe irão para o protótipo da mesma. Porém podemos criar métodos diretamente na classe utilizando a palavra chave static. Assim como [].map() é um método de uma array e Array.from() é um método do construtor Array.
class Button {
  constructor(text) {
    this.text = text;
  }
  static create(background) {
    const elementButton = document.createElement('button');
    elementButton.style.background = background;
    elementButton.innerText = 'Clique';
    return elementButton;
  }
}

const blueButton = Button.create('blue');
  • STATIC
    • Você pode utilizar um método static para retornar a própria classe com propriedades já pré definidas.
class Button {
  constructor(text, background) {
    this.text = text;
    this.background = background;
  }
  element() {
    const elementButton = document.createElement('button');
    elementButton.innerText = this.text;
    elementButton.style.background = this.background;
    return elementButton
  }
  static createBlue(text) {
    return new Button(text, 'blue');
  }
}

const blueButton = Button.createBlue('Comprar');
  • GET E SET
    • Podemos definir comportamentos diferentes de get e set para um método.
const button = {
  get element() {
    return this._element;
  }
  set element(tipo) {
    this._element = document.createElement(tipo);
  }
}

button.element = 'button'; // set
button.element; // get (<button></button>);
  • VALOR ESTÁTICO
    • Se definirmos apenas o get de um método, teremos então um valor estático que não será possível mudarmos.
const matematica = {
  get PI() {
    return 3.14;
  }
}

matematica.PI; // get (3.14)
matematica.PI = 20; // nada acontece
  • SET
    • Eu posso ter um método com set apenas, que modifique outras propriedades do meu objeto.
const frutas = {
  lista: [],
  set nova(fruta) {
    this.lista.push(fruta);
  }
}

frutas.nova = 'Banana';
frutas.nova = 'Morango';
frutas.lista; // ['Banana', Morango];
  • CLASS
    • Assim como em um objeto, as classes podem ter métodos de get e set também.
class Button {
  constructor(text, color) {
    this.text = text;
    this.color = color;
  }
  get element() {
    const buttonElement = document.createElement('button');
    buttonElement.innerText = this.text;
    buttonElement.style.color = this.color;
    return buttonElement;
  }
}

const blueButton = new Button('Comprar', 'blue');
blueButton.element; // retorna o elemento
  • CLASS
    • Assim como em um objeto, as classes podem ter métodos de get e set também.
class Button {
  constructor(text, color) {
    this.text = text;
    this.color = color;
  }
  get element() {
    const buttonElement = document.createElement('button');
    buttonElement.innerText = this.text;
    buttonElement.style.color = this.color;
    return buttonElement;
  }
}

const blueButton = new Button('Comprar', 'blue');
blueButton.element; // retorna o elemento
  • SET E CLASS
    • Com o set podemos modificar apenas parte do elemento de get. É comum definirmos variáveis privadas, utilizando o underscore _privada.
class Button {
  constructor(text) {
    this.text = text;
  }
  get element() {
    const elementType = this._elementType || 'button';
    const buttonElement = document.createElement(elementType);
    buttonElement.innerText = this.text;
    return buttonElement;
  }
  set element(type) {
    this._elementType = type;
  }
}

const blueButton = new Button('Comprar');
blueButton.element; // retorna o elemento
  • SUBCLASSES
    • É possível criarmos uma subclasse, esta irá ter acesso aos métodos da classe à qual ela estendeu através do seu protótipo.
class Veiculo {
  constructor(rodas) {
    this.rodas = rodas;
  }
  acelerar() {
    console.log('Acelerou');
  }
}

class Moto extends Veiculo {
  empinar() {
    console.log('Empinou com ' + this.rodas + ' rodas');
  }
}

const honda = new Moto(2);
honda.empinar();
  • MÉTODOS
    • Podemos escrever por cima de um método herdado.
class Veiculo {
  constructor(rodas) {
    this.rodas = rodas;
  }
  acelerar() {
    console.log('Acelerou');
  }
}

class Moto extends Veiculo {
  acelerar() {
    console.log('Acelerou muito');
  }
}

const honda = new Moto(2);
honda.acelerar();
  • SUPER
    • É possível utilizar a palavra chave super para falarmos com a classe que pai e acessarmos os seus métodos e propriedades.
class Veiculo {
  constructor(rodas) {
    this.rodas = rodas;
  }
  acelerar() {
    console.log('Acelerou');
  }
}

class Moto extends Veiculo {
  acelerar() {
    super.acelerar();
    console.log('Muito');
  }
}

const honda = new Moto(2);
honda.acelerar();
  • SUPER E CONSTRUCTOR
    • Podemos utilizar o super para estendermos o método constructor.
class Veiculo {
  constructor(rodas, combustivel) {
    this.rodas = rodas;
    this.combustivel = combustivel;
  }
}

class Moto extends Veiculo {
  constructor(rodas, combustivel, capacete) {
    super(rodas, combustivel);
    this.capacete = capacete;
  }
}

const honda = new Moto(4, 'Gasolina', true);
  • FUNCTION DECLARATION
    • São duas as formas mais comuns de declararmos uma função. A que utilizamos até o momento é chamado de Function Declaration.
function somar(a,b) {
  return a + b;
}

somar(4,2); // 6
```js

- FUNCTION EXPRESSION
   - É criada a partir da declaração de uma variável, na qual assinalamos uma função. Esta função pode ser anônima ou nomeada. A mesma poderá ser ativada através da variável assinalada.
```js
const somar = function(a,b) {
  return a + b;
}

somar(4,2); // 6
  • HOISTING
    • Function Declarations são completamente definidas no momento do hoisting, já function expressions apenas serão definidas no momento da execução. Por isso a ordem da declaração de uma FE possui importância.
somar(4,2); // 6
dividir(4,2); // Erro

function somar(a,b) {
  return a + b;
}
const dividir = function(a,b) {
  return a / b;
}
  • ARROW FUNCTION
    • Podemos criar utilizando arrow functions.
const somar = (a, b) => a + b;
somar(4,2); // 6

const quadrado = a => a * a;
quadrado(4); // 16
  • ESTRUTURA / PREFERÊNCIA
    • Geralmente o uso entre expression / declaration é uma questão de preferência. Function Expression força a criação da mesma antes de sua ativação, o que pode contribuir para um código mais estruturado.
// Declarada como método de window
// vaza o escopo de bloco, como se
// fosse criada utilizando var
function somar(a,b) {
  return a + b;
}
const dividir = (a,b) => a / b;

somar(4,2);
dividir(4,2);
  • IIFE - IMMEDIATELY INVOKED FUNCTION EXPRESSION
    • Antes da introdução de modules e da implementação do escopo de bloco, a forma mais comum utilizada para isolarmos o escopo de um código JavaScript era através das chamadas IIFE's.
var instrumento = 'Violão';

(function() {
  // código isolado do escopo global
  var instrumento = 'Guitarra';
  console.log(instrumento); // Guitarra
})();

console.log(instrumento); // Violão
  • IIFE - ARROW FUNCTION
    • Compiladores ainda transformam modules em IIFE's para manter a compatibilidade com browsers antigos.
const instrumento = 'Violão';

(() => {
  const instrumento = 'Guitarra';
  console.log(instrumento); // Guitarra
})();

console.log(instrumento); // Violão
  • EXERCÍCIOS
// Remova o erro
priceNumber('R$ 99,99');
const priceNumber = n => +n.replace('R$', '').replace(',', '.');

// Crie uma IIFE e isole o escopo
// de qualquer código JS.

// Como podemos utilizar
// a função abaixo.
const active = callback => callback();
  • FACTORY FUNCTION
    • São funções que retornam um objeto sem a necessidade de utilizarmos a palavra chave new. Possuem basicamente a mesma função que constructor functions / classes.
function createButton(text) {
  function element() {
    const buttonElement = document.createElement('button');
    buttonElement.innerText = text;
    return buttonElement;
  }
  return {
    element: element,
    text: text,
  }
}

const comprarBtn = createButton('Comprar');
  • MÉTODOS / VARIÁVEIS PRIVADAS
    • Uma das vantagens é a possibilidade de criarmos métodos / variáveis privadas.
function criarPessoa(nome, sobrenome) {
  const nomeCompleto = `${nome} ${sobrenome}`;

  function andar() {
    return `${nomeCompleto} andou`;
  }
  function nadar() {
    return `${nomeCompleto} nadou`;
  }
  return {
    nome,
    sobrenome,
    andar,
    nadar,
  }
}

const designer = criarPessoa('André', 'Rafael');
  • ICE FACTORY
    • Podemos impedir que os métodos e propriedades sejam modificados com Object.freeze(). Ideia inicial de Douglas Crockford.
'use strict';

function criarPessoa(nome, sobrenome) {
  const nomeCompleto = `${nome} ${sobrenome}`;
  function andar() {
    return `${nomeCompleto} andou`;
  }
  return Object.freeze({
    nome,
    sobrenome,
    andar,
  });
}

const designer = criarPessoa('André', 'Rafael');
  • CONSTRUCTOR FUNCTION / FACTORY FUNCTION
    • Uma das vantagens da Factory Function é a possibilidade de iniciarmos a mesma sem a utilização da palavra chave new. Também é possível fazer isso com uma Constructor Function.
function Pessoa(nome) {
  if (!(this instanceof Pessoa)) // ou (!new.target)
    return new Pessoa(nome);
  this.nome = nome;
}

Pessoa.prototype.andar = function() {
  return `${this.nome} andou`;
}

const designer = Pessoa('André');
  • EXEMPLO REAL
function $$(selectedElements) {
  const elements = document.querySelectorAll(selectedElements);

  function on(onEvent, callback) {
    elements.forEach(element => {
      element.addEventListener(onEvent, callback);
    });
    return this; // retornar this irá funcionar da mesma forma
  }

  function hide() {
    elements.forEach(element => {
      element.style.display = 'none';
    });
    return this;
  }

  function show() {
    elements.forEach(element => {
      element.style.display = 'initial';
    });
    return this;
  }

  function addClass(className) {
    elements.forEach(element => {
      element.classList.add(className);
    });
    return this;
  }

  function removeClass(className) {
    elements.forEach(element => {
      element.classList.add(className);
    });
    return this;
  }
  
  return Object.freeze({
    elements,
    on,
    hide,
    show,
    addClass,
    removeClass,
  });
}

const buttons = $$('button');
buttons.hide().show().addClass('ativo').removeClass('ativo');

Clojures e Debugging

  • ESCOPO
    • Quando criamos uma função, a mesma possui acesso à todas as variáveis criadas em seu escopo e também ao escopo pai. A mesma coisa acontece para funções dentro de funções.
let item1 = 1;
function funcao1() {
  let item2 = 2;
  function funcao2() {
    let item3 = 3;
  }
}

// func1, possui acesso à
// item1 e item2

// func2, possui acesso à
// item1, item2 e item3
  • CLOJURES
    • A funcao2 possui 4 escopos. O primeiro escopo é o Local, com acesso ao item3. O segundo escopo dá acesso ao item2, esse escopo é chamado de Clojure (funcao1) (escopo de função dentro de função). O terceiro escopo é o Script com acesso ao item1 e o quarto escopo é o Global/Window.
let item1 = 1;
function funcao1() {
  let item2 = 2;
  function funcao2() {
    let item3 = 3;
    console.log(item1);
    console.log(item2);
    console.log(item3);
  }
  funcao2();
}
  • DEBUGGING
    • É possível "debugarmos" um código JavaScript utilizando ferramentas do browser ou através do próprio Visual Studio Code. Se o código possuir qualquer Web API, o processo deve ser feito no Browser. Plugins podem interferir no debug dentro do browser.
debugger; // adicione a palavra debugger
let item1 = 1;
function funcao1() {
  let item2 = 2;
  function funcao2() {
    let item3 = 3;
    console.log(item1);
    console.log(item2);
    console.log(item3);
  }
  funcao2();
}
  • CASO CLÁSSICO
    • Um dos casos mais clássicos para a demonstração de Clojures é através da criação de uma função de incremento. É como se a função incrementar carregasse uma mochila chamada contagem, onde uma referência para as suas variáveis estão contidas na mesma.
function contagem() {
  let total = 0;
  return function incrementar() {
    total++;
    console.log(total);
  }
}

const ativarIncrementar = contagem();
ativarIncrementar(); // 1
ativarIncrementar(); // 2
ativarIncrementar(); // 3
  • CLOJURES NA REAL
    • Todas as funções internas da Factory Function possuem uma closure de $$. As mesmas contém uma referência à variável elements declarada dentro do escopo da função.
function $$(selectedElements) {
  const elements = document.querySelectorAll(selectedElements);

  function hide() { ... }
  function show() { ... }
  function on() { ... }
  function addClass() { ... }
  function removeClass() { ... }

  return { hide, show, on, addClass, removeClass }
}
  • DESTRUCTURING
    • Permite a desestruturação de Arrays e Objetos. Atribuindo suas propriedades à novas variáveis.
const carro = {
  marca: 'Fiat',
  ano: 2018,
  portas: 4,
}

const {marca, ano} = carro;

console.log(marca); // Fiat
console.log(ano); // 2018
  • DESTRUCTURING OBJECTS
    • A desestruturação irá facilitar a manipulação de dados. Principalmente quando temos uma grande profundidade de objetos.
const cliente = {
  nome: 'Andre',
  compras: {
    digitais: {
      livros: ['Livro 1', 'Livro 2'],
      videos: ['Video JS', 'Video HTML']
    },
    fisicas: {
      cadernos: ['Caderno 1']
    }
  }
}

console.log(cliente.compras.digitais.livros);
console.log(cliente.compras.digitais.videos);

const {livros, videos} = cliente.compras.digitais;

console.log(livros);
console.log(videos);
  • NESTING
    • É possível aninhar uma desestruturação dentro de outra.
const cliente = {
  nome: 'Andre',
  compras: {
    digitais: {
      livros: ['Livro 1', 'Livro 2'],
      videos: ['Video JS', 'Video HTML']
    },
    fisicas: {
      cadernos: ['Caderno 1']
    }
  }
}

const {fisicas, digitais, digitais: {livros, videos}} = cliente.compras;

console.log(fisicas);
console.log(livros);
console.log(videos);
console.log(digitais);
  • NOME DAS VARIÁVEIS
    • É necessário indicar o nome da propriedade que você deseja desestruturar de um objeto. É possível mudar o nome da variável final com:
const cliente = {
  nome: 'Andre',
  compras: 10,
}

const {nome, compras} = cliente;
// ou
const {nome: nomeCliente, compras: comprasCliente} = cliente;
  • VALOR INICIAL
    • Caso a propriedade não exista o valor padrão dela será undefined. É possível modificar este valor no momento da desestruturação.
const cliente = {
  nome: 'Andre',
  compras: 10,
}

const {nome, compras, email = '[email protected]', cpf} = cliente;
console.log(email) // [email protected]
console.log(cpf) // undefined
  • DESTRUCTURING ARRAYS
    • Para desestruturar array's você deve colocar as variáveis entre [] colchetes.
const frutas = ['Banana', 'Uva', 'Morango'];

const primeiraFruta = frutas[0];
const segundaFruta = frutas[1];
const terceiraFruta = frutas[2];

// Com destructuring
const [primeira, segunda, terceira] = frutas;
  • DECLARAÇÃO DE VARIÁVEIS
    • A desestruturação pode servir para declararmos uma sequência de variáveis.
const primeiro = 'Item 1';
const segundo = 'Item 2';
const terceiro = 'Item 3';
// ou
const [primeiro, segundo, terceiro] = ['Item 1', 'Item 2', 'Item 3']; 
  • ARGUMENTO DESESTRUTURADO
    • Se uma função espera receber como argumento um objeto, podemos desestruturar ele no momento da declaração.
function handleKeyboard(event) {
  console.log(event.key);
}
// Com Destructuring
function handleKeyboard({key}) {
  console.log(key);
}

document.addEventListener('keyup', handleKeyboard);
  • EXERCÍCIOS
// Extraia o backgroundColor, color e margin do btn
const btn = document.querySelector('button');
const btnStyles = getComputedStyle(btn);


// Troque os valores das variáveis abaixo
let cursoAtivo = 'JavaScript';
let cursoInativo = 'HTML';

// Corrija o erro abaixo
const cachorro = {
  nome: 'Bob',
  raca: 'Labrador',
  cor: 'Amarelo'
}

const {bobCor: cor} = cachorro;
  • Rest e Spread
  • PARÂMETROS
    • Nem todos os parâmetros que definimos são utilizados quando uma função é executada, devido a falta de argumentos. Por isso é importante nos prepararmos para caso estes argumentos não sejam declarados.
function perimetroForma(lado, totalLados) {
  return lado * totalLados;
}

perimetroForma(10, 4); // 40
perimetroForma(10); // NaN
  • PARÂMETRO PADRÃO (DEFAULT) ES5
    • Antes do ES6 a forma de definirmos um valor padrão para um parâmetro, era através de uma expressão.
function perimetroForma(lado, totalLados) {
  totalLados = totalLados || 4; // se não for definido, será igual à 4
  return lado * totalLados;
}

perimetroForma(10, 3); // 30
perimetroForma(10); // 40
  • PARÂMETRO PADRÃO (DEFAULT) ES6+
    • Com o ES6 é possível definirmos o valor de um parâmetro direto na declaração do mesmo, caso o argumento não seja passado no momento da execução.
function perimetroForma(lado, totalLados = 4) {
  return lado * totalLados;
}

perimetroForma(10, 5); // 50
perimetroForma(10); // 40
  • ARGUMENTS
    • A palavra chave arguments é um objeto Array-like criado dentro da função. Esse objeto contém os valores dos argumentos.
function perimetroForma(lado, totalLados = 4) {
  console.log(arguments)
  return lado * totalLados;
}

perimetroForma(10);
perimetroForma(10, 4, 20);
  • PARÂMETRO REST
    • É possível declararmos uma parâmetro utilizando ... na frente do mesmo. Assim todos os argumentos que passarmos na ativação da função, ficarão dentro do parâmetro.
function anunciarGanhadores(...ganhadores) {
  ganhadores.forEach(ganhador => {
    console.log(ganhador + ' ganhou.')
  });
}

anunciarGanhadores('Pedro', 'Marta', 'Maria');
  • ÚNICO REST
    • Só é possível ter um único parâmetro rest e ele deve ser o último.
function anunciarGanhadores(premio, ...ganhadores) {
  ganhadores.forEach(ganhador => {
    console.log(ganhador + ' ganhou um ' + premio)
  });
}

anunciarGanhadores('Carro', 'Pedro', 'Marta', 'Maria');
  • REST VS ARGUMENTS
    • Apesar de parecidos o parâmetro rest e a palavra arguments possuem grandes diferenças. Sendo rest uma array real e arguments um objeto Array-like.
function anunciarGanhadores(premio, ...ganhadores) {
  console.log(ganhadores);
  console.log(arguments);
}

anunciarGanhadores('Carro', 'Pedro', 'Marta', 'Maria');
  • OPERADOR SPREAD
    • Assim como o rest, o operador Spread também utiliza os ... para ser ativado. O spread irá distribuir um item iterável, um por um.
const frutas = ['Banana', 'Uva', 'Morango'];
const legumes = ['Cenoura', 'Batata'];

const comidas = [...frutas, 'Pizza', ...legumes];
  • SPREAD ARGUMENT
    • O Spread pode ser muito útil para funções que recebem uma lista de argumentos ao invés de uma array.
const numeroMaximo = Math.max(4,5,20,10,30,2,33,5); // 33

const listaNumeros = [1,13,21,12,55,2,3,43];
const numeroMaximoSpread = Math.max(...listaNumeros);
  • TRANSFORMAR EM ARRAY
    • É possível transformar itens iteráveis em uma array real com o spread.
const btns = document.querySelectorAll('button');
const btnsArray = [...btns];

const frase = 'Isso é JavaScript';
const fraseArray = [...frase];
  • EXERCÍCIOS
// Reescreva a função utilizando
// valores iniciais de parâmetros com ES6
function createButton(background, color) {
  background = background || 'blue';
  if(color === undefined) {
    color = 'red';
  }
  const buttonElement = document.createElement('button');
  buttonElement.style.background = background;
  return buttonElement;
} 

const redButton = createButton();

// Utilize o método push para inserir as frutas ao final de comidas.
const frutas = ['Banana', 'Uva', 'Morango'];
const comidas = ['Pizza', 'Batata'];
  • ITERABLE
    • São objetos que possuem o método [Symbol.iterator], geralmente no protótipo, é dentro dele que a função que lida com a iteração será definida. Ex: Array, String, NodeList, boa parte das Array-Like e outros.
const frutas = ['Banana', 'Morango', 'Uva'];
const frase = 'Isso é JavaScript';

fetch('https://pokeapi.co/api/v2/pokemon/')
.then(({headers}) => console.log(headers));
  • FOR...OF
    • É possível fazemos um loop por cada iteração do objeto iterável utilizando o for...of. Além deste loop podemos também utilizar o Spread Operator nos mesmos.
const frutas = ['Banana', 'Morango', 'Uva'];
const frase = 'Isso é JavaScript';

for(const fruta of frutas) {
  console.log(fruta);
}

for(const char of frase) {
  console.log(char);
}
  • SPREAD E FOR...OF
    • Com o for loop podemos manipular cada um dos elementos do objeto iterável.
const buttons = document.querySelectorAll('button');

for(const btn of buttons) {
  btn.style.background = 'blue';
}

console.log(...buttons);
  • APENAS ITERÁVEIS
    • O for...of não irá funcionar em um objeto comum que não seja iterável.
const carro = {
  marca: 'Honda',
  ano: 2018,
}

// Erro, não é Iterável
for(const propriedade of carro) {
  console.log(propriedade);
}
  • FOR...IN
    • Este loop irá retornar a chave (key) de todas as propriedades enumeráveis (que não sejam símbolos) de um objeto.
const carro = {
  marca: 'Honda',
  ano: 2018,
}

for(const propriedade in carro) {
  console.log(propriedade);
}
  • ARRAYS E FOR...IN
    • Uma Array é um objeto, porém a chave de cada valor é igual ao seu index.
const frutas = ['Banana', 'Morango', 'Uva'];

for(const index in frutas) {
  console.log(index);
}

for(const index in frutas) {
  console.log(frutas[index]);
}
  • CHAVE E VALOR
    • Utilizando o for...in podemos retornar todas as chaves e valores de propriedades enumeráveis.
const btn = document.querySelector('button');
const btnStyles = getComputedStyle(btn);

for(const style in btnStyles) {
  console.log(`${style}: ${btnStyles[style]}`);
}
  • DO / WHILE
    • Outro tipo de loop é o Do / While. Não é muito utilizado.
let i = 0;
do {
  console.log(i++)
} while (i <= 5);
  • REGULAR EXPRESSION
    • Regexp ou Regex são expressões utilizadas para realizarmos buscas / substituições de padrões em strings. Os padrões devem ser colocados entre //. Geralmente vamos utilizá-las nos métodos .replace() e .split().
// Procura: a
const padraoRegexp = /a/;

const texto = 'JavaScript';
const novoTexto = texto.replace(padraoRegexp, 'B');
// BavaScript
  • Praticamente todas as linguagens possuem uma implementação de regexp

  • LITERAL

    • Utilizar um caracter literal irá realizar uma busca específica deste caracter.
// Procura: J seguido de a, v e a
const regexp = /Java/;

'JavaScript'.replace(regexp, 'Type');
// TypeScript
  • FLAG: G
    • As flags irão modificar como a expressão é interpretada. Uma das mais utilizadas é a g, que significa global, ou seja, retorne todos os resultados que estiverem dentro do padrão e não apenas o primeiro. A flag deve ser colocada no final da expressão.
// Procura: Todo a
const regexp = /a/g;

'JavaScript'.replace(regexp, 'i');
// JiviScript
  • FLAG: I
    • Com o i informamos que devem ser ignoradas as diferenças entre maiúsculas e minúsculas. Isso significa que /a/ irá buscar por a e A.
// Procura: Todo PE, Pe, pE e pe
const regexp = /Pe/gi;

'Perdeu perdido'.replace(regexp, 'Ba');
// Bardeu Bardido
  • CHARACTER CLASS
    • Se colocarmos os caracteres entre colchetes, estamos definindo uma classe. /[ab]/ irá procurar por a ou por b.
// Procura: Todo a, A, i, I
const regexp = /[ai]/gi;

'JavaScript'.replace(regexp, 'u');
// JuvuScrupt
  • CHARACTER CLASS E ESPECIAIS
    • Podemos utilizar caracteres que não são alfanuméricos dentro da classe. Mas fique atento, pois existem diversos casos especiais para os mesmos.
// Procura: - ou .
const regexp = /[-.]/g;

'111.222-333-44'.replace(regexp, '');
// 11122233344
  • UM OU OUTRO
    • Combine caracteres literais com uma classe para buscarmos variações: Ju[nl]ho busca Julho ou Junho.
// Procura: B, seguido de r, a
// seguido de s ou z, seguido de i, l
const regexp = /Bra[sz]il/g;

'Brasil é com z: Brazil'.replace(regexp, 'Prazer');
// Prazer é com z: Prazer
  • DE A À Z
    • O traço - dentro de [] pode servir para definirmos um alcance. [A-Z] irá buscar os caracteres de A à Z. [0-9] busca de 0 à 9. A tabela UNICODE é utilizada como referência para definir os caracteres dentro do alcance.
// Busca por itens de a à z
const regexp = /[a-z]/g;

'JavaScript é a linguagem.'.replace(regexp, '0');
// J000S00000 é 0 000000000.

// Busca por itens de a à z e A à Z
const regexp = /[a-zA-Z]/g;

'JavaScript é a linguagem.'.replace(regexp, '1');
// 1111111111 é 1 111111111.

// Busca por números de 0 à 9
const regexpNumero = /[0-9]/g;

'123.333.333-33'.replace(regexpNumero, 'X');
// XXX.XXX.XXX-XX
// Procura: tudo que não estiver entre a e z
const regexp = /[^a-z]/g;

'Brasil é com z: Brazil'.replace(regexp, ' ');
// rasil   com z   razil 
  • PONTO
    • O ponto . irá selecionar qualquer caracter, menos quebras de linha.
// Procura: todos os caracteres menos quebra de linha
const regexp = /./g;

'JavaScript é a linguagem.'.replace(regexp, '0');
// 0000000000000000000000000
  • ESCAPAR ESPECIAIS
    • Caracteres especiais como o ponto ., podem ser escapados utilizando a barra , assim este não terá mais a sua função especial e será tratado como literal. Lista de caracteres especiais: +*?^$.[]{}()|/
// Procura: todos os pontos
const regexp = /\./g;
const regexpAlternativa = /[.]/g;

'999.222.222.11'.replace(regexp, '-');
// 999-222-222-11
  • WORD
    • O \w irá selecionar qualquer caracter alfanumérico e o underline. É a mesma coisa que [A-Za-z0-9_].
// Procura: todos os alfanuméricos
const regexp = /\w/g;

'Guarda-chuva R$ 23,00.'.replace(regexp, '-');
// ------------ -$ --,--.
  • NOT WORD
    • O \W irá selecionar tudo o que não for caracter alfanumérico e o underline. É a mesma coisa que [^A-Za-z0-9_].
// Procura: o que não for caracter alfanuméricos
const regexp = /\W/g;

'Guarda-chuva R$ 23,00.'.replace(regexp, '-');
// Guarda-chuva-R--23-00-
  • DIGIT
    • O \d irá selecionar qualquer dígito. É a mesma coisa que [0-9].
// Procura: todos os dígitos
const regexp = /\d/g;

'+55 (21) 2222-2222'.replace(regexp, 'X');
// +XX (XX) XXXX-XXXX.
  • NOT DIGIT
    • O \D irá selecionar tudo que não for dígito. É a mesma coisa que [^0-9].
// Procura: o que não for dígito
const regexp = /\D/g;

'+55 (21) 2222-2222'.replace(regexp, '');
// 552122222222
  • WHITESPACE -O \s irá selecionar qualquer espaço em branco, isso inclui espaços, tabs, quebra de linhas.
// Procura: espaços em branco
const regexp = /\s/g;

'+55 (21) 2222-  2222  '.replace(regexp, '');
// +55(21)2222-2222
  • NOT WHITESPACE
    • O \S irá selecionar qualquer caracter que não for espaço em branco.
// Procura: o que não for espaço em branco
const regexp = /\S/g;

'+55 (21) 2222-  2222  '.replace(regexp, '');
// XXX XXXX XXXXX  XXXX  

=/[\s\S]/g irá selecionar tudo.

  • QUANTIFICADOR
    • É possível selecionar caracteres seguidos, como /bbb/g irá selecionar apenas bbb. Com as chaves podemos indicar a repetição /b{3}/g. Agora ele está fazendo uma seleção completa e não caracter por caracter.
// Procura: 4 a's seguidos
const regexp = /aaaa/g;
const regexpAlt = /a{4}/g;

'Vaaaai ali por favor.'.replace(regexp, 'a');
// Vai ali por favor.  
  • QUANTIFICADOR MIN E MAX
    • Podemos informar o min e max do quantificador /a{2,4}/ vai selecionar quando aparecer a duas vezes ou até 4 vezes. /a{2,}/ irá selecionar quando se repetir duas ou mais vezes.
// Procura: dígitos seguidos de 2 à 3
const regexp = /\d{2,3}/g;

'222.333.222.42'.replace(regexp, 'X');
// X.X.X.X

// Procura: letras seguidos com 1 caracter ou mais
const regexpLetras = /\w{1,}/g;

'A melhor linguagem é JavaScript'.replace(regexpLetras, 'X');
// X X X é X
  • MAIS +
    • O sinal de + significa que devemos selecionar quando existir pelo menos uma ou mais ocorrências.
// Procura: dígitos em ocorrência de um ou mais
const regexp = /\d+/g;

'222.333.222.42'.replace(regexp, 'X');
// X.X.X.X

// Procura: Começa com d, seguido por uma ou mais letras.
const regexpLetras = /d\w+/g;

'Dígitos, dados, desenhos, Dito, d'.replace(regexpLetras, 'X');
// Dígitos, X, X, Dito, d
  • ASTERISCO *
    • O sinal * significa que devemos selecionar quando existir 0 ou mais ocorrências.
// Procura: Começa com d, seguido por zero ou mais letras.
const regexp = /d\w*/g;

'Dígitos, dados, desenhos, Dito, d'.replace(regexp, 'X');
// Dígitos, X, X, Dito, X
  • OPCIONAL ?
    • O sinal ? significa que o caracter é opcional, pode ou não existir.
// Procura: Por regex com p opcional
const regexp = /regexp?/g;

'Qual é o certo, regexp ou regex?'.replace(regex, 'Regular Expression');
// Qual é o certo, Regular Expression ou Regular Expression?
  • ALTERNADO |
    • O sinal | irá selecionar um ou outro. java|php
// Procura: java ou php (case insensitive)
const regexp = /java|php/gi;

'PHP e Java são linguagens diferentes'.replace(regexp, 'X');
// X e X são linguagens diferente
  • WORD BOUNDARY \B
    • O sinal \b irá indicar que pretendemos fazer uma seleção que deve ter início e fim de não caracteres \w.
// Procura: java (case insensitive)
const regexp = /java/gi;
'Java não é JavaScript.'.replace(regexp, 'X');
// X não é XScript.

// Procura: java (case insensitive)
const regexpBoundary = /\bjava\b/gi;
'Java não é JavaScript.'.replace(regexpBoundary, 'X');
// X não é JavaScript.

// Procura: Dígitos em sequência, que estejam isolados
const regexpDigito = /\b\d+\b/gi;
'O Restaurante25 na Rua 3, custa R$ 32,00'.replace(regexDigito, 'X');
// O Restaurante25 na Rua X, custa R$ X,X

'11_22 33-44 55é66 77e88'.replace(regexpDigito, 'X');
// 11_22 X-X XéX 77e88
  • NOT WORD BOUNDARY \B
    • É o contrário do \b.
const regexpDigito = /\B\d+\B/gi;

'11_22 33-44 55é66 77e88'.replace(regexpDigito, 'X');
// 1X_X2 33-44 55é66 7XeX8
  • ANCHOR BEGINNING
    • Com o ^ é possível informar que a busca deve ser iniciada no início da linha.
// Procura: sequência de alfanuméricos
// no início da linha.
const regexp = /^\w+/g;

`[email protected]
[email protected]`.replace(regexp, 'X');
// [email protected]
// [email protected]
  • ANCHOR END
    • Com o $ é possível informar que a busca deve ser iniciada no final da linha.
// Procura: sequência de alfanuméricos
// no final da linha.
const regexp = /\w+$/g;

`[email protected]
[email protected]`.replace(regexp, 'X');
// [email protected]
// [email protected]
  • FLAG: M
    • Com a flag m de multiline, podemos informar que a busca de início ^ e final $ de linha devem ocorrer em todas as linhas disponíveis.
// Procura: sequência de alfanuméricos
// no final da linha.
const regexp = /\w+$/gm;

`[email protected]
[email protected]`.replace(regexp, 'X');
// [email protected]
// [email protected]

// Procura: sequência de alfanuméricos
// no início da linha.
const regexp = /^\w+/gm;

`[email protected]
[email protected]`.replace(regexp, 'X');
// [email protected]
// [email protected]
  • LINE FEED \N
    • O \n irá selecionar o final de uma linha, quando criamos uma nova.
const regexp = /\n/g;

`[email protected]\[email protected]`.replace(regexp, '---');
// [email protected]@origamid.com

`[email protected]
[email protected]`.replace(regexp, 'X');
// [email protected]@origamid.com
\t seleciona tabs
  • UNICODE \U
    • O \u irá selecionar o respectivo caracter unicode, de acordo com o código passado em \uXXXX. Ex: \u0040 seleciona o @.
// Procura: @ ou ©
const regexp = /\u0040|\u00A9/g;

'[email protected] ©'.replace(regexp, '---');
// andre---origamid.com ---
  • REFERÊNCIA DA SELEÇÃO
    • É possível utilizarmos o $& durante o momento da substituição para fazermos uma referência à seleção.
// Procura: Java
const regexp = /Java/g;

'PHP e Java são linguagens diferentes'.replace(regexp, '--$&Script');
// PHP e --JavaScript são linguagens diferentes
// $& será igual à Java
  • GRUPO DE CAPTURA
    • É possível definirmos diferentes grupos de captura, que poderão ser referenciados durante a substituição. Basta envolvermos um grupo entre () parênteses. A referência se cada grupo será feita com $n, sendo o primeiro $1.
// Procura: sequência alfanumérica, seguida
// de @, seguido de alfanumérico ou .
const regexp = /(\w+)@[\w.]+/g;

'[email protected]'.replace(regexp, '[email protected]');
// [email protected]
  • Não use este regexp para emails, ele falha em alguns casos.

  • MAIS DE UM GRUPO

    • Podemos definir quantos grupos de captura quisermos.
// Procura: sequência alfanumérica, seguida
// de , seguido espaço de sequência alfanumérica.
const regexp = /(\w+),\s(\w+)/g;

'Rafael, Andre'.replace(regexp, '$2 $1');
// Andre Rafael
  • MAIS DO QUE CAPTURA APENAS
    • Um grupo também serve para agruparmos uma sequência de caracteres que queremos em repetição.
// Procura: qualquer sequência de ta
const regexp = /(ta)+/gi;

'Tatata, tata, ta'.replace(regexp, 'Pá');
// Pá, Pá, Pá
  • IGNORAR CAPTURA
    • Utilize o (?:) para ignorar a captura.
// Procura: qualquer sequência de ta
const regexp = /(?:ta)+/gi;

'Tatata, tata, ta'.replace(regexp, 'Pá');
// Pá, Pá, Pá
  • POSITIVE LOOKAHEAD
    • Faz a seleção dos itens que possuírem o padrão dentro de (?=) à sua frente. Apesar de utilizar () parênteses o positive lookahead não captura grupo.
// Procura: dígitos em sequência, que
// possuírem px, sem selecionar o px.
const regexp = /\d(?=px)/g;

'2em, 4px, 5%, 2px, 1px'.replace(regexp, 'X');
// 2em, Xpx, 5%, Xpx, Xpx
  • NEGATIVE LOOKAHEAD
    • Faz a seleção dos itens não possuírem o padrão dentro de (?!) à sua frente.
// Procura: dígitos que não possuírem px
// sem selecionar o restante.
const regexp = /\d(?!px)/g;

'2em, 4px, 5%, 5px, 1px'.replace(regexp, 'X');
// Xem, 4px, X%, 5px, 1px
  • POSITIVE LOOKBEHIND
    • Faz a seleção dos itens que possuírem o padrão dentro de (?<=) atrás dos mesmos.
// Procura: dígitos que possuírem R$
// na frente dos mesmos
const regexp = /(?<=R\$)[\d]+/g;

'R$99, 100, 200, R$20'.replace(regexp, 'X');
// R$X, 100, 200, R$X
  • CEP
const regexpCEP = /\d{5}[-\s]?\d{3}/g;

const ceps = [
  '00000-000',
  '00000 000',
  '00000000'
];

for(cep of ceps) {
  console.log(cep, cep.match(regexpCEP));
}
  • CPF
const regexpCPF = /(?:\d{3}[-.]?){3}\d{2}/g;

const cpfs = [
  '000.000.000-00',
  '000-000-000-00',
  '000.000.000.00',
  '000000000-00',
  '00000000000'
];

for(cpf of cpfs) {
  console.log(cpf, cpf.match(regexpCPF));
}
  • CNPJ
const regexpCNPJ = /\d{2}[-.]?(?:\d{3}[-.]?){2}[-\/]?\d{4}[-.]?\d{2}/g;

const cnpjs = [
  '00.000.000/0000-00',
  '00000000000000',
  '00-000-000-0000-00',
  '00.000.000/000000',
  '00.000.000.000000',
  '00.000.000.0000.00',
];

for(cnpj of cnpjs) {
  console.log(cnpj, cnpj.match(regexpCNPJ));
}
  • TELEFONE
const regexpTELEFONE = /(?:\+?55\s?)?(?:\(?\d{2}\)?[-\s]?)?\d{4,5}[-\s]?\d{4}/g;

const telefones = [
  '+55 11 98888-8888',
  '+55 11 98888 8888',
  '+55 11 988888888',
  '+55 11988888888',
  '+5511988888888',
  '5511988888888',
  '11 98888-8888',
  '11 98888 8888',
  '(11) 98888 8888',
  '(11) 98888-8888',
  '11-98888-8888',
  '11 98888 8888',
  '11988888888',
  '11988888888',
  '988888888',
  '(11)988888888',
  '98888 8888',
  '8888 8888'
];

for(telefone of telefones) {
  console.log(telefone, telefone.match(regexpTELEFONE));
}
  • EMAIL
const regexpEMAIL = /[\w.-]+@[\w-]+\.[\w-.]+/gi;

const emails = [
  '[email protected]',
  '[email protected]',
  '[email protected]',
  '[email protected]',
  '[email protected]',
  '[email protected]',
  '[email protected]',
];

for(email of emails) {
  console.log(email, email.match(regexpEMAIL));
}
const regexpTAG = /<\/?[\w\s="']+\/?>/gi;
const tags = [
  '<div>Isso é uma div</div>',
  '<div class="ativa">Essa está ativa</div>',
  '<img src="imagem" />',
  '<img src="imagem">',
  '<ul class="ativa">',
  '<li>Essa está ativa</li>',
  '</ul>'
];

for(tag of tags) {
  console.log(tag, tag.match(regexpTAG));
}
  • TAG APENAS O NOME
const regexpTAG = /(?<=<\/?)[\w]+/gi;
const tags = [
  '<div>Isso é uma div</div>',
  '<div class="ativa">Essa está ativa</div>',
  '<img src="imagem" />',
  '<img src="imagem">',
  '<ul class="ativa">',
  '<li>Essa está ativa</li>',
  '</ul>'
];

for(tag of tags) {
  console.log(tag, tag.match(regexpTAG));
}
  • Positive Lookbehind (?<=) não está disponível em todos os browsers.

  • REGEXP CONSTRUCTOR

    • Toda regexp é criada com o constructor RegExp() e herda as suas propriedades e métodos. Existem diferenças na sintaxe de uma Regexp criada diretamente em uma variável e de uma passada como argumento de RegExp.
const regexp = /\w+/gi;

// Se passarmos uma string, não precisamos dos //
// e devemos utilizar \\ para meta characters, pois é necessário
// escapar a \ especial. As Flags são o segundo argumento
const regexpObj1 = new RegExp('\\w+', 'gi');
const regexpObj2 = new RegExp(/\w+/, 'gi');

'JavaScript Linguagem 101'.replace(regexpObj1, 'X');
// X X X

// Exemplo complexo:
const regexpTELEFONE1 = /(?:\+?55\s?)?(?:\(?\d{2}\)?[-\s]?)?\d{4,5}[-\s]?\d{4}/g;
const regexpTELEFONE2 = new RegExp('(?:\\+?55\\s?)?(?:\\(?\\d{2}\\)?[-\\s]?)?\\d{4,5}[-\\s]?\\d{4}', 'g');
  • PROPRIEDADES
    • Uma regexp possui propriedades com informações sobre as flags e o conteúdo da mesma.
const regexp = /\w+/gi;

regexp.flags; // 'gi'
regexp.global; // true
regexp.ignoreCase; // true
regexp.multiline; // false
regexp.source; // '\w+'
  • REGEXP.TEST()
    • O método test() verifica se existe ou não uma ocorrência da busca. Se existir ele retorna true. A próxima vez que chamarmos o mesmo, ele irá começar do index em que parou no último true.
const regexp = /Java/g;
const frase = 'JavaScript e Java';

regexp.lastIndex; // 0
regexp.test(frase); // true
regexp.lastIndex; // 4
regexp.test(frase); // true
regexp.lastIndex; // 17
regexp.test(frase); // false
regexp.lastIndex; // 0
regexp.test(frase); // true (Reinicia
regexp.lastIndex;  // 4
  • TEST() EM LOOP
    • Podemos utilizar o while loop, para mostrar enquanto a condição for verdadeira. Assim retornamos a quantidade de match's.
const regexp = /Script/g;
const frase = 'JavaScript, TypeScript e CoffeeScript';

let i = 1;
while(regexp.test(frase)) {
  console.log(i++, regexp.lastIndex);
}
// 1 10
// 2 22
// 3 37
  • REGEXP.EXEC()
    • O exec() diferente do test(), irá retornar uma Array com mais informações do que apenas um valor booleano.
const regexp = /\w{2,}/g;
const frase = 'JavaScript, TypeScript e CoffeeScript';

regexp.exec(frase);
// ["JavaScript", index: 0, input: "JavaScript,
// TypeScript e CoffeeScript", groups: undefined] 
regexp.exec(frase);
// ["TypeScript", index: 12, input: "JavaScript,
// TypeScript e CoffeeScript", groups: undefined] 
regexp.exec(frase);
// ["CoffeeScript", index: 25, input: "JavaScript,
// TypeScript e CoffeeScript", groups: undefined] 
regexp.exec(frase);
// null
regexp.exec(frase); // Reinicia
// ["JavaScript", index: 0, input: "JavaScript,
// TypeScript e CoffeeScript", groups: undefined] 
  • LOOP COM EXEC()
    • Podemos fazer um loop com exec e parar o mesmo no momento que encontre o null.
const regexp = /\w{2,}/g;
const frase = 'JavaScript, TypeScript e CoffeeScript';
let regexpResult;

while((regexpResult = regexp.exec(frase)) !== null) {
  console.log(regexpResult[0]);
}
  • STR.MATCH()
    • O match() é um método de strings que pode receber como argumento uma Regexp. Existe uma diferença de resultado quando utilizamos a flag g ou não.
const regexp = /\w{2,}/g;
const regexpSemG = /\w{2,}/;
const frase = 'JavaScript, TypeScript e CoffeeScript';

frase.match(regexp);
// ['JavaScript', 'TypeScript', 'CoffeeScript']

frase.match(regexpSemG);
// ["JavaScript", index: 0, input: "JavaScript,
// TypeScript e CoffeeScript", groups: undefined]
  • Se não tiver match retorna null

  • STR.SPLIT()

    • O split serve para distribuirmos uma string em uma array, quebrando a string no argumento que for passado. Este método irá remover o match da array final.
const frase = 'JavaScript, TypeScript, CoffeeScript';

frase.split(', ');
// ["JavaScript", "TypeScript", "CoffeeScript"]
frase.split(/Script/g);
// ["Java", ", Type", ", Coffee", ""]

const tags = `
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
</ul>
`;

tags.split(/(?<=<\/?)\w+/g).join('div');
// <div>
//   <div>Item 1</div>
//   <div>Item 2</div>
// <div>
  • STR.REPLACE()
    • O método replace() é o mais interessante por permitir a utilização de funções de callback para cada match que ele der com a Regexp.
const tags = `
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
</ul>
`;

tags.replace(/(?<=<\/?)\w+/g, 'div');
// <div>
//   <div>Item 1</div>
//   <div>Item 2</div>
// <div>
  • CAPTURA
    • É possível fazer uma referência ao grupo de captura dentro do argumento do replace. Então podemos utilizar $&, $1 e mais.
const tags = `
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
</ul>
`;

tags.replace(/<li/g, '$& class="ativo"');
// <ul>
//   <li class="ativo">Item 1</li>
//   <li class="ativo">Item 2</li>
// </ul>
  • GRUPOS DE CAPTURA
    • É possível definirmos quantos grupos de captura quisermos.
const emails = `
[email protected]
[email protected]
[email protected]
`;

emails.replace(/(\w+@)[\w.]+/g, '$1gmail.com');
// [email protected]
// [email protected]
// [email protected]
  • CALLBACK
    • Para substituições mais complexas, podemos utilizar um callback como segundo argumento do replace. O valor do return será o que irá substituir cada match.
const regexp = /(\w+)(@[\w]+)/g;
const emails = `[email protected]
[email protected]
[email protected]`

emails.replace(regexp, function(...args) {
  console.log(args);
  if(args[2] === '@homail') {
    return `${args[1]}@hotmail`;
  } else if(args[2] === '@ggmail') {
    return `${args[1]}@gmail`;
  } else if(args[2] === '@oulook') {
    return `${args[1]}@outlook`;
  } else {
    return 'x';
  }
});

// [email protected]
// [email protected]
// [email protected]