{"id":19536960,"url":"https://github.com/alexgalhardo/learning-javascript","last_synced_at":"2025-08-02T23:07:40.157Z","repository":{"id":43869806,"uuid":"162182491","full_name":"AlexGalhardo/Learning-JavaScript","owner":"AlexGalhardo","description":"Mastering JavaScript  :turtle:","archived":false,"fork":false,"pushed_at":"2024-04-25T18:23:45.000Z","size":40895,"stargazers_count":10,"open_issues_count":4,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-02T23:03:51.242Z","etag":null,"topics":["html5","http","https","javascript","learning-js","tcp","vuejs-guide"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlexGalhardo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-17T19:54:03.000Z","updated_at":"2024-09-09T13:31:28.000Z","dependencies_parsed_at":"2024-04-25T19:47:33.652Z","dependency_job_id":null,"html_url":"https://github.com/AlexGalhardo/Learning-JavaScript","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AlexGalhardo/Learning-JavaScript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexGalhardo%2FLearning-JavaScript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexGalhardo%2FLearning-JavaScript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexGalhardo%2FLearning-JavaScript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexGalhardo%2FLearning-JavaScript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlexGalhardo","download_url":"https://codeload.github.com/AlexGalhardo/Learning-JavaScript/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexGalhardo%2FLearning-JavaScript/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268470799,"owners_count":24255391,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["html5","http","https","javascript","learning-js","tcp","vuejs-guide"],"created_at":"2024-11-11T02:25:06.098Z","updated_at":"2025-08-02T23:07:40.127Z","avatar_url":"https://github.com/AlexGalhardo.png","language":"JavaScript","readme":"### Learning Typescript: https://github.com/AlexGalhardo/Learning-TypeScript\n\n### Learning ReactJS \u0026 NextJS: https://github.com/AlexGalhardo/Learning-ReactJS \n\n### Learning Redux: https://github.com/AlexGalhardo/Curso-Redux-Origamid\n\n### Async Await JS\n- https://www.origamid.com/slide/javascript-completo-es6/#/0101-javascript-completo-es6/10\n\n\nhttps://github.com/AlexGalhardo/Learning-JavaScript/assets/19540357/b2665c40-35e9-4e0b-b0fc-2567939a431c\n\n\n\n## console.\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eComando\u003c/th\u003e\n\u003cth\u003eDescrição\u003c/th\u003e\n\u003cth\u003eExemplo\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eassert(expression, message)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia uma mensagem quando \u003ccode\u003eexpression\u003c/code\u003e é avaliado como \u003cstrong\u003efalso\u003c/strong\u003e.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.assert((x == 1), \u0026quot;assert message: x != 1\u0026quot;);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eclear()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eLimpa 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.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.clear();\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecount(title)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia o número de vezes que o comando count foi chamado para a janela do console. Cada chamada do comando count é identificada exclusivamente pelo \u003ccode\u003etitle\u003c/code\u003eopcional.\u003cbr\u003e\u003cbr\u003e A entrada existente na janela do console é identificada pelo parâmetro \u003ccode\u003etitle\u003c/code\u003e (se presente) e atualizada pelo comando count. Não é criada uma nova entrada.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.count();\u003c/code\u003e\u003cbr\u003e\u003cbr\u003e \u003ccode\u003econsole.count(\u0026quot;inner loop\u0026quot;);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edebug(message)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia \u003ccode\u003emessage\u003c/code\u003e para a janela do console.\u003cbr\u003e\u003cbr\u003e Esse comando é idêntico a console.log.\u003cbr\u003e\u003cbr\u003e Os objetos transmitidos usando o comando são convertidos em um valor de cadeia de caracteres.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.debug(\u0026quot;logging message\u0026quot;);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edir(object)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia 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.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.dir(obj);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edirxml(object)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia o nó XML \u003ccode\u003eobject\u003c/code\u003e especificado para a janela do console e o exibe como uma árvore de nós XML.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.dirxaml(xmlNode);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eerror(message)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia \u003ccode\u003emessage\u003c/code\u003e para a janela do console. O texto da mensagem está em vermelho e antecedido por um símbolo de erro.\u003cbr\u003e\u003cbr\u003e Os objetos transmitidos usando o comando são convertidos em um valor de cadeia de caracteres.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.error(\u0026quot;error message\u0026quot;);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003egroup(title)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eInicia um agrupamento das mensagens enviadas à janela do console e envia o \u003ccode\u003etitle\u003c/code\u003e 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.\u003cbr\u003e\u003cbr\u003e 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.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.group(\u0026quot;Level 2 Header\u0026quot;);\u003c/code\u003e \u003cbr\u003e \u003ccode\u003econsole.log(\u0026quot;Level 2\u0026quot;);\u003c/code\u003e \u003cbr\u003e \u003ccode\u003econsole.group();\u003c/code\u003e \u003cbr\u003e \u003ccode\u003econsole.log(\u0026quot;Level 3\u0026quot;);\u003c/code\u003e \u003cbr\u003e \u003ccode\u003econsole.warn(\u0026quot;More of level 3\u0026quot;);\u003c/code\u003e \u003cbr\u003e \u003ccode\u003econsole.groupEnd();\u003c/code\u003e \u003cbr\u003e \u003ccode\u003econsole.log(\u0026quot;Back to level 2\u0026quot;);\u003c/code\u003e \u003cbr\u003e \u003ccode\u003econsole.groupEnd();\u003c/code\u003e \u003cbr\u003e \u003ccode\u003econsole.debug(\u0026quot;Back to the outer level\u0026quot;);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003egroupCollapsed(title)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eInicia um agrupamento das mensagens enviadas à janela do console e envia o \u003ccode\u003etitle\u003c/code\u003e opcional como um rótulo de grupo. Os grupos enviados usando \u003ccode\u003egroupCollapsed\u003c/code\u003e 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.\u003c/td\u003e\n\u003ctd\u003eO uso é o mesmo do comando \u003ccode\u003egroup\u003c/code\u003e.\u003cbr\u003e\u003cbr\u003e Consulte o exemplo do comando \u003ccode\u003egroup\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003egroupEnd()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEncerra o grupo atual.\u003cbr\u003e\u003cbr\u003e Requisitos:\u003cbr\u003e\u003cbr\u003e Visual Studio 2013\u003c/td\u003e\n\u003ctd\u003eConsulte o exemplo do comando \u003ccode\u003egroup\u003c/code\u003e.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003einfo(message)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia \u003ccode\u003emessage\u003c/code\u003e para a janela do console. A mensagem é prefaciada por um símbolo de informação.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.info(\u0026quot;info message\u0026quot;);\u003c/code\u003e\u003cbr\u003e\u003cbr\u003e Para obter mais exemplos, confira \u003ca href=\"#ConsoleLog\" data-linktype=\"self-bookmark\"\u003eFormatando a saída do console.log\u003c/a\u003e mais adiante neste tópico.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003elog(message)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia \u003ccode\u003emessage\u003c/code\u003e para a janela do console.\u003cbr\u003e\u003cbr\u003e 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.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.log(\u0026quot;logging message\u0026quot;);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003emsIsIndependentlyComposed(element)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eUsado em aplicativos da Web. Sem suporte em aplicativos UWP usando JavaScript.\u003c/td\u003e\n\u003ctd\u003eNão há suporte.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eprofile(reportName)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eUsado em aplicativos da Web. Sem suporte em aplicativos UWP usando JavaScript.\u003c/td\u003e\n\u003ctd\u003eNão há suporte.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eprofileEnd()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eUsado em aplicativos da Web. Sem suporte em aplicativos UWP usando JavaScript.\u003c/td\u003e\n\u003ctd\u003eNão há suporte.\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eselect(element)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eSeleciona o HTML especificado \u003ccode\u003eelement\u003c/code\u003e no \u003ca href=\"quickstart-debug-html-and-css?view=vs-2017\" data-linktype=\"relative-path\"\u003eExplorador do DOM\u003c/a\u003e.\u003c/td\u003e\n\u003ctd\u003econsole.select(element);\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003etime (name)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eInicia um temporizador que é identificado pelo parâmetro \u003ccode\u003ename\u003c/code\u003e opcional. Quando usado com \u003ccode\u003econsole.timeEnd\u003c/code\u003e, calcula o tempo decorrido entre \u003ccode\u003etime\u003c/code\u003e e \u003ccode\u003etimeEnd\u003c/code\u003e e envia o resultado (medido em ms) ao console usando a cadeia de caracteres \u003ccode\u003ename\u003c/code\u003e como prefixo. Usado para habilitar a instrumentação de código do aplicativo para medir o desempenho.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.time(\u0026quot;app start\u0026quot;);  app.start();  console.timeEnd(\u0026quot;app start\u0026quot;);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003etimeEnd(name)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eInterrompe um temporizador que é identificado pelo parâmetro \u003ccode\u003ename\u003c/code\u003e opcional. Consulte o comando \u003ccode\u003etime\u003c/code\u003e do console.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.time(\u0026quot;app start\u0026quot;); app.start(); console.timeEnd(\u0026quot;app start\u0026quot;);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003etrace()\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia 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.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.trace();\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ewarn(message)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eEnvia \u003ccode\u003emessage\u003c/code\u003e para a janela do console, prefaciada por um símbolo de aviso.\u003cbr\u003e\u003cbr\u003e Os objetos transmitidos usando o comando são convertidos em um valor de cadeia de caracteres.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003econsole.warn(\u0026quot;warning message\u0026quot;);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"miscellaneous-commands\"\u003eComandos variados\u003c/h2\u003e\n\u003cp\u003eEsses comandos também estão disponíveis na janela do Console do JavaScript (não estão disponíveis no código).\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eComando\u003c/th\u003e\n\u003cth\u003eDescrição\u003c/th\u003e\n\u003cth\u003eExemplo\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e$0\u003c/code\u003e, \u003ccode\u003e$1\u003c/code\u003e, \u003ccode\u003e$2\u003c/code\u003e, \u003ccode\u003e$3\u003c/code\u003e, \u003ccode\u003e$4\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRetorna o elemento especificado para a janela do console. \u003ccode\u003e$0\u003c/code\u003e retorna o elemento selecionado atualmente no Explorador do DOM, \u003ccode\u003e$1\u003c/code\u003e retorna o elemento selecionado anteriormente no Explorador do DOM e assim por diante, até o quarto elemento selecionado anteriormente.\u003c/td\u003e\n\u003ctd\u003eU$3\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e$(id)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRetorna um elemento por ID. Este é um comando de atalho para \u003ccode\u003edocument.getElementById(id)\u003c/code\u003e, em que \u003ccode\u003eid\u003c/code\u003e é uma cadeia de caracteres que representa a ID do elemento.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e$(\u0026quot;contenthost\u0026quot;)\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003e$$(selector)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRetorna uma matriz de elementos que correspondem ao seletor especificado usando a sintaxe do seletor de CSS. Este é um comando de atalho para \u003ccode\u003edocument.querySelectorAll()\u003c/code\u003e.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e$$(\u0026quot;.itemlist\u0026quot;)\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ecd()\u003c/code\u003e\u003cbr\u003e\u003cbr\u003e \u003ccode\u003ecd(window)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003ePermite 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 \u003ccode\u003ecd()\u003c/code\u003e sem parâmetros reverte o contexto para a janela de nível superior.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003ecd();\u003c/code\u003e\u003cbr\u003e\u003cbr\u003e \u003ccode\u003ecd(myframe);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eselect(element)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eSeleciona o elemento especificado no \u003ca href=\"quickstart-debug-html-and-css?view=vs-2017\" data-linktype=\"relative-path\"\u003eExplorador do DOM\u003c/a\u003e.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eselect(document.getElementById(\u0026quot;element\u0026quot;));\u003c/code\u003e\u003cbr\u003e\u003cbr\u003e \u003ccode\u003eselect($(\u0026quot;element\u0026quot;));\u003c/code\u003e\u003cbr\u003e\u003cbr\u003e \u003ccode\u003eselect($1);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003edir(object)\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRetorna um visualizador para o objeto especificado. Você pode usar o visualizador para inspecionar propriedades na janela do console.\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003edir(obj);\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n## Cookies, LocalStorage, SessionStorage\n\n![storage](https://user-images.githubusercontent.com/19540357/130307198-79c18339-67d7-492e-95a6-661342dfc609.png)\n```js\nlocalSotrage.setItem('name', 'alex')\nlocalSotrage.getItem('name') // alex\nlocalStorage.removeItem('name')\nlocalStorage.clear()\n\nsessionStorage.setItem('name', 'John')\nsessionStorage.getItem('name') // John\nsessionStorage.removeItem('name')\nsessionStorage.clear()\n\ndocument.cookie = `name=Bob; expires=${new Date(2021, 0, 1).toUTCString()}`\nconsole.log(document.cookie)\n```\n\n## Stackoverflow\n```js\nfunction f () {\n  return f()\n}\n\nf()\n```\n\n## Async Event Loop\n```js\nconsole.log('script start')\n\nconst interval = setInterval(() =\u003e {\n    console.log('setInterval')\n}, 0)\n\nsetTimeout(() =\u003e {\n    console.log('setTimeout 1')\n    Promise.resolve()\n        .then(() =\u003e console.log('promise 3'))\n        .then(() =\u003e console.log('promise 4'))\n        .then(() =\u003e {\n            setTimeout(() =\u003e {\n                console.log('setTimeout 2')\n                Promise.resolve().then(() =\u003e console.log('promise 5'))\n                    .then(() =\u003e console.log('promise 6'))\n                    .then(() =\u003e clearInterval(interval))\n            }, 0)\n        })\n}, 0)\n\nPromise.resolve()\n    .then(() =\u003e console.log('promise 1'))\n    .then(() =\u003e console.log('promise 2'))\n\n// OUTPUTS\nscript start\npromise 1\npromise 2\nsetInterval\nsetTimeout 1\npromise 3\npromise 4\nsetInterval\nsetTimeout 2\npromise 5\npromise 6\n```\n\n## Arrays (under the hood) Fast Reference \n```js\nfunction forEach(array, cb) {\n  for (let i = 0; i \u003c array.length; i++) {\n    cb(array[i], i, array)\n  }\n}\n\nfunction map(array, cb) {\n  const newArray = []\n  for (let i = 0; i \u003c array.length; i++) {\n    newArray.push(cb(array[i], i, array))\n  }\n\n  return newArray\n}\n\nfunction filter(array, cb) {\n  const newArray = []\n  for (let i = 0; i \u003c array.length; i++) {\n    const element = array[i]\n    if (cb(element, i, array)) newArray.push(element)\n  }\n\n  return newArray\n}\n\nfunction reduce(array, cb, initialValue) {\n  let currentValue = initialValue\n  for (let i = 0; i \u003c array.length; i++) {\n    const element = array[i]\n    if (initialValue == null \u0026\u0026 i === 0) {\n      currentValue = element\n    } else {\n      currentValue = cb(currentValue, element, i, array)\n    }\n  }\n\n  return currentValue\n}\n\nfunction some(array, cb) {\n  for (let i = 0; i \u003c array.length; i++) {\n    if (cb(array[i], i, array)) return true\n  }\n\n  return false\n}\n\nfunction every(array, cb) {\n  for (let i = 0; i \u003c array.length; i++) {\n    if (!cb(array[i], i, array)) return false\n  }\n\n  return true\n}\n\nfunction flat(array, depth = 1) {\n  const newArray = []\n  for (let i = 0; i \u003c array.length; i++) {\n    const element = array[i]\n    if (Array.isArray(element) \u0026\u0026 depth \u003e 0) {\n      newArray.push(...flat(element, depth - 1))\n    } else {\n      newArray.push(element)\n    }\n  }\n  return newArray\n}\n\nfunction find(array, cb) {\n  for (let i = 0; i \u003c array.length; i++) {\n    const element = array[i]\n    if (cb(element, i, array)) return element\n  }\n}\n```\n\n## Typescript\n- https://www.totaltypescript.com/\n- https://www.origamid.com/curso/typescript-para-iniciantes/\n\n## JavaScript Básico\n\n- VARIÁVEIS\n   - Responsáveis por guardar dados na memória.\n   - Inicia com a palavra var, let ou const\n```js\nvar nome = 'André';\nlet idade = 28;\nconst possuiFaculdade = true;\nCOPIAR\nEVITAM REPETIÇÕES\nDRY (Don't repeat yourself)\n\nvar preco = 20;\nvar totalComprado = 5;\nvar precoTotal = preco * totalComprado;\n```\n\n- SINTAXE\n   - Palavra chave var seguida do nome, sinal de igual e o valor.\n```js\nvar nome = 'André';\nvar idade = 28;\nvar possuiFaculdade = true;\n```\n\n- VÍRGULA\n   - Utilizei a vírgula para criar mais de uma variável, sem repetir a palavra chave var.\n```js\nvar nome = 'André',\n    idade = 28,\n    possuiFaculdade = true;\n```\n\n- SEM VALOR\n   - Pode declarar ela e não atribuir valor inicialmente.\n```js\nvar precoAplicativo;\n// retorna undefined\n```\n\n- NOME\n   - Os nomes podem iniciar com $, _, ou letras.\n   - Podem conter números mas não iniciar com eles\n   - Case sensitive\n      - nome é diferente de Nome\n   - Não utilizar palavras reservadas\n   - https://www.w3schools.com/js/js_reserved.asp\n   - Camel case\n      - É comum nomearmos assim: abrirModal\n```js\nNOME\n// Inválido\nvar §nome;\nvar function;\nvar 1possuiFaculdade;\n\n// Válido\nvar $selecionar;\nvar _nome;\nvar possuiFaculdadeNoExterior;\n```\n\n- DECLARAR\n   - Erro ao tentar utilizar uma variável que não foi declarada.\n```js\nconsole.log(nome);\n// retorna nome is not defined\n```\n\n- HOISTING\n   - São movidas para cima do código, porém o valor atribuído não é movido.\n```js\nconsole.log(nome);\nvar nome = 'André';\n// Retorna undefined\n\nvar profissao = 'Designer';\nconsole.log(profissao);\n// Retornar Designer\n```\n\n- MUDAR O VALOR ATRIBUÍDO\n   - É 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\n```js\nvar idade = 28;\nidade = 29;\n\nlet preco = 50;\npreco = 25;\n\nconst possuiFaculdade = true;\npossuiFaculdade = false;\n// Retorna um erro\n```\n\n- 7 TIPOS DE DADOS\n   - Todos são primitivos exceto os objetos.\n```js\nvar nome = 'André'; // String\nvar idade = 28; // Number\nvar possuiFaculdade = true; // Boolean\nvar time; // Undefined\nvar comida = null; // Null\nvar simbolo = Symbol() // Symbol\nvar novoObjeto = {} // Object\n```\n\n- Primitivos são dados imutáveis.\n```js\nVERIFICAR TIPO DE DADO\nvar nome = 'André';\nconsole.log(typeof nome);\n// retorna string\n```\n\n- typeof null retorna object\n\n- STRING\n   - Você pode somar uma string e assim concatenar as palavras.\n```js\nvar nome = 'André';\nvar sobrenome = 'Rafael';\nvar nomeCompleto = nome + ' ' + sobrenome;\n```\n\n- STRING\n   - Você pode somar números com strings, o resultado final é sempre uma string.\n```js\nvar gols = 1000;\nvar frase = 'Romário fez ' + gols + ' gols';\nCOPIAR\nASPAS DUPLAS, SIMPLES E TEMPLATE STRING\n'JavaScript é \"super\" fácil';\n\"JavaScript é 'super' fácil\";\n\"JavaScript é \\\"super\\\" fácil\";\n`JavaScript é \"super\" fácil\"`;\n\"JavaScript é \"super\" fácil\"; // Inválido\n```\n   - Não necessariamente precisamos atribuir valores a uma variável\n\n\n- TEMPLATE STRING\n```js\nvar gols = 1000;\nvar frase1 = 'Romário fez ' + gols + ' gols';\nvar frase2 = `Romário fez ${gols} gols`; // Utilizando Template String\n```\n   - Você deve passar expressões / variáveis dentro de ${}\n\n\n## JavaScript Assíncrono\n\n- SÍNCRONO VS ASSÍNCRONO\n   - Síncrono\n      - Espera a tarefa acabar para continuar com a próxima.\n   - Assíncrono\n      - 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).\n      - Exemplos\n         - setTimeout, Ajax, Promises, Fetch, Async.\n\n- NEW PROMISE()\n   - Promise é uma função construtora de promessas. \n   - 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.\n\n```js\nconst promessa = new Promise(function(resolve, reject) {\n  let condicao = true;\n  if(condicao) {\n    resolve();\n  } else {\n    reject();\n  }\n});\n\nconsole.log(promessa); // Promise {\u003cresolved\u003e: undefined}\n```\n\n- RESOLVE()\n   - Podemos passar um argumento na função resolve(), este será enviado junto com a resolução da Promise.\n\n```js\nconst promessa = new Promise(function(resolve, reject) {\n  let condicao = true;\n  if(condicao) {\n    resolve('Estou pronto!');\n  } else {\n    reject();\n  }\n});\n\nconsole.log(promessa); // Promise {\u003cresolved\u003e: \"Estou pronto!\"}\n```\n\n- REJECT()\n   - Quando a condição de resolução da promise não é atingida, ativamos a função reject para rejeitar a mesma. \n   - Podemos indicar no console um erro, informando que a promise foi rejeitada.\n```js\nconst promessa = new Promise(function(resolve, reject) {\n  let condicao = false;\n  if(condicao) {\n    resolve('Estou pronto!');\n  } else {\n    reject(Error('Um erro ocorreu.'));\n  }\n});\n\nconsole.log(promessa); // Promise {\u003crejected\u003e: Error:...}\n```\n\n- THEN()\n   - O poder das Promises está no método then() do seu protótipo.\n   - O Callback deste método só será ativado quando a promise for resolvida. \n   - O argumento do callback será o valor passado na função resolve.\n```js\nconst promessa = new Promise(function(resolve, reject) {\n  let condicao = true;\n  if(condicao) {\n    resolve('Estou pronto!');\n  } else {\n    reject(Error('Um erro ocorreu.'));\n  }\n});\n\npromessa.then(function(resolucao) {\n  console.log(resolucao); // 'Estou pronto!'\n});\n```\n\n- ASSÍNCRONO\n   - As promises não fazem sentido quando o código executado dentro da mesma é apenas código síncrono. \n   - O poder está na execução de código assíncrono que executará o resolve() ao final dele.\n```js\nconst promessa = new Promise((resolve, reject) =\u003e {\n  setTimeout(() =\u003e {\n    resolve('Resolvida');\n  }, 1000);\n});\n\npromessa.then(resolucao =\u003e {\n  console.log(resolucao); // 'Resolvida' após 1s\n});\n```\n\n- THEN().THEN()\n   - O método then() retorna outra Promise. Podemos colocar then() após then() e fazer um encadeamento de promessas. \n   - O valor do primeiro argumento de cada then, será o valor do retorno anterior.\n```js\nconst promessa = new Promise((resolve, reject) =\u003e {\n  resolve('Etapa 1');\n});\n\npromessa.then(resolucao =\u003e {\n  console.log(resolucao); // 'Etapa 1';\n  return 'Etapa 2';\n}).then(resolucao =\u003e {\n  console.log(resolucao) // 'Etapa 2';\n  return 'Etapa 3';\n}).then(r =\u003e r + 4)\n.then(r =\u003e {\n  console.log(r); // Etapa 34\n});\n```\n\n- CATCH()\n   - O método catch(), do protótipo de Promises, adiciona um callback a promise que será ativado caso a mesma seja rejeitada.\n```js\nconst promessa = new Promise((resolve, reject) =\u003e {\n  let condicao = false;\n  if(condicao) {\n    resolve('Estou pronto!');\n  } else {\n    reject(Error('Um erro ocorreu.'));\n  }\n});\n\npromessa.then(resolucao =\u003e {\n  console.log(resolucao);\n}).catch(reject =\u003e {\n  console.log(reject);\n});\n```\n\n- THEN(RESOLVE, REJECT)\n   - Podemos passar a função que será ativada caso a promise seja rejeitada, direto no método then, como segundo argumento.\n```js\nconst promessa = new Promise((resolve, reject) =\u003e {\n  let condicao = false;\n  if(condicao) {\n    resolve('Estou pronto!');\n  } else {\n    reject(Error('Um erro ocorreu.'));\n  }\n});\n\npromessa.then(resolucao =\u003e {\n  console.log(resolucao);\n}, reject =\u003e {\n  console.log(reject);\n});\n```\n\n- FINALLY()\n   - finally() executará a função anônima assim que a promessa acabar.\n   - A diferença do finally é que ele será executado independente do resultado, se for resolvida ou rejeitada.\n```js\nconst promessa = new Promise((resolve, reject) =\u003e {\n  let condicao = false;\n  if(condicao) {\n    resolve('Estou pronto!');\n  } else {\n    reject(Error('Um erro ocorreu.'));\n  }\n});\n\npromessa.then(resolucao =\u003e {\n  console.log(resolucao);\n}, reject =\u003e {\n  console.log(reject);\n}).finally(() =\u003e {\n  console.log('Acabou'); // 'Acabou'\n});\n```\n\n- PROMISE.ALL()\n   - Retornará uma nova promise assim que todas as promises dentro dela forem resolvidas ou pelo menos uma rejeitada. \n   - A reposta é uma array com as respostas de cada promise.\n```js\nconst login = new Promise(resolve =\u003e {\n  setTimeout(() =\u003e {\n    resolve('Login Efetuado');\n  }, 1000);\n});\nconst dados = new Promise(resolve =\u003e {\n  setTimeout(() =\u003e {\n    resolve('Dados Carregados');\n  }, 1500);\n});\n\nconst tudoCarregado = Promise.all([login, dados]);\n\ntudoCarregado.then(respostas =\u003e {\n  console.log(respostas); // Array com ambas respostas\n});\n```\n\n- PROMISE.RACE()\n   - Retornará uma nova promise assim que a primeira promise for resolvida ou rejeitada. Essa nova promise terá a resposta da primeira resolvida.\n```js\nconst login = new Promise(resolve =\u003e {\n  setTimeout(() =\u003e {\n    resolve('Login Efetuado');\n  }, 1000);\n});\nconst dados = new Promise(resolve =\u003e {\n  setTimeout(() =\u003e {\n    resolve('Dados Carregados');\n  }, 1500);\n});\n\nconst carregouPrimeiro = Promise.race([login, dados]);\n\ncarregouPrimeiro.then(resposta =\u003e {\n  console.log(resposta); // Login Efetuado\n});\n```\n\n- FETCH API\n   - 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.\n```js\nfetch('./arquivo.txt').then(function(response) {\n  console.log(response); // Response HTTP (Objeto)\n});\n```\n\n- RESPONSE\n   - 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.\n```js\nfetch('./arquivo.txt').then(function(response) {\n  return response.text();\n}).then(function(corpo) {\n  console.log(corpo);\n});\n```\n\n- SERVIDOR LOCAL\n   - 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.\n```js\nfetch('c:/files/arquivo.txt')\n.then((response) =\u003e {\n  return response.text();\n})\n.then((corpo) =\u003e {\n  console.log(corpo);\n}); // erro\n```\n\n   - Se dermos um espaço após o objeto ou pularmos linha, o método continua funcionando.\n\n- .JSON()\n   - 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.\n```js\nfetch('https://viacep.com.br/ws/01001000/json/')\n.then(response =\u003e response.json())\n.then(cep =\u003e {\n  console.log(cep.bairro, cep.logradouro);\n});\n```\n\n- .TEXT()\n   - Podemos utilizar o .text() para diferentes formatos como txt, json, html, css, js e mais.\n\n```js\nconst styleElement = document.createElement('style');\n\nfetch('./style.css')\n.then(response =\u003e response.text())\n.then(style =\u003e {\n  styleElement.innerHTML = style;\n  document.body.appendChild(styleElement);\n});\n```\n\n- HTML E .TEXT()\n   - 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.\n```js\nconst div = document.createElement('div');\n\nfetch('./sobre.html')\n.then(response =\u003e response.text())\n.then(htmlBody =\u003e {\n  div.innerHTML = htmlBody;\n  const titulo = div.querySelector('h1');\n  document.querySelector('h1').innerText = titulo.innerText;\n});\n```\n\n- .BLOB()\n   - 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.\n```js\nconst div = document.createElement('div');\n\nfetch('./imagem.png')\n.then(response =\u003e response.blob())\n.then(imgBlob =\u003e {\n  const blobUrl = URL.createObjectURL(imgBlob);\n  console.log(blobUrl);\n});\n```\n\n- .CLONE()\n   - 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.\n```js\nconst div = document.createElement('div');\n\nfetch('https://viacep.com.br/ws/01001000/json/')\n.then(response =\u003e {\n  const cloneResponse = response.clone();\n  response.json().then(json =\u003e {\n    console.log(json)\n  });\n  cloneResponse.text().then(text =\u003e {\n    console.log(text)\n  });\n});\n```\n\n- .HEADERS\n   - É 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.\n```js\nconst div = document.createElement('div');\n\nfetch('https://viacep.com.br/ws/01001000/json/')\n.then(response =\u003e {\n  response.headers.forEach(console.log);\n});\n```\n\n- .STATUS E .OK\n   - 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.\n```js\nconst div = document.createElement('div');\n\nfetch('https://viacep.com.br/ws/01001000/json/')\n.then(response =\u003e {\n  console.log(response.status, response.ok);\n  if(response.status === 404) {\n    console.log('Página não encontrada')\n  }\n});\n```\n\n- .URL E .TYPE\n   - .url retorna o url da requisição. .type retorna o tipo da reposta.\n```js\nconst div = document.createElement('div');\n\nfetch('https://viacep.com.br/ws/01001000/json/')\n.then(response =\u003e {\n  console.log(response.type, response.url);\n});\n\n//types\n// basic: feito na mesma origem\n// cors: feito em url body pode estar disponível\n// error: erro de conexão\n// opaque: no-cors, não permite acesso de outros sites\n```\n\n- JSON\n   - 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.\n```json\n{\n  \"id\": 1,\n  \"nome\": \"Andre\",\n  \"email\": \"andre@origamid.com\"\n}\n```\n\n- VALORES\n   - Os valores podem ser números, strings, boolean, arrays, objetos e null.\n```json\n{\n  \"id\": 1,\n  \"faculdade\": true,\n  \"pertences\": [\n    \"lapis\",\n    \"caneta\",\n    \"caderno\"\n  ],\n  \"endereco\": {\n    \"cidade\": \"Rio de Janeiro\",\n    \"pais\": \"Brasil\"\n  },\n  \"casado\": null\n}\n```\n\n- ARRAYS E OBJETOS\n   - É 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.\n```json\n[\n  {\n    \"id\": 1,\n    \"aula\": \"JavaScript\",\n    \"tempo\": \"25min\"\n  },\n  {\n    \"id\": 2,\n    \"aula\": \"HTML\",\n    \"tempo\": \"15min\"\n  },\n  {\n    \"id\": 3,\n    \"aula\": \"CSS\",\n    \"tempo\": \"10min\"\n  }\n]\n```\n\n- JSON.PARSE() E JSON.STRINGIFY()\n   - JSON.parse() irá transformar um texto JSON em um objeto JavaScript. JSON.stringify() irá transformar um objeto JavaScript em uma string no formato JSON.\n\n```js\nconst textoJSON = '{\"id\": 1, \"titulo\": \"JavaScript\", \"tempo\": \"25min\"}';\nconst textoOBJ = JSON.parse(textoJSON);\n\nconst enderecoOBJ = {\n  cidade: \"Rio de Janeiro\",\n  rua: \"Ali Perto\",\n  pais: \"Brasil\",\n  numero: 50,\n}\nconst enderecoJSON = JSON.stringfy(enderecoOBJ);\n```\n\n- EXEMPLO REAL\n   - Podemos guardar por exemplo no localStorage, uma string como valor de uma propriedade. \n   - E retornar essa string como um objeto.\n```js\nconst configuracoes = {\n  player: \"Google API\",\n  tempo: 25.5,\n  aula: \"2-1 JavaScript\",\n  vitalicio: true,\n}\n\nlocalStorage.configuracoes = JSON.stringify(configuracoes);\nconst pegarConfiguracoes = JSON.parse(localStorage.configuracoes);\n```\n\n## APIs\n\n- 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.\n- Programação, isso significa que um comando irá encadear uma cadeia de eventos pré-definidos. O resultado esperado é geralmente o mesmo.\n- 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.\n\n- EXEMPLOS DE API'S\n   - https://api.github.com/users/origamid\n   - https://api.github.com/users/origamid/followers\n   - Array / Element\n   - [].map();\n   - [].filter();\n   - Element.classList;\n   - Element.attributes;\n   - Tempo\n      - https://www.metaweather.com/api/location/455825/\n      - https://github.com/toddmotto/public-apis\n\n- HTTP\n   - Hypertext Transfer Protocol é o protocolo utilizando para enviarmos/recebermos arquivos e dados na Web.\n```js\nfetch('https://pokeapi.co/api/v2/pokemon/')\n.then(r =\u003e r.json())\n.then(pokemon =\u003e {\n  console.log(pokemon);\n});\n```\n\n- URL E METHOD\n   - 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.\n```js\nconst url = 'https://jsonplaceholder.typicode.com/posts/';\nconst options = {\n  method: 'POST',\n  headers: {\n    \"Content-Type\": \"application/json; charset=utf-8\",\n  },\n  body: '\"aula\": \"JavaScript\"';\n}\n\nfetch(url, options);\n.then(response =\u003e response.json())\n.then(json =\u003e {\n  console.log(json);\n});\n```\n\n- METHOD\n   - GET\n      - Puxa informação, utilizado para pegar posts, usuários e etc.\n   - POST\n      - Utilizado para criar posts, usuários e etc.\n   - PUT\n      - Geralmente utilizado para atualizar informações.\n   - DELETE\n      - Deleta uma informação.\n   - HEAD\n      - Puxa apenas os headers.\n\n- GET\n   - GET irá puxar as informações da URL. Não é necessário informar que o método é GET, pois este é o padrão.\n```js\nconst url = 'https://jsonplaceholder.typicode.com/posts/';\nfetch(url, {\n  method: 'GET'\n})\n.then(r =\u003e r.json())\n.then(r =\u003e console.log(r))\n```\n\n- POST\n   - POST irá criar uma nova postagem, utilizando o tipo de conteúdo especificado no headers e utilizando o conteúdo do body.\n```js\nconst url = 'https://jsonplaceholder.typicode.com/posts/';\n\nfetch(url, {\n  method: 'POST',\n  headers: {\n    \"Content-Type\": \"application/json; charset=utf-8\",\n  },\n  body: '{\"titulo\": \"JavaScript\"}'\n})\n.then(r =\u003e r.json())\n.then(r =\u003e console.log(r))\n```\n\n- PUT\n   - PUT irá atualizar o conteúdo do URL com o que for informado no conteúdo do body.\n```js\nconst url = 'https://jsonplaceholder.typicode.com/posts/1/';\n\nfetch(url, {\n  method: 'PUT',\n  headers: {\n    \"Content-Type\": \"application/json; charset=utf-8\",\n  },\n  body: '{\"titulo\": \"JavaScript\"}'\n})\n.then(r =\u003e r.json())\n.then(r =\u003e console.log(r))\n```\n\n- HEAD\n    - HEAD puxa apenas os headers. É uma requisição mais leve pois não puxa o body.\n```js\nconst url = 'https://jsonplaceholder.typicode.com/posts/1/';\n\nfetch(url, {\n  method: 'HEAD',\n})\n.then(response =\u003e {\n  response.headers.forEach(console.log);\n  console.log(response.headers.get('Content-Type'));\n});\n```\n\n- HEADERS\n   - Cache-Control\n       - Tempo que o arquivo deve ficar em cache em segundos. Ex: public, max-age=3600\n   - Content-Type\n       - Tipo de conteúdo. Ex: text/html; charset=utf-8. Indicar o tipo de arquivo principalmente em métodos POST e PUT.\n   - Lista de Headers\n       - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers\n\n- CORS\n   - Cross-Origin Resource Sharing, gerencia como deve ser o compartilhamento de recursos entre diferente origens.\n   - É definido no servidor se é permitido ou não o acesso dos recursos através de scripts por outros sites.\n   - Utilizando o Access-Control-Allow-Origin.\n   - Se o servidor não permitir o acesso, este será bloqueado.\n   - É possível passar por cima do bloqueio utilizando um proxy.\n   - CORS é um acordo entre browser / servidor ou servidor / servidor. \n   - Ele serve para dar certa proteção ao browser, mas não é inviolável.\n```js\nconst url = 'https://cors-anywhere.herokuapp.com/https://www.google.com/';\nconst div = document.createElement('div');\n\nfetch(url)\n.then(r =\u003e r.text())\n.then(r =\u003e {\n  div.innerHTML = r;\n  console.log(div);\n});\n```\n\n- ASYNC / AWAIT\n   - 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.\n```js\nasync function puxarDados() {\n  const dadosResponse = await fetch('./dados.json');\n  const dadosJSON = await dadosResponse.json();\n  \n  document.body.innerText = dadosJSON.titulo;\n}\n\npuxarDados();\n```\n\n- THEN / ASYNC\n   - A diferença é uma sintaxe mais limpa.\n```js\nfunction iniciarFetch() {\n  fetch('./dados.json')\n  .then(dadosResponse =\u003e dadosResponse.json())\n  .then(dadosJSON =\u003e {\n    document.body.innerText = dadosJSON.titulo;\n  })\n}\niniciarFetch();\n\nasync function iniciarAsync() {\n  const dadosResponse = await fetch('./dados.json');\n  const dadosJSON = await dadosResponse.json();\n  document.body.innerText = dadosJSON.titulo;\n}\niniciarAsync();\n```\n\n- TRY / CATCH\n   - Para lidarmos com erros nas promises, podemos utilizar o try e o catch na função.\n```js\nasync function puxarDados() {\n  try {\n    const dadosResponse = await fetch('./dados.json');\n    const dadosJSON = await dadosResponse.json();\n    document.body.innerText = dadosJSON.titulo;\n  }\n  catch(erro) {\n    console.log(erro);\n  }\n}\npuxarDados();\n```\n\n- INICIAR FETCH AO MESMO TEMPO\n   - 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.\n```\nasync function iniciarAsync() {\n  const dadosResponse = fetch('./dados.json');\n  const clientesResponse = fetch('./clientes.json');\n\n  // ele espera o que está dentro da expressão () ocorrer primeiro\n  const dadosJSON = await (await dadosResponse).json();\n  const clientesJSON = await (await clientesResponse).json();\n}\niniciarAsync();\n```\n\n- PROMISE\n   - O resultado da expressão à frente de await tem que ser uma promise.  \n   -E o retorno do await será sempre o resultado desta promise.\n```js\nasync function asyncSemPromise() {\n  // Console não irá esperar.\n  await setTimeout(() =\u003e console.log('Depois de 1s'), 1000);\n  console.log('acabou');\n}\nasyncSemPromise();\n\nasync function iniciarAsync() {\n  await new Promise(resolve =\u003e {\n    setTimeout(() =\u003e resolve(), 1000)\n  });\n  console.log('Depois de 1s');\n}\niniciarAsync();\n```\n\n- HISTORY\n   - É 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.\n\n```js\nwindow.history;\nwindow.history.back(); // vai para a anterior\nwindow.history.forward(); // vai para a próxima\n```\n\n- PUSHSTATE()\n   - A parte interessante de manipularmos o history é que podemos modificar o histórico e adicionar um novo item. \n``js\nwindow.history.pushState(obj, title, url).\n\n// Em obj podemos enviar um objeto com dados\n// mas o seu uso é restrito por isso geralmente utilizamos\n// null. O title ainda é ignorado por alguns browsers, também\n// utilizamos null nele. O url que é parte importante.\n\nwindow.history.pushState(null, null, 'sobre.html');\n``\n\n- POPSTATE\n   - 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.\n``js\nwindow.addEventListener('popstate', () =\u003e {\n  fetchPage(window.location.pathname);\n});\n``\n\n- FETCH E HISTORY\n   - 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.\n``js\nasync function fetchPage(url) {\n  const pageReponse = await fetch(url);\n  const pageText = await pageReponse.text();\n  window.history.pushState(null, null, url);\n}\n``\n\n## Classes e Objetos\n\n- CONSTRUCTOR FUNCTION\n   - Funções responsáveis pela criação de objetos. O conceito de uma função construtora de objetos é implementado em outras linguagens como Classes.\n```js\nfunction Button(text, background) {\n  this.text = text;\n  this.background = background;\n}\n\nButton.prototype.element = function() {\n  const buttonElement = document.createElement('button');\n  buttonElement.innerText = this.text;\n  buttonElement.style.background = this.background;\n  return buttonElement;\n}\n\nconst blueButton = new Button('Comprar', 'blue');\n```\n\n- CLASS\n   - 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.\n```js\nclass Button {\n  constructor(text, background) {\n    this.text = text;\n    this.background = background;\n  }\n  element() {\n    const buttonElement = document.createElement('button');\n    buttonElement.innerText = this.text;\n    buttonElement.style.background = this.background;\n    return buttonElement;\n  }\n}\n\nconst blueButton = new Button('Comprar', 'blue');\n```\n\n- CLASS VS CONSTRUCTOR FUNCTION\n```js\nclass Button {\n  constructor(propriedade) {\n    this.propriedade = propriedade;\n  }\n  metodo1() {}\n  metodo2() {}\n}\n\nfunction Button(propriedade) {\n  this.propriedade = propriedade;\n}\nButton.prototype.metodo1 = function() {}\nButton.prototype.metodo1 = function() {}\n```\n\n- CONSTRUCTOR\n   - 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.\n```js\nclass Button {\n  constructor(text, background, color) {\n    this.text = text;\n    this.background = background;\n    this.color = color;\n  }\n}\n\nconst blueButton = new Button('Clique', 'blue', 'white');\n// Button {text: 'Clique', background: 'blue', color: 'white'}\n```\n\n- CONSTRUCTOR RETURN\n   - 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.\n```js\nclass Button {\n  constructor(text) {\n    this.text = text;\n    return this.element(); // não fazer\n  }\n  element() {\n    document.createElement('button').innerText = this.text;\n  }\n}\n\nconst btn = new Button('Clique');\n// \u003cbutton\u003eClique\u003c/button\u003e\n```\n\n- THIS\n   - 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.\n```js\nclass Button {\n  constructor(text) {\n    this.text = text;\n  }\n  element() {\n    const buttonElement = document.createElement('button')\n    buttonElement.innerText = this.text;\n    return buttonElement;\n  }\n  appendElementTo(target) {\n    const targetElement = document.querySelector(target);\n    targetElement.appendChild(this.element());\n  }\n}\n\nconst blueButton = new Button('Clique');\nblueButton.appendElementTo('body');\n```\n\n- PROPRIEDADES\n   - Podemos passar qualquer valor dentro de uma propriedade.\n```js\nclass Button {\n  constructor(options) {\n    this.options = options;\n  }\n}\n\nconst blueOptions = {\n  backgroundColor: 'blue',\n  color: 'white',\n  text: 'Clique',\n  borderRadius: '4px',\n}\n\nconst blueButton = new Button(blueOptions);\nblueButton.options;\n```\n\n- STATIC VS PROTOTYPE\n   - 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.\n```js\nclass Button {\n  constructor(text) {\n    this.text = text;\n  }\n  static create(background) {\n    const elementButton = document.createElement('button');\n    elementButton.style.background = background;\n    elementButton.innerText = 'Clique';\n    return elementButton;\n  }\n}\n\nconst blueButton = Button.create('blue');\n```\n\n- STATIC\n   - Você pode utilizar um método static para retornar a própria classe com propriedades já pré definidas.\n```js\nclass Button {\n  constructor(text, background) {\n    this.text = text;\n    this.background = background;\n  }\n  element() {\n    const elementButton = document.createElement('button');\n    elementButton.innerText = this.text;\n    elementButton.style.background = this.background;\n    return elementButton\n  }\n  static createBlue(text) {\n    return new Button(text, 'blue');\n  }\n}\n\nconst blueButton = Button.createBlue('Comprar');\n```\n\n- GET E SET\n   - Podemos definir comportamentos diferentes de get e set para um método.\n```js\nconst button = {\n  get element() {\n    return this._element;\n  }\n  set element(tipo) {\n    this._element = document.createElement(tipo);\n  }\n}\n\nbutton.element = 'button'; // set\nbutton.element; // get (\u003cbutton\u003e\u003c/button\u003e);\n```\n\n- VALOR ESTÁTICO\n   - Se definirmos apenas o get de um método, teremos então um valor estático que não será possível mudarmos.\n```js\nconst matematica = {\n  get PI() {\n    return 3.14;\n  }\n}\n\nmatematica.PI; // get (3.14)\nmatematica.PI = 20; // nada acontece\n```\n\n- SET\n   - Eu posso ter um método com set apenas, que modifique outras propriedades do meu objeto.\n```js\nconst frutas = {\n  lista: [],\n  set nova(fruta) {\n    this.lista.push(fruta);\n  }\n}\n\nfrutas.nova = 'Banana';\nfrutas.nova = 'Morango';\nfrutas.lista; // ['Banana', Morango];\n```\n\n- CLASS\n   - Assim como em um objeto, as classes podem ter métodos de get e set também.\n```js\nclass Button {\n  constructor(text, color) {\n    this.text = text;\n    this.color = color;\n  }\n  get element() {\n    const buttonElement = document.createElement('button');\n    buttonElement.innerText = this.text;\n    buttonElement.style.color = this.color;\n    return buttonElement;\n  }\n}\n\nconst blueButton = new Button('Comprar', 'blue');\nblueButton.element; // retorna o elemento\n```\n\n- CLASS\n   - Assim como em um objeto, as classes podem ter métodos de get e set também.\n```js\nclass Button {\n  constructor(text, color) {\n    this.text = text;\n    this.color = color;\n  }\n  get element() {\n    const buttonElement = document.createElement('button');\n    buttonElement.innerText = this.text;\n    buttonElement.style.color = this.color;\n    return buttonElement;\n  }\n}\n\nconst blueButton = new Button('Comprar', 'blue');\nblueButton.element; // retorna o elemento\n```\n\n- SET E CLASS\n   - Com o set podemos modificar apenas parte do elemento de get. É comum definirmos variáveis privadas, utilizando o underscore _privada.\n```js\nclass Button {\n  constructor(text) {\n    this.text = text;\n  }\n  get element() {\n    const elementType = this._elementType || 'button';\n    const buttonElement = document.createElement(elementType);\n    buttonElement.innerText = this.text;\n    return buttonElement;\n  }\n  set element(type) {\n    this._elementType = type;\n  }\n}\n\nconst blueButton = new Button('Comprar');\nblueButton.element; // retorna o elemento\n```\n\n- SUBCLASSES\n   - É possível criarmos uma subclasse, esta irá ter acesso aos métodos da classe à qual ela estendeu através do seu protótipo.\n```js\nclass Veiculo {\n  constructor(rodas) {\n    this.rodas = rodas;\n  }\n  acelerar() {\n    console.log('Acelerou');\n  }\n}\n\nclass Moto extends Veiculo {\n  empinar() {\n    console.log('Empinou com ' + this.rodas + ' rodas');\n  }\n}\n\nconst honda = new Moto(2);\nhonda.empinar();\n```\n\n- MÉTODOS\n   - Podemos escrever por cima de um método herdado.\n```js\nclass Veiculo {\n  constructor(rodas) {\n    this.rodas = rodas;\n  }\n  acelerar() {\n    console.log('Acelerou');\n  }\n}\n\nclass Moto extends Veiculo {\n  acelerar() {\n    console.log('Acelerou muito');\n  }\n}\n\nconst honda = new Moto(2);\nhonda.acelerar();\n```\n\n- SUPER\n   - É possível utilizar a palavra chave super para falarmos com a classe que pai e acessarmos os seus métodos e propriedades.\n```js\nclass Veiculo {\n  constructor(rodas) {\n    this.rodas = rodas;\n  }\n  acelerar() {\n    console.log('Acelerou');\n  }\n}\n\nclass Moto extends Veiculo {\n  acelerar() {\n    super.acelerar();\n    console.log('Muito');\n  }\n}\n\nconst honda = new Moto(2);\nhonda.acelerar();\n```\n\n- SUPER E CONSTRUCTOR\n   - Podemos utilizar o super para estendermos o método constructor.\n```js\nclass Veiculo {\n  constructor(rodas, combustivel) {\n    this.rodas = rodas;\n    this.combustivel = combustivel;\n  }\n}\n\nclass Moto extends Veiculo {\n  constructor(rodas, combustivel, capacete) {\n    super(rodas, combustivel);\n    this.capacete = capacete;\n  }\n}\n\nconst honda = new Moto(4, 'Gasolina', true);\n```\n\n- FUNCTION DECLARATION\n   - São duas as formas mais comuns de declararmos uma função. A que utilizamos até o momento é chamado de Function Declaration.\n```js\nfunction somar(a,b) {\n  return a + b;\n}\n\nsomar(4,2); // 6\n```js\n\n- FUNCTION EXPRESSION\n   - É 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.\n```js\nconst somar = function(a,b) {\n  return a + b;\n}\n\nsomar(4,2); // 6\n```\n\n- HOISTING\n   - 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.\n```js\nsomar(4,2); // 6\ndividir(4,2); // Erro\n\nfunction somar(a,b) {\n  return a + b;\n}\nconst dividir = function(a,b) {\n  return a / b;\n}\n```\n\n- ARROW FUNCTION\n   - Podemos criar utilizando arrow functions.\n```js\nconst somar = (a, b) =\u003e a + b;\nsomar(4,2); // 6\n\nconst quadrado = a =\u003e a * a;\nquadrado(4); // 16\n```\n\n- ESTRUTURA / PREFERÊNCIA\n   - 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.\n```js\n// Declarada como método de window\n// vaza o escopo de bloco, como se\n// fosse criada utilizando var\nfunction somar(a,b) {\n  return a + b;\n}\nconst dividir = (a,b) =\u003e a / b;\n\nsomar(4,2);\ndividir(4,2);\n```\n\n- IIFE - IMMEDIATELY INVOKED FUNCTION EXPRESSION\n   - 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.\n```js\nvar instrumento = 'Violão';\n\n(function() {\n  // código isolado do escopo global\n  var instrumento = 'Guitarra';\n  console.log(instrumento); // Guitarra\n})();\n\nconsole.log(instrumento); // Violão\n```\n\n- IIFE - ARROW FUNCTION\n   - Compiladores ainda transformam modules em IIFE's para manter a compatibilidade com browsers antigos.\n```js\nconst instrumento = 'Violão';\n\n(() =\u003e {\n  const instrumento = 'Guitarra';\n  console.log(instrumento); // Guitarra\n})();\n\nconsole.log(instrumento); // Violão\n```\n\n- EXERCÍCIOS\n```js\n// Remova o erro\npriceNumber('R$ 99,99');\nconst priceNumber = n =\u003e +n.replace('R$', '').replace(',', '.');\n\n// Crie uma IIFE e isole o escopo\n// de qualquer código JS.\n\n// Como podemos utilizar\n// a função abaixo.\nconst active = callback =\u003e callback();\n```\n\n- FACTORY FUNCTION\n   - 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.\n```js\nfunction createButton(text) {\n  function element() {\n    const buttonElement = document.createElement('button');\n    buttonElement.innerText = text;\n    return buttonElement;\n  }\n  return {\n    element: element,\n    text: text,\n  }\n}\n\nconst comprarBtn = createButton('Comprar');\n```\n\n- MÉTODOS / VARIÁVEIS PRIVADAS\n   - Uma das vantagens é a possibilidade de criarmos métodos / variáveis privadas.\n```js\nfunction criarPessoa(nome, sobrenome) {\n  const nomeCompleto = `${nome} ${sobrenome}`;\n\n  function andar() {\n    return `${nomeCompleto} andou`;\n  }\n  function nadar() {\n    return `${nomeCompleto} nadou`;\n  }\n  return {\n    nome,\n    sobrenome,\n    andar,\n    nadar,\n  }\n}\n\nconst designer = criarPessoa('André', 'Rafael');\n```\n\n- ICE FACTORY\n   - Podemos impedir que os métodos e propriedades sejam modificados com Object.freeze(). Ideia inicial de Douglas Crockford.\n```js\n'use strict';\n\nfunction criarPessoa(nome, sobrenome) {\n  const nomeCompleto = `${nome} ${sobrenome}`;\n  function andar() {\n    return `${nomeCompleto} andou`;\n  }\n  return Object.freeze({\n    nome,\n    sobrenome,\n    andar,\n  });\n}\n\nconst designer = criarPessoa('André', 'Rafael');\n```\n\n- CONSTRUCTOR FUNCTION / FACTORY FUNCTION\n   - 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.\n```js\nfunction Pessoa(nome) {\n  if (!(this instanceof Pessoa)) // ou (!new.target)\n    return new Pessoa(nome);\n  this.nome = nome;\n}\n\nPessoa.prototype.andar = function() {\n  return `${this.nome} andou`;\n}\n\nconst designer = Pessoa('André');\n```\n\n- EXEMPLO REAL\n```js\nfunction $$(selectedElements) {\n  const elements = document.querySelectorAll(selectedElements);\n\n  function on(onEvent, callback) {\n    elements.forEach(element =\u003e {\n      element.addEventListener(onEvent, callback);\n    });\n    return this; // retornar this irá funcionar da mesma forma\n  }\n\n  function hide() {\n    elements.forEach(element =\u003e {\n      element.style.display = 'none';\n    });\n    return this;\n  }\n\n  function show() {\n    elements.forEach(element =\u003e {\n      element.style.display = 'initial';\n    });\n    return this;\n  }\n\n  function addClass(className) {\n    elements.forEach(element =\u003e {\n      element.classList.add(className);\n    });\n    return this;\n  }\n\n  function removeClass(className) {\n    elements.forEach(element =\u003e {\n      element.classList.add(className);\n    });\n    return this;\n  }\n  \n  return Object.freeze({\n    elements,\n    on,\n    hide,\n    show,\n    addClass,\n    removeClass,\n  });\n}\n\nconst buttons = $$('button');\nbuttons.hide().show().addClass('ativo').removeClass('ativo');\n```\n\n## Clojures e Debugging\n\n- ESCOPO\n   - 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.\n```js\nlet item1 = 1;\nfunction funcao1() {\n  let item2 = 2;\n  function funcao2() {\n    let item3 = 3;\n  }\n}\n\n// func1, possui acesso à\n// item1 e item2\n\n// func2, possui acesso à\n// item1, item2 e item3\n```\n\n- CLOJURES\n   - 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.\n```js\nlet item1 = 1;\nfunction funcao1() {\n  let item2 = 2;\n  function funcao2() {\n    let item3 = 3;\n    console.log(item1);\n    console.log(item2);\n    console.log(item3);\n  }\n  funcao2();\n}\n```\n\n- DEBUGGING\n   - É 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.\n```js\ndebugger; // adicione a palavra debugger\nlet item1 = 1;\nfunction funcao1() {\n  let item2 = 2;\n  function funcao2() {\n    let item3 = 3;\n    console.log(item1);\n    console.log(item2);\n    console.log(item3);\n  }\n  funcao2();\n}\n```\n\n- CASO CLÁSSICO\n   - 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.\n```js\nfunction contagem() {\n  let total = 0;\n  return function incrementar() {\n    total++;\n    console.log(total);\n  }\n}\n\nconst ativarIncrementar = contagem();\nativarIncrementar(); // 1\nativarIncrementar(); // 2\nativarIncrementar(); // 3\n```\n\n- CLOJURES NA REAL\n   - 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.\n```js\nfunction $$(selectedElements) {\n  const elements = document.querySelectorAll(selectedElements);\n\n  function hide() { ... }\n  function show() { ... }\n  function on() { ... }\n  function addClass() { ... }\n  function removeClass() { ... }\n\n  return { hide, show, on, addClass, removeClass }\n}\n```\n\n- DESTRUCTURING\n   - Permite a desestruturação de Arrays e Objetos. Atribuindo suas propriedades à novas variáveis.\n```js\nconst carro = {\n  marca: 'Fiat',\n  ano: 2018,\n  portas: 4,\n}\n\nconst {marca, ano} = carro;\n\nconsole.log(marca); // Fiat\nconsole.log(ano); // 2018\n```\n\n- DESTRUCTURING OBJECTS\n   - A desestruturação irá facilitar a manipulação de dados. Principalmente quando temos uma grande profundidade de objetos.\n```js\nconst cliente = {\n  nome: 'Andre',\n  compras: {\n    digitais: {\n      livros: ['Livro 1', 'Livro 2'],\n      videos: ['Video JS', 'Video HTML']\n    },\n    fisicas: {\n      cadernos: ['Caderno 1']\n    }\n  }\n}\n\nconsole.log(cliente.compras.digitais.livros);\nconsole.log(cliente.compras.digitais.videos);\n\nconst {livros, videos} = cliente.compras.digitais;\n\nconsole.log(livros);\nconsole.log(videos);\n```\n\n- NESTING\n   - É possível aninhar uma desestruturação dentro de outra.\n```js\nconst cliente = {\n  nome: 'Andre',\n  compras: {\n    digitais: {\n      livros: ['Livro 1', 'Livro 2'],\n      videos: ['Video JS', 'Video HTML']\n    },\n    fisicas: {\n      cadernos: ['Caderno 1']\n    }\n  }\n}\n\nconst {fisicas, digitais, digitais: {livros, videos}} = cliente.compras;\n\nconsole.log(fisicas);\nconsole.log(livros);\nconsole.log(videos);\nconsole.log(digitais);\n```\n\n- NOME DAS VARIÁVEIS\n   - É necessário indicar o nome da propriedade que você deseja desestruturar de um objeto. É possível mudar o nome da variável final com:\n```js\nconst cliente = {\n  nome: 'Andre',\n  compras: 10,\n}\n\nconst {nome, compras} = cliente;\n// ou\nconst {nome: nomeCliente, compras: comprasCliente} = cliente;\n```\n\n- VALOR INICIAL\n   - Caso a propriedade não exista o valor padrão dela será undefined. É possível modificar este valor no momento da desestruturação.\n```js\nconst cliente = {\n  nome: 'Andre',\n  compras: 10,\n}\n\nconst {nome, compras, email = 'email@gmail.com', cpf} = cliente;\nconsole.log(email) // email@gmail.com\nconsole.log(cpf) // undefined\n```\n\n- DESTRUCTURING ARRAYS\n   - Para desestruturar array's você deve colocar as variáveis entre [] colchetes.\n```js\nconst frutas = ['Banana', 'Uva', 'Morango'];\n\nconst primeiraFruta = frutas[0];\nconst segundaFruta = frutas[1];\nconst terceiraFruta = frutas[2];\n\n// Com destructuring\nconst [primeira, segunda, terceira] = frutas;\n```\n\n- DECLARAÇÃO DE VARIÁVEIS\n   - A desestruturação pode servir para declararmos uma sequência de variáveis.\n```js\nconst primeiro = 'Item 1';\nconst segundo = 'Item 2';\nconst terceiro = 'Item 3';\n// ou\nconst [primeiro, segundo, terceiro] = ['Item 1', 'Item 2', 'Item 3']; \n```\n\n- ARGUMENTO DESESTRUTURADO\n   - Se uma função espera receber como argumento um objeto, podemos desestruturar ele no momento da declaração.\n```js\nfunction handleKeyboard(event) {\n  console.log(event.key);\n}\n// Com Destructuring\nfunction handleKeyboard({key}) {\n  console.log(key);\n}\n\ndocument.addEventListener('keyup', handleKeyboard);\n```\n\n- EXERCÍCIOS\n```js\n// Extraia o backgroundColor, color e margin do btn\nconst btn = document.querySelector('button');\nconst btnStyles = getComputedStyle(btn);\n\n\n// Troque os valores das variáveis abaixo\nlet cursoAtivo = 'JavaScript';\nlet cursoInativo = 'HTML';\n\n// Corrija o erro abaixo\nconst cachorro = {\n  nome: 'Bob',\n  raca: 'Labrador',\n  cor: 'Amarelo'\n}\n\nconst {bobCor: cor} = cachorro;\n```\n\n- Rest e Spread\n- PARÂMETROS\n   - 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.\n```js\nfunction perimetroForma(lado, totalLados) {\n  return lado * totalLados;\n}\n\nperimetroForma(10, 4); // 40\nperimetroForma(10); // NaN\n```\n\n- PARÂMETRO PADRÃO (DEFAULT) ES5\n   - Antes do ES6 a forma de definirmos um valor padrão para um parâmetro, era através de uma expressão.\n```js\nfunction perimetroForma(lado, totalLados) {\n  totalLados = totalLados || 4; // se não for definido, será igual à 4\n  return lado * totalLados;\n}\n\nperimetroForma(10, 3); // 30\nperimetroForma(10); // 40\n```\n\n- PARÂMETRO PADRÃO (DEFAULT) ES6+\n   - 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.\n```js\nfunction perimetroForma(lado, totalLados = 4) {\n  return lado * totalLados;\n}\n\nperimetroForma(10, 5); // 50\nperimetroForma(10); // 40\n```\n\n- ARGUMENTS\n   - A palavra chave arguments é um objeto Array-like criado dentro da função. Esse objeto contém os valores dos argumentos.\n```js\nfunction perimetroForma(lado, totalLados = 4) {\n  console.log(arguments)\n  return lado * totalLados;\n}\n\nperimetroForma(10);\nperimetroForma(10, 4, 20);\n```\n\n- PARÂMETRO REST\n   - É 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.\n```js\nfunction anunciarGanhadores(...ganhadores) {\n  ganhadores.forEach(ganhador =\u003e {\n    console.log(ganhador + ' ganhou.')\n  });\n}\n\nanunciarGanhadores('Pedro', 'Marta', 'Maria');\n```\n\n- ÚNICO REST\n   - Só é possível ter um único parâmetro rest e ele deve ser o último.\n```js\nfunction anunciarGanhadores(premio, ...ganhadores) {\n  ganhadores.forEach(ganhador =\u003e {\n    console.log(ganhador + ' ganhou um ' + premio)\n  });\n}\n\nanunciarGanhadores('Carro', 'Pedro', 'Marta', 'Maria');\n```\n\n- REST VS ARGUMENTS\n   - 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.\n```js\nfunction anunciarGanhadores(premio, ...ganhadores) {\n  console.log(ganhadores);\n  console.log(arguments);\n}\n\nanunciarGanhadores('Carro', 'Pedro', 'Marta', 'Maria');\n```\n\n- OPERADOR SPREAD\n   - 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.\n```js\nconst frutas = ['Banana', 'Uva', 'Morango'];\nconst legumes = ['Cenoura', 'Batata'];\n\nconst comidas = [...frutas, 'Pizza', ...legumes];\n```\n\n- SPREAD ARGUMENT\n   - O Spread pode ser muito útil para funções que recebem uma lista de argumentos ao invés de uma array.\n```js\nconst numeroMaximo = Math.max(4,5,20,10,30,2,33,5); // 33\n\nconst listaNumeros = [1,13,21,12,55,2,3,43];\nconst numeroMaximoSpread = Math.max(...listaNumeros);\n```\n\n- TRANSFORMAR EM ARRAY\n   - É possível transformar itens iteráveis em uma array real com o spread.\n```js\nconst btns = document.querySelectorAll('button');\nconst btnsArray = [...btns];\n\nconst frase = 'Isso é JavaScript';\nconst fraseArray = [...frase];\n```\n\n- EXERCÍCIOS\n```js\n// Reescreva a função utilizando\n// valores iniciais de parâmetros com ES6\nfunction createButton(background, color) {\n  background = background || 'blue';\n  if(color === undefined) {\n    color = 'red';\n  }\n  const buttonElement = document.createElement('button');\n  buttonElement.style.background = background;\n  return buttonElement;\n} \n\nconst redButton = createButton();\n\n// Utilize o método push para inserir as frutas ao final de comidas.\nconst frutas = ['Banana', 'Uva', 'Morango'];\nconst comidas = ['Pizza', 'Batata'];\n```\n\n- ITERABLE\n   - 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.\n```js\nconst frutas = ['Banana', 'Morango', 'Uva'];\nconst frase = 'Isso é JavaScript';\n\nfetch('https://pokeapi.co/api/v2/pokemon/')\n.then(({headers}) =\u003e console.log(headers));\n```\n\n- FOR...OF\n   - É 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.\n```js\nconst frutas = ['Banana', 'Morango', 'Uva'];\nconst frase = 'Isso é JavaScript';\n\nfor(const fruta of frutas) {\n  console.log(fruta);\n}\n\nfor(const char of frase) {\n  console.log(char);\n}\n```\n\n- SPREAD E FOR...OF\n   - Com o for loop podemos manipular cada um dos elementos do objeto iterável.\n```js\nconst buttons = document.querySelectorAll('button');\n\nfor(const btn of buttons) {\n  btn.style.background = 'blue';\n}\n\nconsole.log(...buttons);\n```\n\n- APENAS ITERÁVEIS\n   - O for...of não irá funcionar em um objeto comum que não seja iterável.\n```js\nconst carro = {\n  marca: 'Honda',\n  ano: 2018,\n}\n\n// Erro, não é Iterável\nfor(const propriedade of carro) {\n  console.log(propriedade);\n}\n```\n\n- FOR...IN\n   - Este loop irá retornar a chave (key) de todas as propriedades enumeráveis (que não sejam símbolos) de um objeto.\n```js\nconst carro = {\n  marca: 'Honda',\n  ano: 2018,\n}\n\nfor(const propriedade in carro) {\n  console.log(propriedade);\n}\n```\n\n- ARRAYS E FOR...IN\n   - Uma Array é um objeto, porém a chave de cada valor é igual ao seu index.\n```js\nconst frutas = ['Banana', 'Morango', 'Uva'];\n\nfor(const index in frutas) {\n  console.log(index);\n}\n\nfor(const index in frutas) {\n  console.log(frutas[index]);\n}\n```\n\n- CHAVE E VALOR\n   - Utilizando o for...in podemos retornar todas as chaves e valores de propriedades enumeráveis.\n```js\nconst btn = document.querySelector('button');\nconst btnStyles = getComputedStyle(btn);\n\nfor(const style in btnStyles) {\n  console.log(`${style}: ${btnStyles[style]}`);\n}\n```\n\n- DO / WHILE\n   - Outro tipo de loop é o Do / While. Não é muito utilizado.\n```js\nlet i = 0;\ndo {\n  console.log(i++)\n} while (i \u003c= 5);\n```\n\n- REGULAR EXPRESSION\n   - 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().\n```js\n// Procura: a\nconst padraoRegexp = /a/;\n\nconst texto = 'JavaScript';\nconst novoTexto = texto.replace(padraoRegexp, 'B');\n// BavaScript\n```\n- Praticamente todas as linguagens possuem uma implementação de regexp\n\n- LITERAL\n   - Utilizar um caracter literal irá realizar uma busca específica deste caracter.\n```js\n// Procura: J seguido de a, v e a\nconst regexp = /Java/;\n\n'JavaScript'.replace(regexp, 'Type');\n// TypeScript\n```\n\n- FLAG: G\n   - 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.\n```js\n// Procura: Todo a\nconst regexp = /a/g;\n\n'JavaScript'.replace(regexp, 'i');\n// JiviScript\n```\n\n- FLAG: I\n   - 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.\n```js\n// Procura: Todo PE, Pe, pE e pe\nconst regexp = /Pe/gi;\n\n'Perdeu perdido'.replace(regexp, 'Ba');\n// Bardeu Bardido\n```\n\n- CHARACTER CLASS\n   - Se colocarmos os caracteres entre colchetes, estamos definindo uma classe. /[ab]/ irá procurar por a ou por b.\n```js\n// Procura: Todo a, A, i, I\nconst regexp = /[ai]/gi;\n\n'JavaScript'.replace(regexp, 'u');\n// JuvuScrupt\n```\n\n- CHARACTER CLASS E ESPECIAIS\n   - Podemos utilizar caracteres que não são alfanuméricos dentro da classe. Mas fique atento, pois existem diversos casos especiais para os mesmos.\n```js\n// Procura: - ou .\nconst regexp = /[-.]/g;\n\n'111.222-333-44'.replace(regexp, '');\n// 11122233344\n```\n\n- UM OU OUTRO\n   - Combine caracteres literais com uma classe para buscarmos variações: Ju[nl]ho busca Julho ou Junho.\n```js\n// Procura: B, seguido de r, a\n// seguido de s ou z, seguido de i, l\nconst regexp = /Bra[sz]il/g;\n\n'Brasil é com z: Brazil'.replace(regexp, 'Prazer');\n// Prazer é com z: Prazer\n```\n\n- DE A À Z\n   - 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.\n```js\n// Busca por itens de a à z\nconst regexp = /[a-z]/g;\n\n'JavaScript é a linguagem.'.replace(regexp, '0');\n// J000S00000 é 0 000000000.\n\n// Busca por itens de a à z e A à Z\nconst regexp = /[a-zA-Z]/g;\n\n'JavaScript é a linguagem.'.replace(regexp, '1');\n// 1111111111 é 1 111111111.\n\n// Busca por números de 0 à 9\nconst regexpNumero = /[0-9]/g;\n\n'123.333.333-33'.replace(regexpNumero, 'X');\n// XXX.XXX.XXX-XX\n```\n- https://unicode-table.com/en/\n\n- NEGAR\n   - Utilizando o acento circunflexo podemos negar caracteres. Ou seja, pegue tudo que não seja [^a]\n```js\n// Procura: tudo que não estiver entre a e z\nconst regexp = /[^a-z]/g;\n\n'Brasil é com z: Brazil'.replace(regexp, ' ');\n// rasil   com z   razil \n```\n\n- PONTO\n   - O ponto . irá selecionar qualquer caracter, menos quebras de linha.\n```js\n// Procura: todos os caracteres menos quebra de linha\nconst regexp = /./g;\n\n'JavaScript é a linguagem.'.replace(regexp, '0');\n// 0000000000000000000000000\n```\n\n- ESCAPAR ESPECIAIS\n   - 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: +*?^$\\.[]{}()|/\n```js\n// Procura: todos os pontos\nconst regexp = /\\./g;\nconst regexpAlternativa = /[.]/g;\n\n'999.222.222.11'.replace(regexp, '-');\n// 999-222-222-11\n```\n\n- WORD\n   - O \\w irá selecionar qualquer caracter alfanumérico e o underline. É a mesma coisa que [A-Za-z0-9_].\n```js\n// Procura: todos os alfanuméricos\nconst regexp = /\\w/g;\n\n'Guarda-chuva R$ 23,00.'.replace(regexp, '-');\n// ------------ -$ --,--.\n```\n\n- NOT WORD\n   - O \\W irá selecionar tudo o que não for caracter alfanumérico e o underline. É a mesma coisa que [^A-Za-z0-9_].\n```js\n// Procura: o que não for caracter alfanuméricos\nconst regexp = /\\W/g;\n\n'Guarda-chuva R$ 23,00.'.replace(regexp, '-');\n// Guarda-chuva-R--23-00-\n```\n\n- DIGIT\n   - O \\d irá selecionar qualquer dígito. É a mesma coisa que [0-9].\n```js\n// Procura: todos os dígitos\nconst regexp = /\\d/g;\n\n'+55 (21) 2222-2222'.replace(regexp, 'X');\n// +XX (XX) XXXX-XXXX.\n```\n\n- NOT DIGIT\n   - O \\D irá selecionar tudo que não for dígito. É a mesma coisa que [^0-9].\n```js\n// Procura: o que não for dígito\nconst regexp = /\\D/g;\n\n'+55 (21) 2222-2222'.replace(regexp, '');\n// 552122222222\n```\n\n- WHITESPACE\n   -O \\s irá selecionar qualquer espaço em branco, isso inclui espaços, tabs, quebra de linhas.\n```js\n// Procura: espaços em branco\nconst regexp = /\\s/g;\n\n'+55 (21) 2222-  2222  '.replace(regexp, '');\n// +55(21)2222-2222\n```\n\n- NOT WHITESPACE\n   - O \\S irá selecionar qualquer caracter que não for espaço em branco.\n```js\n// Procura: o que não for espaço em branco\nconst regexp = /\\S/g;\n\n'+55 (21) 2222-  2222  '.replace(regexp, '');\n// XXX XXXX XXXXX  XXXX  \n```\n=/[\\s\\S]/g irá selecionar tudo.\n\n- QUANTIFICADOR\n   - É 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.\n```js\n// Procura: 4 a's seguidos\nconst regexp = /aaaa/g;\nconst regexpAlt = /a{4}/g;\n\n'Vaaaai ali por favor.'.replace(regexp, 'a');\n// Vai ali por favor.  \n```\n\n- QUANTIFICADOR MIN E MAX\n   - 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.\n\n```js\n// Procura: dígitos seguidos de 2 à 3\nconst regexp = /\\d{2,3}/g;\n\n'222.333.222.42'.replace(regexp, 'X');\n// X.X.X.X\n\n// Procura: letras seguidos com 1 caracter ou mais\nconst regexpLetras = /\\w{1,}/g;\n\n'A melhor linguagem é JavaScript'.replace(regexpLetras, 'X');\n// X X X é X\n```\n\n- MAIS +\n   - O sinal de + significa que devemos selecionar quando existir pelo menos uma ou mais ocorrências.\n```js\n// Procura: dígitos em ocorrência de um ou mais\nconst regexp = /\\d+/g;\n\n'222.333.222.42'.replace(regexp, 'X');\n// X.X.X.X\n\n// Procura: Começa com d, seguido por uma ou mais letras.\nconst regexpLetras = /d\\w+/g;\n\n'Dígitos, dados, desenhos, Dito, d'.replace(regexpLetras, 'X');\n// Dígitos, X, X, Dito, d\n```\n\n- ASTERISCO *\n   - O sinal * significa que devemos selecionar quando existir 0 ou mais ocorrências.\n```js\n// Procura: Começa com d, seguido por zero ou mais letras.\nconst regexp = /d\\w*/g;\n\n'Dígitos, dados, desenhos, Dito, d'.replace(regexp, 'X');\n// Dígitos, X, X, Dito, X\n```\n\n- OPCIONAL ?\n   - O sinal ? significa que o caracter é opcional, pode ou não existir.\n```js\n// Procura: Por regex com p opcional\nconst regexp = /regexp?/g;\n\n'Qual é o certo, regexp ou regex?'.replace(regex, 'Regular Expression');\n// Qual é o certo, Regular Expression ou Regular Expression?\n```\n\n- ALTERNADO |\n   - O sinal | irá selecionar um ou outro. java|php\n```js\n// Procura: java ou php (case insensitive)\nconst regexp = /java|php/gi;\n\n'PHP e Java são linguagens diferentes'.replace(regexp, 'X');\n// X e X são linguagens diferente\n```\n\n- WORD BOUNDARY \\B\n   - O sinal \\b irá indicar que pretendemos fazer uma seleção que deve ter início e fim de não caracteres \\w.\n```js\n// Procura: java (case insensitive)\nconst regexp = /java/gi;\n'Java não é JavaScript.'.replace(regexp, 'X');\n// X não é XScript.\n\n// Procura: java (case insensitive)\nconst regexpBoundary = /\\bjava\\b/gi;\n'Java não é JavaScript.'.replace(regexpBoundary, 'X');\n// X não é JavaScript.\n\n// Procura: Dígitos em sequência, que estejam isolados\nconst regexpDigito = /\\b\\d+\\b/gi;\n'O Restaurante25 na Rua 3, custa R$ 32,00'.replace(regexDigito, 'X');\n// O Restaurante25 na Rua X, custa R$ X,X\n\n'11_22 33-44 55é66 77e88'.replace(regexpDigito, 'X');\n// 11_22 X-X XéX 77e88\n```\n\n- NOT WORD BOUNDARY \\B\n   - É o contrário do \\b.\n```js\nconst regexpDigito = /\\B\\d+\\B/gi;\n\n'11_22 33-44 55é66 77e88'.replace(regexpDigito, 'X');\n// 1X_X2 33-44 55é66 7XeX8\n```\n\n- ANCHOR BEGINNING\n   - Com o ^ é possível informar que a busca deve ser iniciada no início da linha.\n```js\n// Procura: sequência de alfanuméricos\n// no início da linha.\nconst regexp = /^\\w+/g;\n\n`andre@origamid.com\ncontato@origamid.com`.replace(regexp, 'X');\n// X@origamid.com\n// contato@origamid.com\n```\n\n- ANCHOR END\n   - Com o $ é possível informar que a busca deve ser iniciada no final da linha.\n```js\n// Procura: sequência de alfanuméricos\n// no final da linha.\nconst regexp = /\\w+$/g;\n\n`andre@origamid.com\ncontato@origamid.com`.replace(regexp, 'X');\n// andre@origamid.com\n// contato@origamid.X\n```\n\n- FLAG: M\n   - 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.\n```js\n// Procura: sequência de alfanuméricos\n// no final da linha.\nconst regexp = /\\w+$/gm;\n\n`andre@origamid.com\ncontato@origamid.com`.replace(regexp, 'X');\n// andre@origamid.X\n// contato@origamid.X\n\n// Procura: sequência de alfanuméricos\n// no início da linha.\nconst regexp = /^\\w+/gm;\n\n`andre@origamid.com\ncontato@origamid.com`.replace(regexp, 'X');\n// X@origamid.com\n// X@origamid.com\n```\n\n- LINE FEED \\N\n   - O \\n irá selecionar o final de uma linha, quando criamos uma nova.\n```js\nconst regexp = /\\n/g;\n\n`andre@origamid.com\\ncontato@origamid.com`.replace(regexp, '---');\n// andre@origamid.com---contato@origamid.com\n\n`andre@origamid.com\ncontato@origamid.com`.replace(regexp, 'X');\n// andre@origamid.com---contato@origamid.com\n\\t seleciona tabs\n```\n\n- UNICODE \\U\n   - O \\u irá selecionar o respectivo caracter unicode, de acordo com o código passado em \\uXXXX. Ex: \\u0040 seleciona o @.\n```js\n// Procura: @ ou ©\nconst regexp = /\\u0040|\\u00A9/g;\n\n'andre@origamid.com ©'.replace(regexp, '---');\n// andre---origamid.com ---\n```\n\n- REFERÊNCIA DA SELEÇÃO\n   - É possível utilizarmos o $\u0026 durante o momento da substituição para fazermos uma referência à seleção.\n```js\n// Procura: Java\nconst regexp = /Java/g;\n\n'PHP e Java são linguagens diferentes'.replace(regexp, '--$\u0026Script');\n// PHP e --JavaScript são linguagens diferentes\n// $\u0026 será igual à Java\n```\n\n- GRUPO DE CAPTURA\n   - É 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.\n```js\n// Procura: sequência alfanumérica, seguida\n// de @, seguido de alfanumérico ou .\nconst regexp = /(\\w+)@[\\w.]+/g;\n\n'andre@email.com.br'.replace(regexp, '$1@gmail.com');\n// andre@gmail.com\n```\n- Não use este regexp para emails, ele falha em alguns casos.\n\n- MAIS DE UM GRUPO\n   - Podemos definir quantos grupos de captura quisermos.\n```js\n// Procura: sequência alfanumérica, seguida\n// de , seguido espaço de sequência alfanumérica.\nconst regexp = /(\\w+),\\s(\\w+)/g;\n\n'Rafael, Andre'.replace(regexp, '$2 $1');\n// Andre Rafael\n```\n\n- MAIS DO QUE CAPTURA APENAS\n   - Um grupo também serve para agruparmos uma sequência de caracteres que queremos em repetição.\n```js\n// Procura: qualquer sequência de ta\nconst regexp = /(ta)+/gi;\n\n'Tatata, tata, ta'.replace(regexp, 'Pá');\n// Pá, Pá, Pá\n```\n\n- IGNORAR CAPTURA\n   - Utilize o (?:) para ignorar a captura.\n```js\n// Procura: qualquer sequência de ta\nconst regexp = /(?:ta)+/gi;\n\n'Tatata, tata, ta'.replace(regexp, 'Pá');\n// Pá, Pá, Pá\n```\n\n- POSITIVE LOOKAHEAD\n   - 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.\n```js\n// Procura: dígitos em sequência, que\n// possuírem px, sem selecionar o px.\nconst regexp = /\\d(?=px)/g;\n\n'2em, 4px, 5%, 2px, 1px'.replace(regexp, 'X');\n// 2em, Xpx, 5%, Xpx, Xpx\n```\n\n- NEGATIVE LOOKAHEAD\n   - Faz a seleção dos itens não possuírem o padrão dentro de (?!) à sua frente.\n```js\n// Procura: dígitos que não possuírem px\n// sem selecionar o restante.\nconst regexp = /\\d(?!px)/g;\n\n'2em, 4px, 5%, 5px, 1px'.replace(regexp, 'X');\n// Xem, 4px, X%, 5px, 1px\n```\n\n- POSITIVE LOOKBEHIND\n   - Faz a seleção dos itens que possuírem o padrão dentro de (?\u003c=) atrás dos mesmos.\n```js\n// Procura: dígitos que possuírem R$\n// na frente dos mesmos\nconst regexp = /(?\u003c=R\\$)[\\d]+/g;\n\n'R$99, 100, 200, R$20'.replace(regexp, 'X');\n// R$X, 100, 200, R$X\n```\n\n- CEP\n```js\nconst regexpCEP = /\\d{5}[-\\s]?\\d{3}/g;\n\nconst ceps = [\n  '00000-000',\n  '00000 000',\n  '00000000'\n];\n\nfor(cep of ceps) {\n  console.log(cep, cep.match(regexpCEP));\n}\n```\n\n- CPF\n```js\nconst regexpCPF = /(?:\\d{3}[-.]?){3}\\d{2}/g;\n\nconst cpfs = [\n  '000.000.000-00',\n  '000-000-000-00',\n  '000.000.000.00',\n  '000000000-00',\n  '00000000000'\n];\n\nfor(cpf of cpfs) {\n  console.log(cpf, cpf.match(regexpCPF));\n}\n```\n\n- CNPJ\n```js\nconst regexpCNPJ = /\\d{2}[-.]?(?:\\d{3}[-.]?){2}[-\\/]?\\d{4}[-.]?\\d{2}/g;\n\nconst cnpjs = [\n  '00.000.000/0000-00',\n  '00000000000000',\n  '00-000-000-0000-00',\n  '00.000.000/000000',\n  '00.000.000.000000',\n  '00.000.000.0000.00',\n];\n\nfor(cnpj of cnpjs) {\n  console.log(cnpj, cnpj.match(regexpCNPJ));\n}\n```\n\n- TELEFONE\n```js\nconst regexpTELEFONE = /(?:\\+?55\\s?)?(?:\\(?\\d{2}\\)?[-\\s]?)?\\d{4,5}[-\\s]?\\d{4}/g;\n\nconst telefones = [\n  '+55 11 98888-8888',\n  '+55 11 98888 8888',\n  '+55 11 988888888',\n  '+55 11988888888',\n  '+5511988888888',\n  '5511988888888',\n  '11 98888-8888',\n  '11 98888 8888',\n  '(11) 98888 8888',\n  '(11) 98888-8888',\n  '11-98888-8888',\n  '11 98888 8888',\n  '11988888888',\n  '11988888888',\n  '988888888',\n  '(11)988888888',\n  '98888 8888',\n  '8888 8888'\n];\n\nfor(telefone of telefones) {\n  console.log(telefone, telefone.match(regexpTELEFONE));\n}\n```\n\n- EMAIL\n```js\nconst regexpEMAIL = /[\\w.-]+@[\\w-]+\\.[\\w-.]+/gi;\n\nconst emails = [\n  'email@email.com',\n  'email@email.com.org',\n  'email-email@email.com',\n  'email_email@email.com',\n  'email.email23@email.com.br',\n  'email.email23@empresa-sua.com.br',\n  'c@contato.cc',\n];\n\nfor(email of emails) {\n  console.log(email, email.match(regexpEMAIL));\n}\n```\n- http://emailregex.com/\n\n\n- TAG\n```js\nconst regexpTAG = /\u003c\\/?[\\w\\s=\"']+\\/?\u003e/gi;\nconst tags = [\n  '\u003cdiv\u003eIsso é uma div\u003c/div\u003e',\n  '\u003cdiv class=\"ativa\"\u003eEssa está ativa\u003c/div\u003e',\n  '\u003cimg src=\"imagem\" /\u003e',\n  '\u003cimg src=\"imagem\"\u003e',\n  '\u003cul class=\"ativa\"\u003e',\n  '\u003cli\u003eEssa está ativa\u003c/li\u003e',\n  '\u003c/ul\u003e'\n];\n\nfor(tag of tags) {\n  console.log(tag, tag.match(regexpTAG));\n}\n```\n\n- TAG APENAS O NOME\n```js\nconst regexpTAG = /(?\u003c=\u003c\\/?)[\\w]+/gi;\nconst tags = [\n  '\u003cdiv\u003eIsso é uma div\u003c/div\u003e',\n  '\u003cdiv class=\"ativa\"\u003eEssa está ativa\u003c/div\u003e',\n  '\u003cimg src=\"imagem\" /\u003e',\n  '\u003cimg src=\"imagem\"\u003e',\n  '\u003cul class=\"ativa\"\u003e',\n  '\u003cli\u003eEssa está ativa\u003c/li\u003e',\n  '\u003c/ul\u003e'\n];\n\nfor(tag of tags) {\n  console.log(tag, tag.match(regexpTAG));\n}\n```\n- Positive Lookbehind (?\u003c=) não está disponível em todos os browsers.\n\n\n- REGEXP CONSTRUCTOR\n   - 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.\n```js\nconst regexp = /\\w+/gi;\n\n// Se passarmos uma string, não precisamos dos //\n// e devemos utilizar \\\\ para meta characters, pois é necessário\n// escapar a \\ especial. As Flags são o segundo argumento\nconst regexpObj1 = new RegExp('\\\\w+', 'gi');\nconst regexpObj2 = new RegExp(/\\w+/, 'gi');\n\n'JavaScript Linguagem 101'.replace(regexpObj1, 'X');\n// X X X\n\n// Exemplo complexo:\nconst regexpTELEFONE1 = /(?:\\+?55\\s?)?(?:\\(?\\d{2}\\)?[-\\s]?)?\\d{4,5}[-\\s]?\\d{4}/g;\nconst regexpTELEFONE2 = new RegExp('(?:\\\\+?55\\\\s?)?(?:\\\\(?\\\\d{2}\\\\)?[-\\\\s]?)?\\\\d{4,5}[-\\\\s]?\\\\d{4}', 'g');\n```\n\n- PROPRIEDADES\n   - Uma regexp possui propriedades com informações sobre as flags e o conteúdo da mesma.\n```js\nconst regexp = /\\w+/gi;\n\nregexp.flags; // 'gi'\nregexp.global; // true\nregexp.ignoreCase; // true\nregexp.multiline; // false\nregexp.source; // '\\w+'\n```\n\n- REGEXP.TEST()\n   - 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.\n```js\nconst regexp = /Java/g;\nconst frase = 'JavaScript e Java';\n\nregexp.lastIndex; // 0\nregexp.test(frase); // true\nregexp.lastIndex; // 4\nregexp.test(frase); // true\nregexp.lastIndex; // 17\nregexp.test(frase); // false\nregexp.lastIndex; // 0\nregexp.test(frase); // true (Reinicia\nregexp.lastIndex;  // 4\n```\n\n- TEST() EM LOOP\n   - Podemos utilizar o while loop, para mostrar enquanto a condição for verdadeira. Assim retornamos a quantidade de match's.\n```js\nconst regexp = /Script/g;\nconst frase = 'JavaScript, TypeScript e CoffeeScript';\n\nlet i = 1;\nwhile(regexp.test(frase)) {\n  console.log(i++, regexp.lastIndex);\n}\n// 1 10\n// 2 22\n// 3 37\n```\n\n- REGEXP.EXEC()\n   - O exec() diferente do test(), irá retornar uma Array com mais informações do que apenas um valor booleano.\n```js\nconst regexp = /\\w{2,}/g;\nconst frase = 'JavaScript, TypeScript e CoffeeScript';\n\nregexp.exec(frase);\n// [\"JavaScript\", index: 0, input: \"JavaScript,\n// TypeScript e CoffeeScript\", groups: undefined] \nregexp.exec(frase);\n// [\"TypeScript\", index: 12, input: \"JavaScript,\n// TypeScript e CoffeeScript\", groups: undefined] \nregexp.exec(frase);\n// [\"CoffeeScript\", index: 25, input: \"JavaScript,\n// TypeScript e CoffeeScript\", groups: undefined] \nregexp.exec(frase);\n// null\nregexp.exec(frase); // Reinicia\n// [\"JavaScript\", index: 0, input: \"JavaScript,\n// TypeScript e CoffeeScript\", groups: undefined] \n```\n\n- LOOP COM EXEC()\n   - Podemos fazer um loop com exec e parar o mesmo no momento que encontre o null.\n```js\nconst regexp = /\\w{2,}/g;\nconst frase = 'JavaScript, TypeScript e CoffeeScript';\nlet regexpResult;\n\nwhile((regexpResult = regexp.exec(frase)) !== null) {\n  console.log(regexpResult[0]);\n}\n```\n\n- STR.MATCH()\n   - 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.\n```js\nconst regexp = /\\w{2,}/g;\nconst regexpSemG = /\\w{2,}/;\nconst frase = 'JavaScript, TypeScript e CoffeeScript';\n\nfrase.match(regexp);\n// ['JavaScript', 'TypeScript', 'CoffeeScript']\n\nfrase.match(regexpSemG);\n// [\"JavaScript\", index: 0, input: \"JavaScript,\n// TypeScript e CoffeeScript\", groups: undefined]\n```\n- Se não tiver match retorna null\n\n- STR.SPLIT()\n   - 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.\n```js\nconst frase = 'JavaScript, TypeScript, CoffeeScript';\n\nfrase.split(', ');\n// [\"JavaScript\", \"TypeScript\", \"CoffeeScript\"]\nfrase.split(/Script/g);\n// [\"Java\", \", Type\", \", Coffee\", \"\"]\n\nconst tags = `\n\u003cul\u003e\n  \u003cli\u003eItem 1\u003c/li\u003e\n  \u003cli\u003eItem 2\u003c/li\u003e\n\u003c/ul\u003e\n`;\n\ntags.split(/(?\u003c=\u003c\\/?)\\w+/g).join('div');\n// \u003cdiv\u003e\n//   \u003cdiv\u003eItem 1\u003c/div\u003e\n//   \u003cdiv\u003eItem 2\u003c/div\u003e\n// \u003cdiv\u003e\n```\n\n- STR.REPLACE()\n   - 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.\n```js\nconst tags = `\n\u003cul\u003e\n  \u003cli\u003eItem 1\u003c/li\u003e\n  \u003cli\u003eItem 2\u003c/li\u003e\n\u003c/ul\u003e\n`;\n\ntags.replace(/(?\u003c=\u003c\\/?)\\w+/g, 'div');\n// \u003cdiv\u003e\n//   \u003cdiv\u003eItem 1\u003c/div\u003e\n//   \u003cdiv\u003eItem 2\u003c/div\u003e\n// \u003cdiv\u003e\n```\n\n- CAPTURA\n   - É possível fazer uma referência ao grupo de captura dentro do argumento do replace. Então podemos utilizar $\u0026, $1 e mais.\n```js\nconst tags = `\n\u003cul\u003e\n  \u003cli\u003eItem 1\u003c/li\u003e\n  \u003cli\u003eItem 2\u003c/li\u003e\n\u003c/ul\u003e\n`;\n\ntags.replace(/\u003cli/g, '$\u0026 class=\"ativo\"');\n// \u003cul\u003e\n//   \u003cli class=\"ativo\"\u003eItem 1\u003c/li\u003e\n//   \u003cli class=\"ativo\"\u003eItem 2\u003c/li\u003e\n// \u003c/ul\u003e\n```\n\n- GRUPOS DE CAPTURA\n   - É possível definirmos quantos grupos de captura quisermos.\n```js\nconst emails = `\nempresa@email.com\ncontato@email.com\nsuporte@email.com\n`;\n\nemails.replace(/(\\w+@)[\\w.]+/g, '$1gmail.com');\n// empresa@gmail.com\n// contato@gmail.com\n// suporte@gmail.com\n```\n\n- CALLBACK\n   - 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.\n```js\nconst regexp = /(\\w+)(@[\\w]+)/g;\nconst emails = `joao@homail.com.br\nmarta@ggmail.com.br\nbruna@oulook.com.br`\n\nemails.replace(regexp, function(...args) {\n  console.log(args);\n  if(args[2] === '@homail') {\n    return `${args[1]}@hotmail`;\n  } else if(args[2] === '@ggmail') {\n    return `${args[1]}@gmail`;\n  } else if(args[2] === '@oulook') {\n    return `${args[1]}@outlook`;\n  } else {\n    return 'x';\n  }\n});\n\n// joao@hotmail.com.br\n// marta@gmail.com.br\n// bruna@outlook.com.br\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexgalhardo%2Flearning-javascript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexgalhardo%2Flearning-javascript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexgalhardo%2Flearning-javascript/lists"}