diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
commit | 074785cea106179cb3305637055ab0a009ca74f2 (patch) | |
tree | e6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/pt-br/learn/javascript | |
parent | da78a9e329e272dedb2400b79a3bdeebff387d47 (diff) | |
download | translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2 translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip |
initial commit
Diffstat (limited to 'files/pt-br/learn/javascript')
17 files changed, 6062 insertions, 0 deletions
diff --git a/files/pt-br/learn/javascript/asynchronous/conceitos/index.html b/files/pt-br/learn/javascript/asynchronous/conceitos/index.html new file mode 100644 index 0000000000..f2e6759f41 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/conceitos/index.html @@ -0,0 +1,155 @@ +--- +title: Conceitos gerais da programação assíncrona +slug: Learn/JavaScript/Asynchronous/Conceitos +translation_of: Learn/JavaScript/Asynchronous/Concepts +--- +<div>{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}</div> + +<p>Neste artigo, nós vamos ver um número de conceitos importantes relativos à programação assíncrona e como ela se parece em navegadores modernos e em JavaScript. Você deve entender estes conceitos antes de trabalhar com outros artigos neste módulo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimentos básicos de informática e compreensão dos fundamentos de JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender os conceitos básicos da programação assíncrona e como ela se manifesta em navegadores e JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Assíncrono">Assíncrono?</h2> + +<p>Normalmente, o código de um programa é executado de forma direta, com uma coisa acontecendo por vez. Se uma função depende do resultado de outra função, ela tem que esperar o retorno do resultado, e até que isso aconteça, o programa inteiro praticamente para de funcionar da perspectiva do usuário.</p> + +<p>Usuários do Mac, por exemplo, conseguem ver isso como o cursor giratório em arco-íris (ou "beachball", como normalmente é chamado). Este cursor é o jeito do sistema operacional dizer: "o programa atual que você está usando teve que parar e esperar algo terminar de ser executado, e estava demorando tanto que fiquei preocupado se você estava pensando no que aconteceu."</p> + +<p><img alt="Multi-colored macOS beachball busy spinner" src="https://mdn.mozillademos.org/files/16577/beachball.jpg" style="display: block; float: left; height: 256px; margin: 0px 30px 0px 0px; width: 250px;"></p> + +<p>Essa é uma situação frustrante, e não faz bom uso do poder de processamento do computador — especialmente em uma era em que computadores tem múltiplos núcleos de processamento disponíveis. Não há sentido em ficar esperando por algo quando você pode deixar outra tarefa ser executada em um núcleo de processador diferente e deixar que ele te avise quando terminar. Isso te permite fazer mais coisas por enquanto, o que é a base da <strong>programação assincrona</strong>. Depende do ambiente de programação que você está usando (navegadores da Web, no caso de desenvolvimento da Web) para fornecer APIs que permitem executar essas tarefas de forma assíncrona.</p> + +<h2 id="Bloqueio_de_código">Bloqueio de código</h2> + +<p>Técnicas <strong>async</strong> (assíncronas) são muito úteis, principalmente na programação web. Quando um aplicativo web é executado em um navegador e executa um pedaço de código rigoroso sem retornar o controle para o navegador, ele pode parecer que travou. Isso é chamado de <strong>blocking</strong>; o navegador está bloqueado de continuar a manusear a entrada do usuário e de realizar outras tarefas até que o aplicativo web retorne o controle do processador.</p> + +<p>Vamos dar uma olhadinha em alguns exemplos para que você entenda o blocking.</p> + +<p>No nosso exemplo <a href="https://github.com/mdn/learning-area/tree/master/javascript/asynchronous/introducing/simple-sync.html">simple-sync.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync.html">veja aqui</a>), nós adicionamos um evento de click em um botão para que, quando clicado, ele executa uma tarefa pesada (calcula 10 milhões de datas e depois imprime a última delas no console) e depois adiciona um parágrafo no DOM:</p> + +<pre class="brush: js notranslate">const btn = document.querySelector('button'); +btn.addEventListener('click', () => { + let myDate; + for(let i = 0; i < 10000000; i++) { + let date = new Date(); + myDate = date + } + + console.log(myDate); + + let pElem = document.createElement('p'); + pElem.textContent = 'This is a newly-added paragraph.'; + document.body.appendChild(pElem); +});</pre> + +<p>Quando o exemplo for executado, abra seu console JavaScript e depois clique no botão — você verá qua o parágrafo não aparece até que o programa termine de calcular as datas e imprimir a última no console. O código é executado na ordem em que ele aparece na fonte, e a operação seguinte só é executada depois que a primeira for terminada.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: O exemplo anterior não é muito realistico. Você nunca calcularia 10 milhões de datas em um aplicativo real! Mas isso serve par te dar um apoio sobre o assunto.</p> +</div> + +<p>No nosso segundo exemplo <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-ui-blocking.html">simple-sync-ui-blocking.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-ui-blocking.html">veja aqui</a>), nós simulamos algo mais realistico que você pode encontrar em uma página real. Nós bloqueamos a interatividade do usuário na renderização da UI. Neste exemplo, nós temos dois botões:</p> + +<ul> + <li>Um botão "Fill canvas" que quando for clicado renderiza 1 milhão de círculos azuis no elemento {{htmlelement("canvas")}} .</li> + <li>Um botão "Clique-me" que mostra um alerta quando clicado.</li> +</ul> + +<pre class="brush: js notranslate">function expensiveOperation() { + for(let i = 0; i < 1000000; i++) { + ctx.fillStyle = 'rgba(0,0,255, 0.2)'; + ctx.beginPath(); + ctx.arc(random(0, canvas.width), random(0, canvas.height), 10, degToRad(0), degToRad(360), false); + ctx.fill() + } +} + +fillBtn.addEventListener('click', expensiveOperation); + +alertBtn.addEventListener('click', () => + alert('You clicked me!') +);</pre> + +<p>Se você clicar no primeiro botão e imediatamente no segundo, você verá que a mensagem de alerta não aparece até que os círculos sejam totalmente renderizados. A primeira operação bloqueia a segunda até a sua finalização.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: OK, no nosso caso, isso é ruim e estamos bloqueando o código de propósito, mas isso é um problema comum que desenvolvedores de aplicativos reais sempre tentam resolver.</p> +</div> + +<p>E por quê isso acontece? A resposta é que o JavaScript é <strong>single threaded</strong>. E é neste ponto que precisamos introduzir a você o conceito de <strong>threads</strong>.</p> + +<h2 id="Threads">Threads</h2> + +<p>Uma <strong>thread</strong> é basicamente um único processo que um programa pode usar para concluir tarefas. Cada thread só pode fazer uma tarefa de cada vez:</p> + +<pre class="notranslate">Tarefa A --> Tarefa B --> Tarefa C</pre> + +<p>Cada tarefa será executada sequencialmente; uma tarefa tem que ser concluída antes que a próxima possa ser iniciada.</p> + +<p>Como foi dito anteriormente, muitos computadores possuem múltiplos núcleos, para que possam fazer múltiplas coisas de uma vez só. Linguagens de programação que podem suportar múltiplas threads podem usar múltiplos processadores para concluir múltiplas tarefas simultâneamente:</p> + +<pre class="notranslate">Thread 1: Tarefa A --> Tarefa B +Thread 2: Tarefa C --> Tarefa D</pre> + +<h3 id="JavaScript_é_single_threaded">JavaScript é single threaded</h3> + +<p>JavaScript é tradicionalmente single-threaded. Mesmo com múltiplos núcleos de processamento, você só pode fazê-lo executar tarefas em uma única thread, chamada de <strong>main thread</strong> (thread principal). Nosso exemplo de cima é executado assim:</p> + +<pre class="notranslate">Main thread: Renderizar circulos no canvas --> Mostrar alert()</pre> + +<p>Depois de um tempo, o JavaScript ganhou algumas ferramentas para ajudar em tais problemas. As <a href="/en-US/docs/Web/API/Web_Workers_API">Web workers</a> te permitem mandar parte do processamento do JavaScript para uma thread separada. Você geralmente usaria uma worker para executar um processo pesado para que a UI não seja bloqueada.</p> + +<pre class="notranslate"> Main thread: Tarefa A --> Tarefa C +Worker thread: Tarefa pesada B</pre> + +<p>Com isso em mente, dê uma olhada em <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-worker.html">simple-sync-worker.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-worker.html">veja aqui</a>), com o seu console JavaScript aberto. Isso é uma nova versão do nosso exemplo que calcula 10 milhões de datas em uma tread worker separada. Agora, quando você clica no botão, o navegador é capaz de mostrar o parágrafo antes que as datas sejam terminadas. A primeira opreção não bloqueia a segunda.</p> + +<h2 id="Código_assíncrono">Código assíncrono</h2> + +<p>Web workers podem ser bem úteis, mas elas tem as suas limitações. Uma delas é que elas não são capazes de acessar a {{Glossary("DOM")}} — você não pode fazer com que uma worker faça algo diretamente para atualizar a UI. Nós não poderíamos renderizar nossos 1 milhão de círculos azuis na nossa worker; basicamente ela pode apenas fazer cálculos de números.</p> + +<p>O segundo problema é que, mesmo que o código executado em uma worker não cause um bloqueio, ele ainda é um código síncrono. Isso se torna um problema quando uma função depende dos resultados de processos anteriores para funcionar. Considere os diagramas a seguir:</p> + +<pre class="notranslate">Main thread: Tarefa A --> Tarefa B</pre> + +<p>Nesse caso, digamos que a tarefa A está fazendo algo como pegar uma imagem do servidor e que a tarefa B faz algo com essa imagem, como colocar um filtro nela. Se você iniciar a tarefa A e depois tentar executar a tarefa B imediatamente, você obterá um erro, porque a imagem não estará disponível ainda.</p> + +<pre class="notranslate"> Main thread: Tarefa A --> Tarefa B --> |Tarefa D| +Worker thread: Tarefa C ---------------> | |</pre> + +<p>Neste caso, digamos que a tarefa D faz uso dos resultados das tarefas B e C. Se nós pudermos garantir que esses resultados estejam disponíveis ao mesmo tempo, então tudo talvez esteja bem, mas isso não é garantido. Se a tarefa D tentar ser executada quando um dos resultados não estiver disponível, ela retornará um erro.</p> + +<p>Para consertarmos tais problemas, os browsers nos permitem executar certas operações de modo assíncrono. Recursos como <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a> te permitem executar uma operação e depois esperar pelo resultado antes de executar outra operação: </p> + +<pre class="notranslate">Main thread: Tarefa A Tarefa B + Promise: |___operação async___|</pre> + +<p>Já que a operação está acontecendo em outro lugar, a main thread não está bloqueada enquanto a operação assíncrona está sendo processada.</p> + +<p>Nós vamos começar a olhar em como podemos escrever código assíncrono no próximo artigo.</p> + +<h2 id="Conclusão">Conclusão</h2> + +<p>O design moderno de software gira em torno do uso de programação assíncrona, para permitir que os programas façam mais de uma coisa por vez. Ao usar APIs mais novas e mais poderosas, você encontrará mais casos em que a única maneira de fazer as coisas é assincronamente. Costumava ser difícil escrever código assíncrono. Ainda é preciso se acostumar, mas ficou muito mais fácil. No restante deste módulo, exploraremos ainda mais por que o código assíncrono é importante e como projetar o código que evita alguns dos problemas descritos acima.</p> + +<h2 id="Nesse_módulo">Nesse módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">Conceitos gerais da programação assíncrona</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introduzindo o JavaScript assíncrono</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Timeouts e intervalos</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Código elegante usando as Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Facilitando a programação async com async e await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Escolhendo a abordagem certa</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html b/files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html new file mode 100644 index 0000000000..254bc41a99 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/escolhendo_abordagem_correta/index.html @@ -0,0 +1,523 @@ +--- +title: Escolhendo a abordagem correta +slug: Learn/JavaScript/Asynchronous/Escolhendo_abordagem_correta +translation_of: Learn/JavaScript/Asynchronous/Choosing_the_right_approach +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</div> + +<p>To finish this module off, we'll provide a brief discussion of the different coding techniques and features we've discussed throughout, looking at which one you should use when, with recommendations and reminders of common pitfalls where appropriate. We'll probably add to this resource as time goes on.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Basic computer literacy, a reasonable understanding of JavaScript fundamentals.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To be able to make a sound choice of when to use different asynchronous programming techniques.</td> + </tr> + </tbody> +</table> + +<h2 id="Asynchronous_callbacks">Asynchronous callbacks</h2> + +<p>Generally found in old-style APIs, involves a function being passed into another function as a parameter, which is then invoked when an asynchronous operation has been completed, so that the callback can in turn do something with the result. This is the precursor to promises; it's not as efficient or flexible. Use only when necessary.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + </thead> + <tbody> + <tr> + <td>No</td> + <td>Yes (recursive callbacks)</td> + <td>Yes (nested callbacks)</td> + <td>No</td> + </tr> + </tbody> +</table> + +<h3 id="Code_example">Code example</h3> + +<p>An example that loads a resource via the <a href="/en-US/docs/Web/API/XMLHttpRequest"><code>XMLHttpRequest</code> API</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html">run it live</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html">see the source</a>):</p> + +<pre class="brush: js notranslate">function loadAsset(url, type, callback) { + let xhr = new XMLHttpRequest(); + xhr.open('GET', url); + xhr.responseType = type; + + xhr.onload = function() { + callback(xhr.response); + }; + + xhr.send(); +} + +function displayImage(blob) { + let objectURL = URL.createObjectURL(blob); + + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +} + +loadAsset('coffee.jpg', 'blob', displayImage);</pre> + +<h3 id="Pitfalls">Pitfalls</h3> + +<ul> + <li>Nested callbacks can be cumbersome and hard to read (i.e. "callback hell").</li> + <li>Failure callbacks need to be called once for each level of nesting, whereas with promises you can just use a single <code>.catch()</code> block to handle the errors for the entire chain.</li> + <li>Async callbacks just aren't very graceful.</li> + <li>Promise callbacks are always called in the strict order they are placed in the event queue; async callbacks aren't.</li> + <li>Async callbacks lose full control of how the function will be executed when passed to a third-party library.</li> +</ul> + +<h3 id="Browser_compatibility">Browser compatibility</h3> + +<p>Really good general support, although the exact support for callbacks in APIs depends on the particular API. Refer to the reference documentation for the API you're using for more specific support info.</p> + +<h3 id="Further_information">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a>, in particular <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing#Async_callbacks">Async callbacks</a></li> +</ul> + +<h2 id="setTimeout">setTimeout()</h2> + +<p><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> is a method that allows you to run a function after an arbitrary amount of time has passed.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>Yes</td> + <td>Yes (recursive timeouts)</td> + <td>Yes (nested timeouts)</td> + <td>No</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_2">Code example</h3> + +<p>Here the browser will wait two seconds before executing the anonymous function, then will display the alert message (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">see it running live</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">see the source code</a>):</p> + +<pre class="brush: js notranslate">let myGreeting = setTimeout(function() { + alert('Hello, Mr. Universe!'); +}, 2000)</pre> + +<h3 id="Pitfalls_2">Pitfalls</h3> + +<p>You can use recursive <code>setTimeout()</code> calls to run a function repeatedly in a similar fashion to <code>setInterval()</code>, using code like this:</p> + +<pre class="brush: js notranslate">let i = 1; +setTimeout(function run() { + console.log(i); + i++; + + setTimeout(run, 100); +}, 100);</pre> + +<p>There is a difference between recursive <code>setTimeout()</code> and <code>setInterval()</code>:</p> + +<ul> + <li>Recursive <code>setTimeout()</code> guarantees at least the specified amount of time (100ms in this example) will elapse between the executions; the code will run and then wait 100 milliseconds before it runs again. The interval will be the same regardless of how long the code takes to run.</li> + <li>With <code>setInterval()</code>, the interval we choose <em>includes</em> the time taken to execute the code we want to run in. Let's say that the code takes 40 milliseconds to run — the interval then ends up being only 60 milliseconds.</li> +</ul> + +<p>When your code has the potential to take longer to run than the time interval you’ve assigned, it’s better to use recursive <code>setTimeout()</code> — this will keep the time interval constant between executions regardless of how long the code takes to execute, and you won't get errors.</p> + +<h3 id="Browser_compatibility_2">Browser compatibility</h3> + +<p>{{Compat("api.WindowOrWorkerGlobalScope.setTimeout")}}</p> + +<h3 id="Further_information_2">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a>, in particular <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#setTimeout()">setTimeout()</a></li> + <li><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout() reference</a></li> +</ul> + +<h2 id="setInterval">setInterval()</h2> + +<p><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></code> is a method that allows you to run a function repeatedly with a set interval of time between each execution. Not as efficient as <code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code>, but allows you to choose a running rate/frame rate.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>Yes</td> + <td>No (unless it is the same one)</td> + <td>No</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_3">Code example</h3> + +<p>The following function creates a new <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date">Date()</a></code> object, extracts a time string out of it using <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString">toLocaleTimeString()</a></code>, and then displays it in the UI. We then run it once per second using <code>setInterval()</code>, creating the effect of a digital clock that updates once per second (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">see this live</a>, and also <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">see the source</a>):</p> + +<pre class="brush: js notranslate">function displayTime() { + let date = new Date(); + let time = date.toLocaleTimeString(); + document.getElementById('demo').textContent = time; +} + +const createClock = setInterval(displayTime, 1000);</pre> + +<h3 id="Pitfalls_3">Pitfalls</h3> + +<ul> + <li>The frame rate isn't optimized for the system the animation is running on, and can be somewhat inefficient. Unless you need to choose a specific (slower) framerate, it is generally better to use <code>requestAnimationFrame()</code>.</li> +</ul> + +<h3 id="Browser_compatibility_3">Browser compatibility</h3> + +<p>{{Compat("api.WindowOrWorkerGlobalScope.setInterval")}}</p> + +<h3 id="Further_information_3">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a>, in particular <a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></li> + <li><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval() reference</a></li> +</ul> + +<h2 id="requestAnimationFrame">requestAnimationFrame()</h2> + +<p><code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code> is a method that allows you to run a function repeatedly, and efficiently, at the best framerate available given the current browser/system. You should, if at all possible, use this instead of <code>setInterval()</code>/recursive <code>setTimeout()</code>, unless you need a specific framerate.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>Yes</td> + <td>No (unless it is the same one)</td> + <td>No</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_4">Code example</h3> + +<p>A simple animated spinner; you can find this <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">example live on GitHub</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">source code</a> also):</p> + +<pre class="brush: js notranslate">const spinner = document.querySelector('div'); +let rotateCount = 0; +let startTime = null; +let rAF; + +function draw(timestamp) { + if(!startTime) { + startTime = timestamp; + } + + rotateCount = (timestamp - startTime) / 3; + + if(rotateCount > 359) { + rotateCount %= 360; + } + + spinner.style.transform = 'rotate(' + rotateCount + 'deg)'; + + rAF = requestAnimationFrame(draw); +} + +draw();</pre> + +<h3 id="Pitfalls_4">Pitfalls</h3> + +<ul> + <li>You can't choose a specific framerate with <code>requestAnimationFrame()</code>. If you need to run your animation at a slower framerate, you'll need to use <code>setInterval()</code> or recursive <code>setTimeout()</code>.</li> +</ul> + +<h3 id="Browser_compatibility_4">Browser compatibility</h3> + +<p>{{Compat("api.Window.requestAnimationFrame")}}</p> + +<h3 id="Further_information_4">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a>, in particular <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals#requestAnimationFrame()">requestAnimationFrame()</a></li> + <li><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame() reference</a></li> +</ul> + +<h2 id="Promises">Promises</h2> + +<p><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a> are a JavaScript feature that allows you to run asynchronous operations and wait until it is definitely complete before running another operation based on its result. Promises are the backbone of modern asynchronous JavaScript.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>No</td> + <td>Yes</td> + <td>See <code>Promise.all()</code>, below</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_5">Code example</h3> + +<p>The following code fetches an image from the server and displays it inside an {{htmlelement("img")}} element; <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/simple-fetch-chained.html">see it live also</a>, and see also <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch-chained.html">the source code</a>:</p> + +<pre class="brush: js notranslate">fetch('coffee.jpg') +.then(response => response.blob()) +.then(myBlob => { + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}) +.catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); +});</pre> + +<h3 id="Pitfalls_5">Pitfalls</h3> + +<p>Promise chains can be complex and hard to parse. If you nest a number of promises, you can end up with similar troubles to callback hell. For example:</p> + +<pre class="brush: js notranslate">remotedb.allDocs({ + include_docs: true, + attachments: true +}).then(function (result) { + let docs = result.rows; + docs.forEach(function(element) { + localdb.put(element.doc).then(function(response) { + alert("Pulled doc with id " + element.doc._id + " and added to local db."); + }).catch(function (err) { + if (err.name == 'conflict') { + localdb.get(element.doc._id).then(function (resp) { + localdb.remove(resp._id, resp._rev).then(function (resp) { +// et cetera...</pre> + +<p>It is better to use the chaining power of promises to go with a flatter, easier to parse structure:</p> + +<pre class="brush: js notranslate">remotedb.allDocs(...).then(function (resultOfAllDocs) { + return localdb.put(...); +}).then(function (resultOfPut) { + return localdb.get(...); +}).then(function (resultOfGet) { + return localdb.put(...); +}).catch(function (err) { + console.log(err); +});</pre> + +<p>or even:</p> + +<pre class="brush: js notranslate">remotedb.allDocs(...) +.then(resultOfAllDocs => { + return localdb.put(...); +}) +.then(resultOfPut => { + return localdb.get(...); +}) +.then(resultOfGet => { + return localdb.put(...); +}) +.catch(err => console.log(err));</pre> + +<p>That covers a lot of the basics. For a much more complete treatment, see the excellent <a href="https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">We have a problem with promises</a>, by Nolan Lawson.</p> + +<h3 id="Browser_compatibility_5">Browser compatibility</h3> + +<p>{{Compat("javascript.builtins.Promise")}}</p> + +<h3 id="Further_information_5">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Using_promises">Using promises</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise reference</a></li> +</ul> + +<h2 id="Promise.all">Promise.all()</h2> + +<p>A JavaScript feature that allows you to wait for multiple promises to complete before then running a further operation based on the results of all the other promises.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>No</td> + <td>No</td> + <td>Yes</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_6">Code example</h3> + +<p>The following example fetches several resources from the server, and uses <code>Promise.all()</code> to wait for all of them to be available before then displaying all of them — <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-all.html">see it live</a>, and see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html">source code</a>:</p> + +<pre class="brush: js notranslate">function fetchAndDecode(url, type) { + // Returning the top level promise, so the result of the entire chain is returned out of the function + return fetch(url).then(response => { + // Depending on what type of file is being fetched, use the relevant function to decode its contents + if(type === 'blob') { + return response.blob(); + } else if(type === 'text') { + return response.text(); + } + }) + .catch(e => { + console.log(`There has been a problem with your fetch operation for resource "${url}": ` + e.message); + }); +} + +// Call the fetchAndDecode() method to fetch the images and the text, and store their promises in variables +let coffee = fetchAndDecode('coffee.jpg', 'blob'); +let tea = fetchAndDecode('tea.jpg', 'blob'); +let description = fetchAndDecode('description.txt', 'text'); + +// Use Promise.all() to run code only when all three function calls have resolved +Promise.all([coffee, tea, description]).then(values => { + console.log(values); + // Store each value returned from the promises in separate variables; create object URLs from the blobs + let objectURL1 = URL.createObjectURL(values[0]); + let objectURL2 = URL.createObjectURL(values[1]); + let descText = values[2]; + + // Display the images in <img> elements + let image1 = document.createElement('img'); + let image2 = document.createElement('img'); + image1.src = objectURL1; + image2.src = objectURL2; + document.body.appendChild(image1); + document.body.appendChild(image2); + + // Display the text in a paragraph + let para = document.createElement('p'); + para.textContent = descText; + document.body.appendChild(para); +});</pre> + +<h3 id="Pitfalls_6">Pitfalls</h3> + +<ul> + <li>If a <code>Promise.all()</code> rejects, then one or more of the promises you are feeding into it inside its array parameter must be rejecting, or might not be returning promises at all. You need to check each one to see what they returned. </li> +</ul> + +<h3 id="Browser_compatibility_6">Browser compatibility</h3> + +<p>{{Compat("javascript.builtins.Promise.all")}}</p> + +<h3 id="Further_information_6">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises#Running_code_in_response_to_multiple_promises_fulfilling">Running code in response to multiple promises fulfilling</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all">Promise.all() reference</a></li> +</ul> + +<h2 id="Asyncawait">Async/await</h2> + +<p>Syntactic sugar built on top of promises that allows you to run asynchronous operations using syntax that's more like writing synchronous callback code.</p> + +<table class="standard-table"> + <caption>Useful for...</caption> + <thead> + <tr> + <th scope="col">Single delayed operation</th> + <th scope="col">Repeating operation</th> + <th scope="col">Multiple sequential operations</th> + <th scope="col">Multiple simultaneous operations</th> + </tr> + <tr> + <td>No</td> + <td>No</td> + <td>Yes</td> + <td>Yes (in combination with <code>Promise.all()</code>)</td> + </tr> + </thead> +</table> + +<h3 id="Code_example_7">Code example</h3> + +<p>The following example is a refactor of the simple promise example we saw earlier that fetches and displays an image, written using async/await (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-refactored-fetch.html">see it live</a>, and see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-refactored-fetch.html">source code</a>):</p> + +<pre class="brush: js notranslate">async function myFetch() { + let response = await fetch('coffee.jpg'); + let myBlob = await response.blob(); + + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +} + +myFetch();</pre> + +<h3 id="Pitfalls_7">Pitfalls</h3> + +<ul> + <li>You can't use the <code>await</code> operator inside a non-<code>async</code> function, or in the top level context of your code. This can sometimes result in an extra function wrapper needing to be created, which can be slightly frustrating in some circumstances. But it is worth it most of the time.</li> + <li>Browser support for async/await is not as good as that for promises. If you want to use async/await but are concerned about older browser support, you could consider using the <a href="https://babeljs.io/">BabelJS</a> library — this allows you to write your applications using the latest JavaScript and let Babel figure out what changes if any are needed for your user’s browsers.</li> +</ul> + +<h3 id="Browser_compatibility_7">Browser compatibility</h3> + +<p>{{Compat("javascript.statements.async_function")}}</p> + +<h3 id="Further_information_7">Further information</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/async_function">Async function reference</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/await">Await operator reference</a></li> +</ul> + +<p>{{PreviousMenu("Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/asynchronous/index.html b/files/pt-br/learn/javascript/asynchronous/index.html new file mode 100644 index 0000000000..67c3f8e466 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/index.html @@ -0,0 +1,67 @@ +--- +title: JavaScript Assíncrono +slug: Learn/JavaScript/Asynchronous +tags: + - Beginner + - CodingScripting + - Guide + - Guía + - Iniciante + - JavaScript + - Landing + - NeedsTranslation + - Promises + - TopicStub + - async + - asynchronous + - await + - callbacks + - requestAnimationFrame + - setInterval + - setTimeout +translation_of: Learn/JavaScript/Asynchronous +--- +<div>{{LearnSidebar}}</div> + + + +<div><span class="seoSummary">Neste módulo vamos entender {{Glossary("JavaScript")}} <a href="/pt-BR/docs/Glossario/Assincrono">Assíncrono</a></span><span class="seoSummary">, porque isso é importante e como pode ser usado para lidar com operações potencialmente bloqueantes, como a busca de recursos em um servidor remoto.</span></div> + +<h2 id="Pre_requisitos">Pre requisitos</h2> + +<p>Javascript Assíncrono é um tópico razoavelmente avançado e é aconselhada a leitura dos módulos <a href="/pt-BR/docs/Learn/JavaScript/First_steps">Primeiros Passos com Javascript</a> e <a href="/pt-BR/docs/Aprender/JavaScript/Elementos_construtivos">Elementos construtivos do Javascript</a> antes de continuar.</p> + +<p>Se você não estiver familiarizado com os conceitos de programação assíncrona, a sugestão é iniciar com o artigo <a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Conceitos">Conceitos gerais da programação assíncrona</a> desse módulo. Caso contrário, você pode provavelmente pular para o módulo <a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Introdu%C3%A7%C3%A3o">Introdução ao Javascript Assíncrono</a>.</p> + +<div class="note"> +<p><strong>Note</strong>: Se você está estudando a partir de um computador/tablet/ outro dispositivo onde não é capaz de criar seus próprios arquivos, é possível executar os códigos de exemplo (a maioria deles) em plataformas como <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guias">Guias</h2> + +<dl> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Conceitos">Conceitos gerais da programação assíncrona</a></dt> + <dd> + <p>Nesse artigo vamos explorar um número de conceitos importantes relacionados à programação assíncrona e como aparece nos browsers Web. Você deve entender estes conceitos antes de seguir adiante através dos outros artigos neste módulo.</p> + </dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Introdu%C3%A7%C3%A3o">Introdução ao Javascript Assíncrono</a></dt> + <dd>Nesse artigo vamos recapitular brevemente os problemas associados ao Javascript síncrono e introduzir algumas das diferentes técnicas do Javascript assícrono que irá encontrar mais a frente, mostrando como essas técnicas podem nos ajudar a resolver tais problemas.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Javascript assícrono cooperativo: Timeouts e intervalos</a></dt> + <dd>Aqui contemplamos os métodos tradicionais que o Javascript possui disponível para executar código de forma assíncrona após decorrido um certo periodo de tempo ou em um intervalo regular (e.g. um determinado número de vezes por segundo), discutir sua utilidade e perceber alguns problemas inerentes a eles.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Promises">Manipulando elegantemente operações assíncronas com Promises</a></dt> + <dd>Promises são um novo recurso da linguagem Javascript que permitem adiar ações até que a ação anterior esteja concluída ou responder com falha. Isso é extremamente útil para montar uma sequência de operações para que funcione corretamente. Este artigo lhe orienta como as Promises funcionam, onde verá elas sendo utilizadas em <a href="/pt-BR/docs/WebAPI">WebAPIs</a>. Também aprenderá como escrever suas próprias promises.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Facilitando a programação assícrona com async e await</a></dt> + <dd>Promises podem ser um pouco complexas de construir e entender. Por esse motivo, os navegadores modernos implementado funções <code>async</code> e o operador <code>await.</code> O primeiro permite que funções padrão se comportem implicitamente de forma assíncrona com promises, enquanto que o último pode ser usado dentro de funções <code>async</code> para esperar por 'promessas' antes que a função continue. Isso faz com que o encadeamento de 'promessas' seja mais fácil de ler.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/Asynchronous/Escolhendo_abordagem_correta">Escolhendo a abordagem correta</a></dt> + <dd>Para concluir este módulo, vamos considerar as diferentes técnicas de programação e as features que abordamos do começo ao fim, considerando quais e quando utilizar, com recomendações e advertências das armadilhas mais comuns.</dd> +</dl> + +<h2 id="Veja_Também">Veja Também</h2> + +<ul> + <li><a href="https://eloquentjavascript.net/11_async.html">Programação Assícrona</a> do livro online <a href="https://eloquentjavascript.net/">Eloquent JavaScript</a>, por Marijn Haverbeke.</li> +</ul> + +<div class="note"> +<p><strong>Nota do tradutor</strong>: A segunda edição do <em>Eloquent Javascript</em> foi traduzida pela comunidade brasileira do Javascript e está disponível em <a href="https://github.com/braziljs/eloquente-javascript">Javascript Eloquente - 2ª Edição</a>. Até o momento da tradução deste artigo, a comunidade está trabalhando na conclusão da 3ª edição.</p> +</div> diff --git a/files/pt-br/learn/javascript/asynchronous/introdução/index.html b/files/pt-br/learn/javascript/asynchronous/introdução/index.html new file mode 100644 index 0000000000..b95a88d35c --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/introdução/index.html @@ -0,0 +1,283 @@ +--- +title: Introdução ao JavaScript Async +slug: Learn/JavaScript/Asynchronous/Introdução +translation_of: Learn/JavaScript/Asynchronous/Introducing +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}</div> + +<div>Neste artigo nós recapitulamos brevemente os problemas que são associados com o JavaScript síncrono, e dar uma primeira olhada em algumas das diferentes técnicas assíncronas que você vai encontrar, mostrando como elas podem nos ajudar a resolver tais problemas.</div> + +<div></div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimentos básicos de informática e sobre os fundamentos do JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ganhar familiaridade com o que é o Js assíncrono e como ele se difere do Js síncrono.</td> + </tr> + </tbody> +</table> + +<h2 id="JavaScript_síncrono">JavaScript síncrono</h2> + +<p>Para entendermos o que é o <strong>{{Glossary("asynchronous")}}</strong> JavaScript, nós primeiro temos que ter certeza que entedemos o que é o <strong>{{Glossary("synchronous")}}</strong> JavaScript. Essa seção revê um pouco das informações que nós vimos no artigo anterior.</p> + +<p>Muitas das funcionalidades que nós vimos em áreas anteriores são síncronas — você executa um código, e o reultado é retornado assim que o navegador puder. Vamos ver um exemplo simples (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/basic-function.html">veja aqui</a>, e <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/basic-function.html">veja o código fonte</a>):</p> + +<pre class="brush: js">const btn = document.querySelector('button'); +btn.addEventListener('click', () => { + alert('Você clicou em mim!'); + + let pElem = document.createElement('p'); + pElem.textContent = 'Este é um novo parágrafo adicionado'; + document.body.appendChild(pElem); +}); +</pre> + +<p>Neste bloco, as linhas são executadas uma após a outra:</p> + +<ol> + <li>Nós damos referência à um elemento {{htmlelement("button")}} que já está disponível na DOM.</li> + <li>Nós adicionamos um evento de <code><a href="/en-US/docs/Web/API/Element/click_event">click</a></code>, e quando ele for clicado ele fará o seguinte: + <ol> + <li>Mostrar uma mensagem no <code><a href="/en-US/docs/Web/API/Window/alert">alert()</a></code>.</li> + <li>Uma vez que o alert for dispensado, nós criamos um elemento {{htmlelement("p")}}.</li> + <li>Depois nós o preenchemos com um texto.</li> + <li>E finalmente, o adicionamos no body.</li> + </ol> + </li> +</ol> + +<p>Enquanro cada operação é processada, nada mais pode acontecer — a renderização é pausada. Isso acontece porque o JavaScript opera em uma única thread (<a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts#JavaScript_is_single_threaded">JavaScript é single threaded</a>). Apenas uma coisa pode acontecer por vez, em uma única thread principal, e tudo é bloqueado até que a operação seja concluída.</p> + +<p>Então, no exemplo acima, depois que você tenha clicado no botão, o parágrafo não vai aparecer até que o botão OK do alert seja pressionado. Tente isso com o botão a seguir:</p> + +<div class="hidden"> +<pre class="brush: html"><<span class="pl-ent">button</span>>Clique em mim</<span class="pl-ent">button</span>></pre> +</div> + +<p>{{EmbedLiveSample('Synchronous_JavaScript', '100%', '70px')}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: É importante lembrar que, mesmo sendo muito útil para demonstar uma situação de blocking, o <code><a href="/en-US/docs/Web/API/Window/alert">alert()</a></code> não é de bom uso em aplicativos reais.</p> +</div> + +<h2 id="Asynchronous_JavaScript">Asynchronous JavaScript</h2> + +<p>Por razões esclarecidas anteriormente (e.g. relativas ao blocking), muitas funcionalidades de APIs da Web agora usam código assíncrono na execução, especialmente aquelas que acessam ou buscam algum tipo de recurso de um dispositivo externo, como pegar um arquivo da rede, acessar um banco de dados e retornar dados dele, acessar uma stream de uma web cam, ou transmitir uma tela para um dispositivo VR.</p> + +<p>Por que é tão difícil trabalhar com isso usando códigos síncronos? Vamos dar uma olhada em um exemplo rápido. Quando você pega uma imagem de um servidor, você não pode retornar o resultado imediatamente. Isso significa que o pseudocódigo a seguir não poderia funcionar:</p> + +<pre class="brush: js">let resposta = fetch('myImage.png'); +let blob = resposta.blob(); +// Mostra sua imagem na UI</pre> + +<p>Isso acontece por que você não sabe quanto tempo a imagem levará para ser baixada, então quando você executar a segunda linha, ela vai resultar em um erro (provalvelmente sempre) porque a <code>resposta</code> não estará disponível ainda. Você precisa que o seu código espere até que a <code>resposta</code> seja retornada antes de fazer algo com ela.</p> + +<p>Existem dois tipos principais de estilo de código assíncrono que você encontrará no código JavaScript, as callbacks com um estilo old-school e código em um estilo das promises mais recente. Nas seções abaixo, revisaremos cada um deles por vez.</p> + +<h2 id="Callbacks_assíncronas">Callbacks assíncronas</h2> + +<p>Callback são funções que são passada como parâmetros na chamada de outra função que vai executar código por trás do panos. Quando esse código por trás dos panos terminar de ser executado, a função callback será chamada para te informar que a tarefa foi finalizada ou que algo do seu interesse aconteceu. O uso das callbacks é um pouco antiquado agora, mas você ainda pode vê-las em um número de APIs comumente usadas.</p> + +<p>Um exemplo de uma callback async é o segundo parâmetro do método {{domxref("EventTarget.addEventListener", "addEventListener()")}} (como vimos em ação anteriormente):</p> + +<pre class="brush: js">btn.addEventListener('click', () => { + alert('Você clicou em mim!'); + + let pElem = document.createElement('p'); + pElem.textContent = 'Este é um novo parágrafo.'; + document.body.appendChild(pElem); +});</pre> + +<p>O primeiro parâmetro é o tipo de evento a ser executado e o segundo parâmetro é uma função callback que é chamada quando o evento é disparado.</p> + +<p>Quando passamos uma função callback como um parâmetro em outra função, nós apenas estamos passando a rêferencia da função como argumento, ou seja, a função callback <strong>não</strong><strong> é</strong> executada imediatamente. Ela é chamada de volta assíncronamente dentro do corpo da função que a contém, que é responsável por executar a função callback quando for necessário.</p> + +<p>Você pode escrever a sua própria função que contém uma callback facilmente. Vamos dar uma olhada em outro exemplo que carrega uma arquivo usando a <a href="/en-US/docs/Web/API/XMLHttpRequest">API <code>XMLHttpRequest</code> </a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/xhr-async-callback.html">veja aqui</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/xhr-async-callback.html">veja o código fonte</a>):</p> + +<pre class="brush: js">function loadAsset(url, type, callback) { + let xhr = new XMLHttpRequest(); + xhr.open('GET', url); + xhr.responseType = type; + + xhr.onload = function() { + callback(xhr.response); + }; + + xhr.send(); +} + +function displayImage(blob) { + let objectURL = URL.createObjectURL(blob); + + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +} + +loadAsset('coffee.jpg', 'blob', displayImage);</pre> + +<p>Aqui nós criamos uma função <code>displayImage()</code> que simplesmente representa um blob que foi passada à ela como uma URL de objeto, e depois cria uma imagem para mostrar a URL, adicionando-a ao <code><body></code> do documento. Entretando, nós criamos depois uma função <code>loadAsset()</code> que pega uma callback como parâmetro, junto com uma URL a ser buscada e um tipo para o conteúdo. Ela usa o <code>XMLHttpRequest</code> (abreviação: "XHR") para buscar o recurso na URL dada, para depois passar a resposta para a callback para fazer algo com isso. Neste caso a callback está esperando o XHR terminar de baixar o recurso (usando o manipulador de eventos <code><a href="/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>) antes de passá-lo para a callback.</p> + +<p>Callback são versáteis — elas não apenas lhe permitem controlar a ordem em que as funções são executadas e quais dados são passados entre elas, elas também podem passar dados para diferentes funçoes dependendo das circunstâncias. Então você pode ter ações diferentes para executar na resposta baixada, como <code>processJSON()</code>, <code>displayText()</code>, etc.</p> + +<p>Note que nem todas as callback são assíncronas — algumas são executadas de um modo síncrono. Um exemplo é quando nós usamos o método {{jsxref("Array.prototype.forEach()")}} para iterar sobre os itens de uma array (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/foreach.html">veja aqui</a>, e a <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/foreach.html">fonte</a>):</p> + +<pre class="brush: js">const gods = ['Apollo', 'Artemis', 'Ares', 'Zeus']; + +gods.forEach(function (eachName, index){ + console.log(index + '. ' + eachName); +});</pre> + +<p>Neste exemplo nós iteramos sobra uma array de Deuses Gregos e imprimos o índice e seus valores no console. O parâmetro de <code>forEach()</code> é uma callback function, que por si só toma dois parâmetros: uma refêrencia ao nome da array e e os valores dos índices. Entretanto, ela não espera por algo para fazer a execução, pois isso acontece imediatamente</p> + +<h2 id="Promises">Promises</h2> + +<p>Promises são uma nova maneira de escrever código assíncrono que você verá em APIs Web modernas. Um bom exemplo disso é a API <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch">fetch()</a></code>, que é basicamente uma versão mais moderna e eficiente de {{domxref("XMLHttpRequest")}}. Vamos dar uma olhada em um exemplo rápido, do nosso artigo de <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Pegando dados do servidor</a>:</p> + +<pre class="brush: js">fetch('products.json').then(function(response) { + return response.json(); +}).then(function(json) { + products = json; + initialize(); +}).catch(function(err) { + console.log('Fetch problem: ' + err.message); +});</pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Você pode encontrar a versão finalizada no GitHub (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store-xhr/can-script.js">veja aqui</a>, e também <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store-xhr/">seja a execução</a>).</p> +</div> + +<p>Aqui nós vemos <code>fetch</code><code>()</code> pegando um único parâmetro — a URL de um recurso que você quer pegar da rede — e retornando uma <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</a>. A promise é um objeto que representa a conclusão ou falha da operação assíncrona. Ela represente um estado intermediário, por assim dizer. É praticamente o jetio do navegador de dizer "Eu prometo voltar para você com a resposta o mais rápido possível", daí o nome "promessa".</p> + +<p>Você pode levar um tempo para se acostumar com esse conceito; Ele se parece um pouco com o {{interwiki("wikipedia", "Gato de Schrödinger")}} em ação. Nenhum dos possíveis resultados aconteceu ainda, então a operação fetch está esperando pelo resultado do navegador que vai completar a operação em algum ponto no futuro.</p> + +<p>Nós temos três blocos de código encadeados ao fim do <code>fetch()</code>:</p> + +<ul> + <li>Dois blocos <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then()</a></code>. Ambos contém uma função callback que será executada se a operação anterior for executada, então você pode fazer algo com o resultado. Cada bloco <code>.then()</code> retorna outra promise, o que significa que você pode encadear múltiplos blocos <code>.then()</code> um ao outro, para que múltiplas operações assíncronas possam ser executadas uma atrás da outra.</li> + <li>O bloco <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch">catch()</a></code> no final será executado em casos em que erros ocorrem quando um dos <code>.then()</code> falhe — de um modo similar aos blocos <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> síncronos, um objeto de erro fica disponível dentro do <code>catch()</code>, e pode ser usado para reportar erros que ocorreram. Note que o bloco <code>try...catch</code> não funcionará com promises, embora funcione com <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">async/await</a>, como você aprenderá mais adiante.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Você vai aprender mais sobre promises mais tarde no módulo, então não se preocupe se você não entendeu muito bem.</p> +</div> + +<h3 id="A_fila_de_eventos">A fila de eventos</h3> + +<p>Operações assíncronas como as promises são colocadas em uma <strong>fila de eventos</strong>, que é executada depois que a main thread terminar de ser processada. As operações serão completadas assim que for possível e depois retornam seus resultados para o ambiente JavaScript.</p> + +<h3 id="Promises_versus_callbacks">Promises versus callbacks</h3> + +<p>As promises tem algumas semelhanças com as callbacks. Elas são basicamente um objeto retornado em que você vincula funções callback, ao invés de passar as callbacks para uma função.</p> + +<p>Entretanto, as promises são feitas especificamente para lidarmos com operações async, e ter muitas vantagens sobre as velhas callbacks:</p> + +<ul> + <li>Você pode encadear múltiplas operações assíncronas usando múltiplos blocos <code>.then()</code>, passando o resultado de uma delas como o resultado como parâmetro da próxima operação. Isso é muito mais difícil de se fazer usando as callback, que normalmente termina em algo chamado de <a href="http://callbackhell.com/">callback hell</a>.</li> + <li>As callbacks das promises sempre são chamadas na ordem estrita em quesão colocadas na fila de eventos.</li> + <li>O tratamento de erros é muito melhor — todos os erros são tratados por um único bloco <code>.catch()</code> no final do encadeamento, ao invés de ser tratado individualmente em cada função callback.</li> + <li>Promessas evitam inversão de controle. Ao contrário das callbacks, que perdem totalmente o controle de como a função será executada quando passada para uma biblioteca de terceiros.</li> +</ul> + +<h2 id="A_natureza_do_código_assíncrono">A natureza do código assíncrono</h2> + +<p>Vamos explorar um exemplo que ilustra a natureza do código assíncrono, mostrando o que pode acontecer quando nós não estamos cientes da ordem de execução e dos problemas em tentar tratar código async como código síncrono. O exemplo a seguir é muito similar ao que vimos antes (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync.html">veja aqui</a>, e <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">a fonte</a>). Uma diferença e que nós icluimos um número de declarações {{domxref("console.log()")}} para ilustrar na ordem que você pensa que o código fosse executado.</p> + +<pre class="brush: js">console.log ('Starting'); +let image; + +fetch('coffee.jpg').then((response) => { + console.log('It worked :)') + return response.blob(); +}).then((myBlob) => { + let objectURL = URL.createObjectURL(myBlob); + image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}).catch((error) => { + console.log('There has been a problem with your fetch operation: ' + error.message); +}); + +console.log ('All done!');</pre> + +<p>O navegador vai começar a executar o código, veja a primeira declaração <code>console.log()</code>(<code>Starting</code>) e a execute, e depois crie a variável <code>image</code>.</p> + +<p>Depois a segunda linha vai começar a ser executada começando com o bloco <code>fetch()</code>, mas desde que <code>fetch()</code> é executado assíncronamente sem bloquear nada, a execução do código continua mesmo depois do código promise, alcançando a última declaração <code>console.log()</code>(<code>All done!</code>) e imprimindo a no console.</p> + +<p>Uma vez que o bloco <code>fetch()</code> tenha terminado a sua execução e retornado seu resultado com os blocos <code>.then()</code>, nós finalmente veremos a segunda mensagem <code>console.log()</code> (<code>It worked :)</code>) appear. Então as mensagens aparecem nessa ordem:</p> + +<ul> + <li>Starting</li> + <li>All done!</li> + <li>It worked :)</li> +</ul> + +<p>Se isso te deixa confuso, então considere o exemplo a seguir:</p> + +<pre class="brush: js">console.log("registering click handler"); + +button.addEventListener('click', () => { + console.log("get click"); +}); + +console.log("all done");</pre> + +<p>Isso é bem similar no comportamento — a primeira e a terceira mensagens <code>console.log()</code> são mostradas imediatamente, mas a segunda está bloqueada até alguém clique no botão. O exemplo anterior funciona da mesma forma, exceto que no caso a segunda mensagem está bloqueada na promise pegando um recurso e depois o mostra na tela.</p> + +<p>Em um exemplo mais superficial, esse tipo de configuração poderia causar um problema — você não pode incluir um bloco async que retorna um resultado, que depois depende de um código síncrono. Você não pode garantir que a função async vai retornar antes que o navegador processou o bloco síncrono.</p> + +<p>Para ver isso em ação, tente fazer uma cópia local do <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync.html">nosso exemplo</a>, e mudar o terceiro <code>console.log()</code> para o seguinte:</p> + +<pre class="brush: js">console.log ('Tudo Feito! ' + image.src + 'mostrada.');</pre> + +<p>Agora você deve ter um erro no seu console ao invés da terceira mensagem:</p> + +<pre><span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body">TypeError: image is undefined; can't access its "src" property</span></span></span></pre> + +<p>Isso acontece porque o navegador tenta executar o terceiro <code>console.log()</code> e o bloco <code>fetch()</code> não terminou de ser executado e não foi dado um valor para a variável <code>image</code>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>:Por razões de segurança, você não pode usar o <code>fetch()</code> com arquivos do seu sistema local (ou executar operações localmente); para executar o exemplo acima você teria que rodá-lo em um <a href="/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server">servidor local</a>.</p> +</div> + +<h2 id="Aprendizado_ativo_faça_tudo_async!">Aprendizado ativo: faça tudo async!</h2> + +<p>Faça que o exemplo problemático de <code>fetch()</code> imprima três mensagens <code>console.log()</code> na tela na ordem desejada, você pode fazer a útima declaração <code>console.log()</code> assíncrona também. Isso pode ser feito colocando ela em outro bloco <code>.then()</code> encadeamo no final do segundo bloco, ou por simplesmente movê-lo para dentro do segundo bloco <code>then()</code>.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you get stuck, you can <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/async-sync-fixed.html">find an answer here</a> (see it <a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/async-sync-fixed.html">running live</a> also). You can also find a lot more information on promises in our <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a> guide, later on in the module.</p> +</div> + +<h2 id="Conclusion">Conclusion</h2> + +<p>In its most basic form, JavaScript is a synchronous, blocking, single-threaded language, in which only one operation can be in progress at a time. But web browsers define functions and APIs that allow us to register functions that should not be executed synchronously, and should instead be invoked asynchronously when some kind of event occurs (the passage of time, the user's interaction with the mouse, or the arrival of data over the network, for example). This means that you can let your code do several things at the same time without stopping or blocking your main thread.</p> + +<p>Whether we want to run code synchronously or asynchronously will depend on what we're trying to do.</p> + +<p>There are times when we want things to load and happen right away. For example when applying some user-defined styles to a webpage you'll want the styles to be applied as soon as possible.</p> + +<p>If we're running an operation that takes time however, like querying a database and using the results to populate templates, it is better to push this off the main thread and complete the task asynchronously. Over time, you'll learn when it makes more sense to choose an asynchronous technique over a synchronous one.</p> + +<ul> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Concepts", "Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/asynchronous/promises/index.html b/files/pt-br/learn/javascript/asynchronous/promises/index.html new file mode 100644 index 0000000000..1fdd746d9d --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/promises/index.html @@ -0,0 +1,586 @@ +--- +title: Programação elegante com Promises +slug: Learn/JavaScript/Asynchronous/Promises +translation_of: Learn/JavaScript/Asynchronous/Promises +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</div> + +<p class="summary"><strong>Promises </strong>são uma nova implementação do JavaScript que permite você adiar ações até que determinada ação finalize. Isso é realmente bastante útil para uma sequência de operações assíncronas trabalharem corretamente. Neste artigo irá mostrar para você como Promises trabalham, como elas são usadas em web APIs e como escrever a sua Promise.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conhecimentos básicos em informática, um básico entendimento do JavaScript e seus fundamentos.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender promises e como elas funcionam.</td> + </tr> + </tbody> +</table> + + + +<h2 id="O_que_são_promises">O que são promises?</h2> + +<p>Nós vimos apenas um resumo do que são <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a> até agora, a partir daqui iremos explorar mais a fundo sobre elas.</p> + +<p>Essencialmente, uma Promise é um objeto que representa um estado intermediário de uma operação — de fato, uma <em>promessa</em> que um resultado irá ser retornado em um ponto no futuro, mas isso não é garantia de que o resultado estará disponível, ou a promise falhará, o código será executado em ordem para fazer alguma coisa que o resultado seja sucesso, ou tratar uma falha.</p> + +<p>Generally you are less interested in the amount of time an async operation will take to return its result (unless of course it takes <em>far</em> too long!), and more interested in being able to respond to it being returned, whenever that is. And of course, it's nice that it doesn't block the rest of the code execution.</p> + +<p>One of the most common engagements you'll have with promises is with web APIs that return a promise. Let's consider a hypothetical video chat application. The application has a window with a list of the user's friends, and clicking on a button next to a user starts a video call to that user.</p> + +<p>That button's handler calls {{domxref("MediaDevices.getUserMedia", "getUserMedia()")}} in order to get access to the user's camera and microphone. Since <code>getUserMedia()</code> has to ensure that the user has permission to use those devices <em>and</em> ask the user which microphone to use and which camera to use (or whether to be a voice only call, among other possible options), it can block until not only all of those decisions are made, but also the camera and microphone have been engaged. In addition, the user may not respond immediately to these permission requests. This can potentially take a long time.</p> + +<p>Since the call to <code>getUserMedia()</code> is made from the browser's main thread, the entire browser is blocked until <code>getUserMedia()</code> returns! Obviously, that's not an acceptable option; without promises, everything in the browser becomes unusable until the user decides what to do about the camera and microphone. So instead of waiting for the user, getting the chosen devices enabled, and directly returning the {{domxref("MediaStream")}} for the stream created from the selected sources, <code>getUserMedia()</code> returns a {{jsxref("promise")}} which is resolved with the {{domxref("MediaStream")}} once it's available.</p> + +<p>The code that the video chat application would use might look something like this:</p> + +<pre class="brush: js notranslate">function handleCallButton(evt) { + setStatusMessage("Calling..."); + navigator.mediaDevices.getUserMedia({video: true, audio: true}) + .then(chatStream => { + selfViewElem.srcObject = chatStream; + chatStream.getTracks().forEach(track => myPeerConnection.addTrack(track, chatStream)); + setStatusMessage("Connected"); + }).catch(err => { + setStatusMessage("Failed to connect"); + }); +} +</pre> + +<p>This function starts by using a function called <code>setStatusMessage()</code> to update a status display with the message "Calling...", indicating that a call is being attempted. It then calls <code>getUserMedia()</code>, asking for a stream that has both video and audio tracks, then once that's been obtained, sets up a video element to show the stream coming from the camera as a "self view," then takes each of the stream's tracks and adds them to the <a href="/en-US/docs/Web/API/WebRTC_API">WebRTC</a> {{domxref("RTCPeerConnection")}} representing a connection to another user. After that, the status display is updated to say "Connected".</p> + +<p>If <code>getUserMedia()</code> fails, the <code>catch</code> block runs. This uses <code>setStatusMessage()</code> to update the status box to indicate that an error occurred.</p> + +<p>The important thing here is that the <code>getUserMedia()</code> call returns almost immediately, even if the camera stream hasn't been obtained yet. Even if the <code>handleCallButton()</code> function has already returned to the code that called it, when <code>getUserMedia()</code> has finished working, it calls the handler you provide. As long as the app doesn't assume that streaming has begun, it can just keep on running.</p> + +<div class="blockIndicator note"> +<p><strong>Note:</strong> You can learn more about this somewhat advanced topic, if you're interested, in the article <a href="/docs/Web/API/WebRTC_API/Signaling_and_video_calling">Signaling and video calling</a>. Code similar to this, but much more complete, is used in that example.</p> +</div> + +<h2 id="The_trouble_with_callbacks">The trouble with callbacks</h2> + +<p>To fully understand why promises are a good thing, it helps to think back to old-style callbacks, and to appreciate why they are problematic.</p> + +<p>Let's talk about ordering pizza as an analogy. There are certain steps that you have to take for your order to be successful, which don't really make sense to try to execute out of order, or in order but before each previous step has quite finished:</p> + +<ol> + <li>You choose what toppings you want. This can take a while if you are indecisive, and may fail if you just can't make up your mind, or decide to get a curry instead.</li> + <li>You then place your order. This can take a while to return a pizza, and may fail if the restaurant does not have the required ingredients to cook it.</li> + <li>You then collect your pizza and eat. This might fail if, say, you forgot your wallet so can't pay for the pizza!</li> +</ol> + +<p>With old-style <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing#Callbacks">callbacks</a>, a pseudo-code representation of the above functionality might look something like this:</p> + +<pre class="brush: js notranslate">chooseToppings(function(toppings) { + placeOrder(toppings, function(order) { + collectOrder(order, function(pizza) { + eatPizza(pizza); + }, failureCallback); + }, failureCallback); +}, failureCallback);</pre> + +<p>This is messy and hard to read (often referred to as "callback hell"), requires the <code>failureCallback()</code> to be called multiple times (once for each nested function), with other issues besides.</p> + +<h3 id="Improvements_with_promises">Improvements with promises</h3> + +<p>Promises make situations like the above much easier to write, parse, and run. If we represented the above pseudo-code using asynchronous promises instead, we'd end up with something like this:</p> + +<pre class="brush: js notranslate">chooseToppings() +.then(function(toppings) { + return placeOrder(toppings); +}) +.then(function(order) { + return collectOrder(order); +}) +.then(function(pizza) { + eatPizza(pizza); +}) +.catch(failureCallback);</pre> + +<p>This is much better — it is easier to see what is going on, we only need a single <code>.catch()</code> block to handle all the errors, it doesn't block the main thread (so we can keep playing video games while we wait for the pizza to be ready to collect), and each operation is guaranteed to wait for previous operations to complete before running. We're able to chain multiple asynchronous actions to occur one after another this way because each <code>.then()</code> block returns a new promise that resolves when the <code>.then()</code> block is done running. Clever, right?</p> + +<p>Using arrow functions, you can simplify the code even further:</p> + +<pre class="brush: js notranslate">chooseToppings() +.then(toppings => + placeOrder(toppings) +) +.then(order => + collectOrder(order) +) +.then(pizza => + eatPizza(pizza) +) +.catch(failureCallback);</pre> + +<p>Or even this:</p> + +<pre class="brush: js notranslate">chooseToppings() +.then(toppings => placeOrder(toppings)) +.then(order => collectOrder(order)) +.then(pizza => eatPizza(pizza)) +.catch(failureCallback);</pre> + +<p>This works because with arrow functions <code>() => x</code> is valid shorthand for <code>() => { return x; }</code>.</p> + +<p>You could even do this, since the functions just pass their arguments directly, so there isn't any need for that extra layer of functions:</p> + +<pre class="brush: js notranslate">chooseToppings().then(placeOrder).then(collectOrder).then(eatPizza).catch(failureCallback);</pre> + +<p>This is not quite as easy to read, however, and this syntax might not be usable if your blocks are more complex than what we've shown here.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can make further improvements with <code>async</code>/<code>await</code> syntax, which we'll dig into in the next article.</p> +</div> + +<p>At their most basic, promises are similar to event listeners, but with a few differences:</p> + +<ul> + <li>A promise can only succeed or fail once. It cannot succeed or fail twice and it cannot switch from success to failure or vice versa once the operation has completed.</li> + <li>If a promise has succeeded or failed and you later add a success/failure callback, the correct callback will be called, even though the event took place earlier.</li> +</ul> + +<h2 id="Explaining_basic_promise_syntax_A_real_example">Explaining basic promise syntax: A real example</h2> + +<p>Promises are important to understand because most modern Web APIs use them for functions that perform potentially lengthy tasks. To use modern web technologies you'll need to use promises. Later on in the chapter we'll look at how to write your own promise, but for now we'll look at some simple examples that you'll encounter in Web APIs.</p> + +<p>In the first example, we'll use the <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch">fetch()</a></code> method to fetch an image from the web, the {{domxref("Body.blob", "blob()")}} method to transform the fetch response's raw body contents into a {{domxref("Blob")}} object, and then display that blob inside an {{htmlelement("img")}} element. This is very similar to the example we looked at in the <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing#Asynchronous_JavaScript">first article of the series</a>, but we'll do it a bit differently as we get you building your own promise-based code.</p> + +<ol> + <li> + <p>First of all, download our <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">simple HTML template</a> and the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/coffee.jpg">sample image file</a> that we'll fetch.</p> + </li> + <li> + <p>Add a {{htmlelement("script")}} element at the bottom of the HTML {{htmlelement("body")}}.</p> + </li> + <li> + <p>Inside your {{HTMLElement("script")}} element, add the following line:</p> + + <pre class="brush: js notranslate">let promise = fetch('coffee.jpg');</pre> + + <p>This calls the <code>fetch()</code> method, passing it the URL of the image to fetch from the network as a parameter. This can also take an options object as a optional second parameter, but we are just using the simplest version for now. We are storing the promise object returned by <code>fetch()</code> inside a variable called <code>promise</code>. As we said before, this object represents an intermediate state that is initially neither success or failure — the official term for a promise in this state is <strong>pending</strong>.</p> + </li> + <li> + <p>To respond to the successful completion of the operation whenever that occurs (in this case, when a {{domxref("Response")}} is returned), we invoke the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">.then()</a></code> method of the promise object. The callback inside the <code>.then()</code> block (referred to as the <strong>executor</strong>) runs only when the promise call completes successfully and returns the {{domxref("Response")}} object — in promise-speak, when it has been <strong>fulfilled</strong>. It is passed the returned {{domxref("Response")}} object as a parameter.</p> + + <div class="blockIndicator note"> + <p><strong>Note</strong>: The way that a <code>.then()</code> block works is similar to when you add an event listener to an object using <code>AddEventListener()</code>. It doesn't run until an event occurs (when the promise fulfills). The most notable difference is that a .then() will only run once for each time it is used, whereas an event listener could be invoked multiple times.</p> + </div> + + <p>We immediately run the <code>blob()</code> method on this response to ensure that the response body is fully downloaded, and when it is available transform it into a <code>Blob</code> object that we can do something with. The result of this is returned like so:</p> + + <pre class="brush: js notranslate">response => response.blob()</pre> + + <p>which is shorthand for</p> + + <pre class="brush: js notranslate">function(response) { + return response.blob(); +}</pre> + + <p>OK, enough explanation for now. Add the following line below your first line of JavaScript.</p> + + <pre class="brush: js notranslate">let promise2 = promise.then(response => response.blob());</pre> + </li> + <li> + <p>Each call to <code>.then()</code> creates a new promise. This is very useful; because the <code>blob()</code> method also returns a promise, we can handle the <code>Blob</code> object it returns on fulfillment by invoking the <code>.then()</code> method of the second promise. Because we want to do something a bit more complex to the blob than just run a single method on it and return the result, we'll need to wrap the function body in curly braces this time (otherwise it'll throw an error).</p> + + <p>Add the following to the end of your code:</p> + + <pre class="brush: js notranslate">let promise3 = promise2.then(myBlob => { + +})</pre> + </li> + <li> + <p>Now let's fill in the body of the executor function. Add the following lines inside the curly braces:</p> + + <pre class="brush: js notranslate">let objectURL = URL.createObjectURL(myBlob); +let image = document.createElement('img'); +image.src = objectURL; +document.body.appendChild(image);</pre> + + <p>Here we are running the {{domxref("URL.createObjectURL()")}} method, passing it as a parameter the <code>Blob</code> returned when the second promise fulfills. This will return a URL pointing to the object. Then we create an {{htmlelement("img")}} element, set its <code>src</code> attribute to equal the object URL and append it to the DOM, so the image will display on the page!</p> + </li> +</ol> + +<p>If you save the HTML file you've just created and load it in your browser, you'll see that the image is displayed in the page as expected. Good work!</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You will probably notice that these examples are somewhat contrived. You could just do away with the whole <code>fetch()</code> and <code>blob()</code> chain, and just create an <code><img></code> element and set its <code>src</code> attribute value to the URL of the image file, <code>coffee.jpg</code>. We did however pick this example because it demonstrates promises in a nice simple fashion, rather than for its real world appropriateness.</p> +</div> + +<h3 id="Responding_to_failure">Responding to failure</h3> + +<p>There is something missing — currently there is nothing to explicitly handle errors if one of the promises fails (<strong>rejects</strong>, in promise-speak). We can add error handling by running the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch">.catch()</a></code> method of the previous promise. Add this now:</p> + +<pre class="brush: js notranslate">let errorCase = promise3.catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); +});</pre> + +<p>To see this in action, try misspelling the URL to the image and reloading the page. The error will be reported in the console of your browser's developer tools.</p> + +<p>This doesn't do much more than it would if you just didn't bother including the <code>.catch()</code> block at all, but think about it — this allows us to control error handling exactly how we want. In a real app, your <code>.catch()</code> block could retry fetching the image, or show a default image, or prompt the user to provide a different image URL, or whatever.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can see <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/simple-fetch.html">our version of the example live</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch.html">source code</a> also).</p> +</div> + +<h3 id="Chaining_the_blocks_together">Chaining the blocks together</h3> + +<p>This is a very longhand way of writing this out; we've deliberately done this to help you understand what is going on clearly. As shown earlier on in the article, you can chain together <code>.then()</code> blocks (and also <code>.catch()</code> blocks). The above code could also be written like this (see also <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/simple-fetch-chained.html">simple-fetch-chained.html</a> on GitHub):</p> + +<pre class="brush: js notranslate">fetch('coffee.jpg') +.then(response => response.blob()) +.then(myBlob => { + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}) +.catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); +});</pre> + +<p>Bear in mind that the value returned by a fulfilled promise becomes the parameter passed to the next <code>.then()</code> block's executor function.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: <code>.then()</code>/<code>.catch()</code> blocks in promises are basically the async equivalent of a <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> block in sync code. Bear in mind that synchronous <code>try...catch</code> won't work in async code.</p> +</div> + +<h2 id="Promise_terminology_recap">Promise terminology recap</h2> + +<p>There was a lot to cover in the above section, so let's go back over it quickly to give you a <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises#Promise_terminology_recap">short guide that you can bookmark</a> and use to refresh your memory in the future. You should also go over the above section again a few more time to make sure these concepts stick.</p> + +<ol> + <li>When a promise is created, it is neither in a success or failure state. It is said to be <strong>pending</strong>.</li> + <li>When a promise returns, it is said to be <strong>resolved</strong>. + <ol> + <li>A successfully resolved promise is said to be <strong>fulfilled</strong>. It returns a value, which can be accessed by chaining a <code>.then()</code> block onto the end of the promise chain. The executor function inside the <code>.then()</code> block will contain the promise's return value.</li> + <li>An unsuccessful resolved promise is said to be <strong>rejected</strong>. It returns a <strong>reason</strong>, an error message stating why the promise was rejected. This reason can be accessed by chaining a <code>.catch()</code> block onto the end of the promise chain.</li> + </ol> + </li> +</ol> + +<h2 id="Running_code_in_response_to_multiple_promises_fulfilling">Running code in response to multiple promises fulfilling</h2> + +<p>The above example showed us some of the real basics of using promises. Now let's look at some more advanced features. For a start, chaining processes to occur one after the other is all fine, but what if you want to run some code only after a whole bunch of promises have <em>all</em> fulfilled?</p> + +<p>You can do this with the ingeniously named <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all">Promise.all()</a></code> static method. This takes an array of promises as an input parameter and returns a new <code>Promise</code> object that will fulfill only if and when <em>all</em> promises in the array fulfill. It looks something like this:</p> + +<pre class="brush: js notranslate">Promise.all([a, b, c]).then(values => { + ... +});</pre> + +<p>If they all fulfill, then chained <code>.then()</code> block's executor function will be passed an array containing all those results as a parameter. If any of the promises passed to <code>Promise.all()</code> reject, the whole block will reject.</p> + +<p>This can be very useful. Imagine that we’re fetching information to dynamically populate a UI feature on our page with content. In many cases, it makes sense to receive all the data and only then show the complete content, rather than displaying partial information.</p> + +<p>Let's build another example to show this in action.</p> + +<ol> + <li> + <p>Download a fresh copy of our <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">page template</a>, and again put a <code><script></code> element just before the closing <code></body></code> tag.</p> + </li> + <li> + <p>Download our source files (<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/coffee.jpg">coffee.jpg</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/tea.jpg">tea.jpg</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/description.txt">description.txt</a>), or feel free to substitute your own.</p> + </li> + <li> + <p>In our script we'll first define a function that returns the promises we want to send to <code>Promise.all()</code>. This would be easy if we just wanted to run the <code>Promise.all()</code> block in response to three <code>fetch()</code> operations completing. We could just do something like:</p> + + <pre class="brush: js notranslate">let a = fetch(url1); +let b = fetch(url2); +let c = fetch(url3); + +Promise.all([a, b, c]).then(values => { + ... +});</pre> + + <p>When the promise is fulfilled, the <code>values</code> passed into the fullfillment handler would contain three <code>Response</code> objects, one for each of the <code>fetch()</code> operations that have completed.</p> + + <p>However, we don't want to do this. Our code doesn't care when the <code>fetch()</code> operations are done. Instead, what we want is the loaded data. That means we want to run the <code>Promise.all()</code> block when we get back usable blobs representing the images, and a usable text string. We can write a function that does this; add the following inside your <code><script></code> element:</p> + + <pre class="brush: js notranslate">function fetchAndDecode(url, type) { + return fetch(url).then(response => { + if (type === 'blob') { + return response.blob(); + } else if (type === 'text') { + return response.text(); + } + }) + .catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); + }); +}</pre> + + <p>This looks a bit complex, so let's run through it step by step:</p> + + <ol> + <li>First of all we define the function, passing it a URL and a string representing the type of resource it is fetching.</li> + <li>Inside the function body, we have a similar structure to what we saw in the first example — we call the <code>fetch()</code> function to fetch the resource at the specified URL, then chain it onto another promise that returns the decoded (or "read") response body. This was always the <code>blob()</code> method in the previous example.</li> + <li>However, two things are different here: + <ul> + <li>First of all, the second promise we return is different depending on what the <code>type</code> value is. Inside the executor function we include a simple <code>if ... else if</code> statement to return a different promise depending on what type of file we need to decode (in this case we've got a choice of <code>blob</code> or <code>text</code>, but it would be easy to extend this to deal with other types as well).</li> + <li>Second, we have added the <code>return</code> keyword before the <code>fetch()</code> call. The effect this has is to run the entire chain and then run the final result (i.e. the promise returned by <code>blob()</code> or <code>text()</code>) as the return value of the function we've just defined. In effect, the <code>return</code> statements pass the results back up the chain to the top.</li> + </ul> + </li> + <li> + <p>At the end of the block, we chain on a <code>.catch()</code> call, to handle any error cases that may come up with any of the promises passed in the array to <code>.all()</code>. If any of the promises reject, the catch block will let you know which one had a problem. The <code>.all()</code> block (see below) will still fulfill, but just won't display the resources that had problems. If you wanted the <code>.all</code> to reject, you'd have to chain the <code>.catch()</code> block on to the end of there instead.</p> + </li> + </ol> + + <p>The code inside the function body is async and promise-based, therefore in effect the entire function acts like a promise — convenient.</p> + </li> + <li> + <p>Next, we call our function three times to begin the process of fetching and decoding the images and text, and store each of the returned promises in a variable. Add the following below your previous code:</p> + + <pre class="brush: js notranslate">let coffee = fetchAndDecode('coffee.jpg', 'blob'); +let tea = fetchAndDecode('tea.jpg', 'blob'); +let description = fetchAndDecode('description.txt', 'text');</pre> + </li> + <li> + <p>Next, we will define a <code>Promise.all()</code> block to run some code only when all three of the promises stored above have successfully fulfilled. To begin with, add a block with an empty executor inside the <code>.then()</code> call, like so:</p> + + <pre class="brush: js notranslate">Promise.all([coffee, tea, description]).then(values => { + +});</pre> + + <p>You can see that it takes an array containing the promises as a parameter. The executor will only run when all three promises resolve; when that happens, it will be passed an array containing the results from the individual promises (i.e. the decoded response bodies), kind of like [coffee-results, tea-results, description-results].</p> + </li> + <li> + <p>Last of all, add the following inside the executor. Here we use some fairly simple sync code to store the results in separate variables (creating object URLs from the blobs), then display the images and text on the page.</p> + + <pre class="brush: js notranslate">console.log(values); +// Store each value returned from the promises in separate variables; create object URLs from the blobs +let objectURL1 = URL.createObjectURL(values[0]); +let objectURL2 = URL.createObjectURL(values[1]); +let descText = values[2]; + +// Display the images in <img> elements +let image1 = document.createElement('img'); +let image2 = document.createElement('img'); +image1.src = objectURL1; +image2.src = objectURL2; +document.body.appendChild(image1); +document.body.appendChild(image2); + +// Display the text in a paragraph +let para = document.createElement('p'); +para.textContent = descText; +document.body.appendChild(para);</pre> + </li> + <li> + <p>Save and refresh and you should see your UI components all loaded, albeit in a not particularly attractive way!</p> + </li> +</ol> + +<p>The code we provided here for displaying the items is fairly rudimentary, but works as an explainer for now.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you get stuck, you can compare your version of the code to ours, to see what it is meant to look like — <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-all.html">see it live</a>, and see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html">source code</a>.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you were improving this code, you might want to loop through a list of items to display, fetching and decoding each one, and then loop through the results inside <code>Promise.all()</code>, running a different function to display each one depending on what the type of code was. This would make it work for any number of items, not just three.</p> + +<p>In addition, you could determine what the type of file is being fetched without needing an explicit <code>type</code> property. You could for example check the {{HTTPHeader("Content-Type")}} HTTP header of the response in each case using <code><a href="/en-US/docs/Web/API/Headers/get">response.headers.get("content-type")</a></code>, and then react accordingly.</p> +</div> + +<h2 id="Running_some_final_code_after_a_promise_fulfillsrejects">Running some final code after a promise fulfills/rejects</h2> + +<p>There will be cases where you want to run a final block of code after a promise completes, regardless of whether it fulfilled or rejected. Previously you'd have to include the same code in both the <code>.then()</code> and <code>.catch()</code> callbacks, for example:</p> + +<pre class="brush: js notranslate">myPromise +.then(response => { + doSomething(response); + runFinalCode(); +}) +.catch(e => { + returnError(e); + runFinalCode(); +});</pre> + +<p>In more recent modern browsers, the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally">.finally()</a></code> method is available, which can be chained onto the end of your regular promise chain allowing you to cut down on code repetition and do things more elegantly. The above code can now be written as follows:</p> + +<pre class="brush: js notranslate">myPromise +.then(response => { + doSomething(response); +}) +.catch(e => { + returnError(e); +}) +.finally(() => { + runFinalCode(); +});</pre> + +<p>For a real example, take a look at our <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/promise-finally.html">promise-finally.html demo</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-finally.html">source code</a> also). This works exactly the same as the <code>Promise.all()</code> demo we looked at in the above section, except that in the <code>fetchAndDecode()</code> function we chain a <code>finally()</code> call on to the end of the chain:</p> + +<pre class="brush: js notranslate">function fetchAndDecode(url, type) { + return fetch(url).then(response => { + if(type === 'blob') { + return response.blob(); + } else if(type === 'text') { + return response.text(); + } + }) + .catch(e => { + console.log(`There has been a problem with your fetch operation for resource "${url}": ` + e.message); + }) + .finally(() => { + console.log(`fetch attempt for "${url}" finished.`); + }); +}</pre> + +<p>This logs a simple message to the console to tell us when each fetch attempt has finished.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: <code>finally()</code> allows you to write async equivalents to try/catch/finally in async code.</p> +</div> + +<h2 id="Building_your_own_custom_promises">Building your own custom promises</h2> + +<p>The good news is that, in a way, you've already built your own promises. When you've chained multiple promises together with <code>.then()</code> blocks, or otherwise combined them to create custom functionality, you are already making your own custom async promise-based functions. Take our <code>fetchAndDecode()</code> function from the previous examples, for example.</p> + +<p>Combining different promise-based APIs together to create custom functionality is by far the most common way you'll do custom things with promises, and shows the flexibility and power of basing most modern APIs around the same principle. There is another way, however.</p> + +<h3 id="Using_the_Promise_constructor">Using the Promise() constructor</h3> + +<p>It is possible to build your own promises using the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise()</a></code> constructor. The main situation in which you'll want to do this is when you've got code based on an an old-school asynchronous API that is not promise-based, which you want to promis-ify. This comes in handy when you need to use existing, older project code, libraries, or frameworks along with modern promise-based code.</p> + +<p>Let's have a look at a simple example to get you started — here we wrap a <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> call with a promise — this runs a function after two seconds that resolves the promise (using the passed <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve">resolve()</a></code> call) with a string of "Success!".</p> + +<pre class="brush: js notranslate">let timeoutPromise = new Promise((resolve, reject) => { + setTimeout(function(){ + resolve('Success!'); + }, 2000); +});</pre> + +<p><code>resolve()</code> and <code>reject()</code> are functions that you call to fulfill or reject the newly-created promise. In this case, the promise fulfills with a string of "Success!".</p> + +<p>So when you call this promise, you can chain a <code>.then()</code> block onto the end of it and it will be passed a string of "Success!". In the below code we simply alert that message:</p> + +<pre class="brush: js notranslate">timeoutPromise +.then((message) => { + alert(message); +})</pre> + +<p>or even just</p> + +<pre class="brush: js notranslate">timeoutPromise.then(alert); +</pre> + +<p>Try <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/custom-promise.html">running this live</a> to see the result (also see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise.html">source code</a>).</p> + +<p>The above example is not very flexible — the promise can only ever fulfill with a single string, and it doesn't have any kind of <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject">reject()</a></code> condition specified (admittedly, <code>setTimeout()</code> doesn't really have a fail condition, so it doesn't matter for this simple example).</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Why <code>resolve()</code>, and not <code>fulfill()</code>? The answer we'll give you for now is <em>it's complicated</em>.</p> +</div> + +<h3 id="Rejecting_a_custom_promise">Rejecting a custom promise</h3> + +<p>We can create a promise that rejects using the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/reject">reject()</a></code> method — just like <code>resolve()</code>, this takes a single value, but in this case it is the reason to reject with, i.e., the error that will be passed into the <code>.catch()</code> block.</p> + +<p>Let's extend the previous example to have some <code>reject()</code> conditions as well as allowing different messages to be passed upon success.</p> + +<p>Take a copy of the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise.html">previous example</a>, and replace the existing <code>timeoutPromise()</code> definition with this:</p> + +<pre class="brush: js notranslate">function timeoutPromise(message, interval) { + return new Promise((resolve, reject) => { + if (message === '' || typeof message !== 'string') { + reject('Message is empty or not a string'); + } else if (interval < 0 || typeof interval !== 'number') { + reject('Interval is negative or not a number'); + } else { + setTimeout(function(){ + resolve(message); + }, interval); + } + }); +};</pre> + +<p>Here we are passing two methods into a custom function — a message to do something with, and the time interval to pass before doing the thing. Inside the function we then return a new <code>Promise</code> object — invoking the function will return the promise we want to use.</p> + +<p>Inside the Promise constructor, we do a number of checks inside <code>if ... else</code> structures:</p> + +<ol> + <li>First of all we check to see if the message is appropriate for being alerted. If it is an empty string or not a string at all, we reject the promise with a suitable error message.</li> + <li>Next, we check to see if the interval is an appropriate interval value. If it is negative or not a number, we reject the promise with a suitable error message.</li> + <li>Finally, if the parameters both look OK, we resolve the promise with the specified message after the specified interval has passed using <code>setTimeout()</code>.</li> +</ol> + +<p>Since the <code>timeoutPromise()</code> function returns a <code>Promise</code>, we can chain <code>.then()</code>, <code>.catch()</code>, etc. onto it to make use of its functionality. Let's use it now — replace the previous <code>timeoutPromise</code> usage with this one:</p> + +<pre class="brush: js notranslate">timeoutPromise('Hello there!', 1000) +.then(message => { + alert(message); +}) +.catch(e => { + console.log('Error: ' + e); +});</pre> + +<p>When you save and run the code as is, after one second you'll get the message alerted. Now try setting the message to an empty string or the interval to a negative number, for example, and you'll be able to see the promise reject with the appropriate error messages! You could also try doing something else with the resolved message rather than just alerting it.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can find our version of this example on GitHub as <a href="https://mdn.github.io/learning-area/javascript/asynchronous/promises/custom-promise2.html">custom-promise2.html</a> (see also the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/custom-promise2.html">source code</a>).</p> +</div> + +<h3 id="A_more_real-world_example">A more real-world example</h3> + +<p>The above example was kept deliberately simple to make the concepts easy to understand, but it is not really very async. The asynchronous nature is basically faked using <code>setTimeout()</code>, although it does still show that promises are useful for creating a custom function with sensible flow of operations, good error handling, etc.</p> + +<p>One example we'd like to invite you to study, which does show a useful async application of the <code>Promise()</code> constructor, is <a href="https://github.com/jakearchibald/idb/">Jake Archibald's idb library</a>. This takes the <a href="/en-US/docs/Web/API/IndexedDB_API">IndexedDB API</a>, which is an old-style callback-based API for storing and retrieving data on the client-side, and allows you to use it with promises. If you look at the <a href="https://github.com/jakearchibald/idb/blob/master/lib/idb.js">main library file</a> you'll see the same kind of techniques we discussed above being used there. The following block converts the basic request model used by many IndexedDB methods to use promises:</p> + +<pre class="brush: js notranslate">function promisifyRequest(request) { + return new Promise(function(resolve, reject) { + request.onsuccess = function() { + resolve(request.result); + }; + + request.onerror = function() { + reject(request.error); + }; + }); +}</pre> + +<p>This works by adding a couple of event handlers that fulfill and reject the promise at appropriate times:</p> + +<ul> + <li>When the <code><a href="/en-US/docs/Web/API/IDBRequest">request</a></code>'s <a href="/en-US/docs/Web/API/IDBRequest/success_event"><code>success</code> event</a> fires, the <code><a href="/en-US/docs/Web/API/IDBRequest/onsuccess">onsuccess</a></code> handler fulfills the promise with the request <code><a href="/en-US/docs/Web/API/IDBRequest/result">result</a></code>.</li> + <li>When the <code><a href="/en-US/docs/Web/API/IDBRequest">request</a></code>'s <a href="/en-US/docs/Web/API/IDBRequest/error_event"><code>error</code> event</a> fires, the <code><a href="/en-US/docs/Web/API/IDBRequest/onerror">onerror</a></code> handler rejects the promise with the request <code><a href="/en-US/docs/Web/API/IDBRequest/error">error</a></code>.</li> +</ul> + +<h2 id="Conclusion">Conclusion</h2> + +<p>Promises are a good way to build asynchronous applications when we don’t know the return value of a function or how long it will take to return. They make it easier to express and reason about sequences of asynchronous operations without deeply nested callbacks, and they support a style of error handling that is similar to the synchronous <code>try...catch</code> statement.</p> + +<p>Promises work in the latest versions of all modern browsers; the only place where promise support will be a problem is in Opera Mini and IE11 and earlier versions.</p> + +<p>We didn't touch on all promise features in this article, just the most interesting and useful ones. As you start to learn more about promises, you'll come across further features and techniques.</p> + +<p>Most modern Web APIs are promise-based, so you'll need to understand promises to get the most out of them. Among those APIs are <a href="/en-US/docs/Web/API/WebRTC_API">WebRTC</a>, <a href="/en-US/docs/Web/API/Web_Audio_API">Web Audio API</a>, <a href="/en-US/docs/Web/API/Media_Streams_API">Media Capture and Streams</a>, and many more. Promises will be more and more important as time goes on, so learning to use and understand them is an important step in learning modern JavaScript.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise()</a></code></li> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Using_promises">Using promises</a></li> + <li><a href="https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html">We have a problem with promises</a> by Nolan Lawson</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Timeouts_and_intervals", "Learn/JavaScript/Asynchronous/Async_await", "Learn/JavaScript/Asynchronous")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/asynchronous/timeouts_and_intervals/index.html b/files/pt-br/learn/javascript/asynchronous/timeouts_and_intervals/index.html new file mode 100644 index 0000000000..2c399201e5 --- /dev/null +++ b/files/pt-br/learn/javascript/asynchronous/timeouts_and_intervals/index.html @@ -0,0 +1,624 @@ +--- +title: Timeouts e intervalos +slug: Learn/JavaScript/Asynchronous/Timeouts_and_intervals +translation_of: Learn/JavaScript/Asynchronous/Timeouts_and_intervals +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}</div> + +<p class="summary">Este tutorial é sobre os métodos tradicionais que o JavaScript tem disponíveis para executar códigos assíncronamente depois que um dado período de tempo tenha passado, ou em um intervalo (um número de segundos por segundo), discute suas utilidades e considera seus problemas.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Entendimento básico sobre informáticas e fundamentos do JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender loops e intervalos assíncronos e para o que eles servem.</td> + </tr> + </tbody> +</table> + +<h2 id="Introdução">Introdução</h2> + +<p>Por um longo tempo, a plataforma web tem oferecido à programadores JavaScript um número de funções que permitem que eles executem código assíncronamente depois de um determinado intervalo de tempo, e executar um bloco de código de modo assíncrono repetidamente até que você o mande parar.</p> + +<p>Essas funções são:</p> + +<dl> + <dt><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code></dt> + <dd>Executa um bloco específico uma vez depois de um determinado tempo</dd> + <dt><code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></code></dt> + <dd>Executa um bloco específico repetidamente com um intervalo fixo entre cada chamada.</dd> + <dt><code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code></dt> + <dd>Uma versão moderna de <code>setInterval()</code>. Ela executa um bloc de código específico antes do navegador renderizar a tela novamento, permitindo que seja executada em uma taxa de quadros adequada, independentemente do ambiente em que está sendo executado.</dd> +</dl> + +<p>O código executado por estas funções é executado na main thread (depois do dado intervalo).</p> + +<div> +<p>É importante saber que você pode (e irá) executar outros códigos antes que uma chamada <code>setTimeout()</code> é executada, ou entre iterações de <code>setInterval()</code>. Dependendo de como essas operações são intensas, elas podem atrasar o seu código async ainda mais, já que o código async só é executado depois que a main thread terminar seu processamento (ou seja, quando a fila estiver vazia). Você aprenderá mais sobre isso enquanto fazemos nosso progresso neste artigo.</p> +</div> + +<p>De qualquer forma, essas funções são usadas para executar animações constantes e outros processamentos em um web site ou aplicação. Nas seções a seguir, nós vamos te mostrar como elas podem ser usadas.</p> + +<h2 id="setTimeout">setTimeout()</h2> + +<p>Como foi dito anteriormente, o <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> executa um bloco de código particular depois que um determinado período de tempo passou. Ele toma os seguintes parâmetros:</p> + +<ul> + <li>Uma função a ser executada, ou uma referência de uma função definida em outro lugar.</li> + <li>Um número representando o intervalo de tempo em milissegundos (1000 milissegundos equivalem a 1 segundo) para esperar antes de executar o código. Se você especificar um valor de 0 (ou simplesmente omitir o valor), a função será executada assim que possível (mas não imediatamente).</li> + <li>Zero ou mais valores que representam quaisquer parâmetros que você quiser passar para a função quando ela for executada.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>NOTA:</strong> O tempos especificafo <strong>não</strong> é o tempo garantido de execução, mas sim o tempo míniimo de execução. As callback que você passa para essas funções não podem ser executadas até que a main thread esteja vazia.</p> + +<p>Como consequência, códigos como <code>setTimeout(fn, 0)</code><em> </em>serão executados assim que a fila estiver vazia, <strong>não</strong> imediatamente. Se você executar código como <code>setTimeout(fn, 0)</code> e depois imediatamente executar um loop que conta de 1 a 10 bilhões, sua callback será executada depois de alguns segundos.</p> +</div> + +<p>No exemplo a seguir, o navegador vai esperar dois segundos antes de executar a função anônima, e depois vai mostrar a mensagem de alerta (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">veja aqui</a>, e <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-settimeout.html">veja o código</a>):</p> + +<pre class="brush: js notranslate">let myGreeting = setTimeout(function() { + alert('Hello, Mr. Universe!'); +}, 2000)</pre> + +<p>As funções especificadas não tem que ser anônimas. Você pode dar o nome da função, e até mesmo definir ela em outro lugar e passar uma referência para o timeout <code>setTimeout()</code>. As versões a seguir do código são equivalentes à primeira:</p> + +<pre class="brush: js notranslate">// With a named function +let myGreeting = setTimeout(function sayHi() { + alert('Hello, Mr. Universe!'); +}, 2000) + +// With a function defined separately +function sayHi() { + alert('Hello Mr. Universe!'); +} + +let myGreeting = setTimeout(sayHi, 2000);</pre> + +<p>Isso pode ser útil se você tem uma função que precisa ser chamada de um timeout e também em resposta à um evento, por exemplo. Mas também pode servir para manter seu código organizado, especialmente se a callback timetout é mais do que algumas linhas de código.</p> + +<p><code>setTimeout()</code> retorna um valor identificador que pode ser usado para se referir ao timeout depois, como em quando você que pará-lo. Veja {{anch("Cancelando timetous")}} (abaixo) e aprenda como fazer isso.</p> + +<h3 id="Passando_parâmetros_para_uma_função_setTimeout">Passando parâmetros para uma função setTimeout()</h3> + +<p>Quaisquer parâmetros que você quiser passar para a função sendo executada dentro do <code>setTimeout()</code> devem ser passados como parâmetros adicionais no final da lista.</p> + +<p>Por exemplo, você pode mudar a função anterior para que ela diga oi para qualquer nome que foi passada para ela:</p> + +<pre class="brush: js notranslate">function sayHi(who) { + alert(`Hello ${who}!`); +}</pre> + +<p>Agora, você pode passar o nome da pessoa no <code>setTimeout()</code> como um terceiro parâmetro:</p> + +<pre class="brush: js notranslate">let myGreeting = setTimeout(sayHi, 2000, 'Mr. Universe');</pre> + +<h3 id="Cancelando_timeouts">Cancelando timeouts</h3> + +<p>Finalmente, se um timeout foi criado, você pode cancelá-lo antes que o tempo especificado tenha passado chamando <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearTimeout">clearTimeout()</a></code>, passando para o identificador a chamada <code>setTimeout()</code> como um parâmetreo. então para cancelar o timeout acima, você fará isso:</p> + +<pre class="brush: js notranslate">clearTimeout(myGreeting);</pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Veja <code><a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/greeter-app.html">greeter-app.html</a></code> para uma demonstração mais desenvolvida que te permite colocar o nome da pessoa a dizer oi em um formulário, e cancelar a saudação usando um botão separado (<a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/greeter-app.html">veja aqui o código fonte</a>).</p> +</div> + +<h2 id="setInterval">setInterval()</h2> + +<p><code>setTimeout()</code> funciona perfeitamento quando você precisa executar algum código depois de um período de tempo. Mas o que acontece quando voc~e precisa executar o código de novo e de novo — por exemplo, no caso de uma animação?</p> + +<p>É aí que o <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></code> entra. Ele funciona de uma maneira muito similar à <code>setTimeout()</code>, exceto que a função que você passar como primeiro parâmetro é executada repetidamente em não menos que um número determinado de milissegundos dado no segundo parâmetro, ao invés de apenas uma vez. Você também pode passar qualquer parâmetro sendo executado como um parâmetro subsequente da chamada de <code>setInterval()</code>.</p> + +<p>Vamos dar uma olhada em um exemplo. A função a seguir cria um novo objeto <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date">Date()</a></code>, tira uma string de tempo usando <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString">toLocaleTimeString()</a></code>, e depois a mostra naUI. Em seguida, ela executa a função uma vez por segundo usando <code>setInterval()</code>, criando o efeito de um relógio digital que é atualizado uma vez por segundo (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">veja aqui</a>, e também <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">veja o código</a>):</p> + +<pre class="brush: js notranslate">function displayTime() { + let date = new Date(); + let time = date.toLocaleTimeString(); + document.getElementById('demo').textContent = time; +} + +const createClock = setInterval(displayTime, 1000);</pre> + +<p>Assim como o <code>setTimeout()</code>, o <code>setInterval()</code> também retorna um valor identificador que você pode usar depois para cancelar o intervalo.</p> + +<h3 id="Cancelando_intervalos">Cancelando intervalos</h3> + +<p><code>setInterval()</code> continua sua execução para sempre, a menos que você faça algo sobre isso. Você provavelmente quer um jeito de parar tais tarefas, do contrário você pode acabar com error quando o navegador não puder completar outras versões futuras da tarefa, ou se a animação acabar. Você pode fazer isso do mesmo jeito que você para timeouts — passando o identificador retornado por <code>setInterval()</code> para a função <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval">clearInterval()</a></code>:</p> + +<pre class="brush: js notranslate">const myInterval = setInterval(myFunction, 2000); + +clearInterval(myInterval);</pre> + +<h4 id="Aprendizado_ativo_Criando_seu_próprio_cronômetro!">Aprendizado ativo: Criando seu próprio cronômetro!</h4> + +<p>Com tudo isso dito, nós temos um desafio para você. Faça uma cópia do nosso exemplo <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-clock.html">setInterval-clock.html</a></code>, e o modifique para criar seu próprio cronômetro.</p> + +<p>Você precisa mostrar um tempo na tela como antes, mas nesse ememplo você vai precisar de:</p> + +<ul> + <li>Um botão de início para fazer o cronômetro começar a contar.</li> + <li>Um botâo de parar para parar ou pausar o tempo.</li> + <li>Um botão de "reset" para resetar o tempo em 0.</li> + <li>O display do tempo para mostrar o número de sgundos passados.</li> +</ul> + +<p>Here's a few hints for you:</p> + +<ul> + <li>You can structure and style the button markup however you like; just make sure you use semantic HTML, with hooks to allow you to grab the button references using JavaScript.</li> + <li>You probably want to create a variable that starts at <code>0</code>, then increments by one every second using a constant loop.</li> + <li>It is easier to create this example without using a <code>Date()</code> object, like we've done in our version, but less accurate — you can't guarantee that the callback will fire after exactly <code>1000</code>ms. A more accurate way would be to run <code>startTime = Date.now()</code> to get a timestamp of exactly when the user clicked the start button, and then do <code>Date.now() - startTime</code> to get the number of milliseconds after the start button was clicked.</li> + <li>You also want to calculate the number of hours, minutes, and seconds as separate values, and then show them together in a string after each loop iteration. From the second counter, you can work out each of these.</li> + <li>How would you calculate them? Have a think about it: + <ul> + <li>The number of seconds in an hour is <code>3600</code>.</li> + <li>The number of minutes will be the amount of seconds left over when all of the hours have been removed, divided by <code>60</code>.</li> + <li>The number of seconds will be the amount of seconds left over when all of the minutes have been removed.</li> + </ul> + </li> + <li>You'll want to include a leading zero on your display values if the amount is less than <code>10</code>, so it looks more like a traditional clock/watch.</li> + <li>To pause the stopwatch, you'll want to clear the interval. To reset it, you'll want to set the counter back to <code>0</code>, clear the interval, and then immediately update the display.</li> + <li>You probably ought to disable the start button after pressing it once, and enable it again after you've stopped/reset it. Otherwise multiple presses of the start button will apply multiple <code>setInterval()</code>s to the clock, leading to wrong behavior.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you get stuck, you can <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html">find our version here</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/setinterval-stopwatch.html">source code</a> also).</p> +</div> + +<h2 id="Coisas_para_se_manter_em_mente_sobre_o_setTimeout_e_o_setInterval">Coisas para se manter em mente sobre o setTimeout() e o setInterval()</h2> + +<p>Existem algumas coisinhas que devemos sempre lembrar quando estamos trabalhando com <code>setTimeout()</code> e<code>setInterval()</code>:</p> + +<h3 id="Timeouts_recursivos">Timeouts recursivos</h3> + +<p>Há outra maneira de usar o <code>setTimeout()</code>: você pode chamá-lo recusivamnete para executar o mesmo código repetidas vezes, ao invés de usar o <code>setInterval()</code>.</p> + +<p>O exemplo abaixo usa um <code>setTimeout()</code> recursivo para executar a função passada a cada <code>100</code> millissegundos:</p> + +<pre class="brush: js notranslate">let i = 1; + +setTimeout(function run() { + console.log(i); + i++; + setTimeout(run, 100); +}, 100);</pre> + +<p>Compare the above example to the following one — this uses <code>setInterval()</code> to accomplish the same effect:</p> + +<pre class="brush: js notranslate">let i = 1; + +setInterval(function run() { + console.log(i); + i++ +}, 100);</pre> + +<h4 id="Qual_a_diferença_entre_o_setTimeout_recursivo_e_o_setInterval">Qual a diferença entre o <code>setTimeout()</code> recursivo e o <code>setInterval()</code>?</h4> + +<p>A diferença entre as duas versões é bem sútil.</p> + +<ul> + <li>O <code>setTimeout()</code> recursivo garante que o mesmo intervalo entre as execuções (por exemplo, <code>100</code>ms no exemplo acima). O código será executado, depois esperar <code>100</code> milissegundos antes de fazer isso de novo— então o intervalo será o mesmo, idependente do tempo que o código leva para ser executado.</li> + <li>O exemplo usando <code>setInterval()</code> faz as coisas um pouco diferentes.O intervalo escolhido inclui o tempo necessário para executar o código que você deseja executar. Digamos que o código leva <code>40</code> milissegundos de execução — o intervalo acaba levando apenas <code>60</code> milissegundos.</li> + <li>Quando usamos o <code>setTimeout()</code> recursivamente, cada iteração pode calcular um delay diferente antes de executar a próxima iteração. Em outras palavras, o valor do segundo parâmetro pode especificar um tempo diferente em milissegundos para esperar antes de rodar o código de novo.</li> +</ul> + +<p>Quando seu código tem o potencial para levar mais tempo do que lhe foi atribuido, é melhor usar o <code>setTimeout()</code> recursivo — isso irá manter o intervalo de tempo constant entre execuções independente do quanto tempo o código levar para ser executado, e você não terá erros.</p> + +<h3 id="Timeouts_imediatos">Timeouts imediatos</h3> + +<p>Usar zero como o valor para <code>setTimeout()</code> faz a execução da callback ser o mais rápido o possível, mas apenas depois que a main thread for terminada.</p> + +<p>Por exemplo, o código abaixo (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/zero-settimeout.html">veja funcionar aqui</a>) mostra um alert que contém um <code>"Hello"</code>, depois um alert que contém <code>"World"</code> assim que você clicar em OK no primeiro alerta.</p> + +<pre class="brush: js notranslate">setTimeout(function() { + alert('World'); +}, 0); + +alert('Hello');</pre> + +<p>Isso pode ser útil em casos onde você quer fazer um bloco de código ser executado assim que a main thread acabar o seu processamento — colocar no loop de eventos async, assim ele vai ser executado logo depois.</p> + +<h3 id="Cancelando_com_clearTimeout_ou_clearInterval">Cancelando com clearTimeout() ou clearInterval()</h3> + +<p><code>clearTimeout()</code> e <code>clearInterval()</code> usam a mesma lista de entradas para cancelamento. Isso significa que você pode usar os dois para cancelar um <code>setTimeout()</code> ou <code>setInterval()</code>.</p> + +<p>Mas mesmo assim, você deve usar o <code>clearTimeout()</code> para entradas <code>setTimeout()</code> e <code>clearInterval()</code> para entradas <code>setInterval()</code>. Isso evita confusões.</p> + +<h2 id="requestAnimationFrame">requestAnimationFrame()</h2> + +<p><code><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></code> é uma função de loop especializada criada para executar animações com eficiência no navegador. Ela é basicamente a versão moderna de <code>setInterval()</code> — ela executa um bloco de código específico antes que o navegador renove o display, permitindo que uma animação seja executada em um framerate adequado independente do ambiente em que está sendo executada.</p> + +<p>Ela foi criada em resposta à problemas ocorridos com <code>setInterval()</code>, que por exemplo não roda em uma taxa de quadros otimizada para o dispositivo, e às vezes diminui os frames, continua a rodar mesmo se a guia não esiver ativa ou se a animação for rolada para fora da página, etc.</p> + +<p>(<a href="http://creativejs.com/resources/requestanimationframe/index.html">Leia mais sobre isso em CreativeJS</a>.)</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Você pode encontrar exemplos do uso de <code>requestAnimationFrame()</code> em outros lugares do curso — por exemplo em <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Drawing graphics</a>, e <a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a>.</p> +</div> + +<p>O método toma como argumentos uma callback a ser invocada antes da renovação. Esse é o padrão geral que você verá usado em:</p> + +<pre class="brush: js notranslate">function draw() { + // Drawing code goes here + requestAnimationFrame(draw); +} + +draw();</pre> + +<p>A ideia é definir uma função em que sua animação é atualizada (e.g. seus spritas se movem, a pontuação é atuializada, dados são recarregados, etc). Depois, você inicia o processo. No final do bloco da função você chama <code>requestAnimationFrame()</code> com a referência da função passada como parâmetro, e isso instrui o navegador a chamar a função de novo na próxima renovação. Isso é executado continuamente, já que o código está chamando <code>requestAnimationFrame()</code> recursivamente.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Se você quer realizar algum tipo de animação na DOM constantemente, <a href="/en-US/docs/Web/CSS/CSS_Animations">Animações CSS</a> são provavelemente mais rápidas. elas são calculadas diretamente pelo código interno do navegador, ao invés de JavaScript.</p> + +<p>Se, no entanto, você está fazendo algo mais complexo e envolvendo objetos que não são diretamente assessados da DOM (como <a href="/en-US/docs/Web/API/Canvas_API">2D Canvas API</a> ou objetos <a href="/en-US/docs/Web/API/WebGL_API">WebGL</a>), <code>requestAnimationFrame()</code> é a melhor opção na maioria dos casos</p> +</div> + +<h3 id="Qual_a_velocidade_da_sua_animação">Qual a velocidade da sua animação?</h3> + +<p>A suavidade da sua animação é diretamente dependente na frame rate da sua animação e é medida em frames per second (fps). The smoothness of your animation is directly dependent on your animation's frame rate and it is measured in frames per second (fps). Quanto maior esse número, mais suave será a sua animação, até certo ponto.</p> + +<p>Já que a maioria das tela tem uma taxa de atualização de 60Hz, a frame rate mais rápida que você pode ter é de 60fps quando trabalhando com web browsers. No entanto, mais frames significa mais processamento, o que pode ser causar uma queda de quadros e travamento.</p> + +<p>Se você tem um monitos com uma taxa de atualização de 60Hz e você quer atingir 60FPS você tem pelo menos 16.7 milissegundos (<code>1000 / 60</code>) para executar sua animação em cada frame. Isso é um lembrete de que você vai precisar estar atento à quantidade de código que você vai tentar executar em cada iteração do loop de animação.</p> + +<p><code>requestAnimationFrame()</code> sempre tenta ficar o mais próximo possível de 60 FPS. Às vezes, isso não é possível — se você tem uma animação bem complexa e você está executando ela em um computador lento, sua frame rate será menor. Em todos os casos, o <code>requestAnimationFrame()</code> sempre vai fazer o melhor que pode com o que ele tem dísponivel.</p> + +<h3 id="Como_o_requestAnimationFrame_se_diferencia_de_setInterval_e_setTimeout">Como o requestAnimationFrame() se diferencia de setInterval() e setTimeout()?</h3> + +<p>Vamos falar um pouco sobre como o método <code>requestAnimationFrame()</code> se diferencia dos outros métodos vistos anteriormente. Olhando com o código anterior:</p> + +<pre class="brush: js notranslate">function draw() { + // Drawing code goes here + requestAnimationFrame(draw); +} + +draw();</pre> + +<p>Vamos ver isso usando o <code>setInterval()</code>:</p> + +<pre class="brush: js notranslate">function draw() { + // Drawing code goes here +} + +setInterval(draw, 17);</pre> + +<p>Como foi dito anteriormente, você não especifica um intervalo de tempo para <code>requestAnimationFrame()</code>. O método se executa o mais rápido e suave o possível nas condições atuais. O navegador também não perde tempo executando uma animação se ela está fora da tela por algum motivo, etc.</p> + +<p><code>setInterval()</code>, por outro lado, exige que um intervalo de tempo seja especificado. Nós chegamos ao valor final de 17 por meio da formula <em>1000 milliseconds / 60Hz</em>, e depois arredondamos o resultado. Arredondar é uma boa ideia; se você tivesse arredondado para baixo, o navegador pode tentar executar a animação mais rápido do que 60 FPS, e não faria nenhuma diferênça na suavidade da animação de qualquer forma. Como foi dito antes, 60Hz é a taxa de atualização padrão.</p> + +<h3 id="Incluindo_um_timestamp">Incluindo um timestamp</h3> + +<p>A callback passada para a função <code>requestAnimationFrame()</code> pode ser dada um parâmetro támbem: um valor <em>timestamp</em>, que representa o tempo desde que o <code>requestAnimationFrame()</code> começou a rodar.</p> + +<p>Isso é útil, permite que você execute coisas em um tempo específico e em passo constante, independente do quão rápido ou lento é o seu dispositivo. O padão geral que você usaria se parece um pouco com isso:</p> + +<pre class="brush: js notranslate">let startTime = null; + +function draw(timestamp) { + if (!startTime) { + startTime = timestamp; + } + + currentTime = timestamp - startTime; + + // Do something based on current time + + requestAnimationFrame(draw); +} + +draw();</pre> + +<h3 id="Suporte_do_navegador">Suporte do navegador</h3> + +<p><code>requestAnimationFrame()</code> é suportado em navegadores mais recentes do que <code>setInterval()</code>/<code>setTimeout()</code>. Curiosamente, está disponível no Internet Explorer 10 e além.</p> + +<p>Então, você não precisa dar suporte para versões mais velhas do IE, não há poruqe não usar o <code>requestAnimationFrame()</code>.</p> + +<h3 id="Um_exemplo_simples">Um exemplo simples</h3> + +<p>Enough with the theory! Let's build your own personal <code>requestAnimationFrame()</code> example. You're going to create a simple "spinner animation"—the kind you might see displayed in an app when it is busy connecting to the server, etc.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: In a real world example, you should probably use CSS animations to run this kind of simple animation. However, this kind of example is very useful to demonstrate <code>requestAnimationFrame()</code> usage, and you'd be more likely to use this kind of technique when doing something more complex such as updating the display of a game on each frame.</p> +</div> + +<ol> + <li> + <p>Grab a basic HTML template (<a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">such as this one</a>).</p> + </li> + <li> + <p>Put an empty {{htmlelement("div")}} element inside the {{htmlelement("body")}}, then add a ↻ character inside it. This is circular arrow character will act as our spinner for this example.</p> + </li> + <li> + <p>Apply the following CSS to the HTML template (in whatever way you prefer). This sets a red background on the page, sets the <code><body></code> height to <code>100%</code> of the {{htmlelement("html")}} height, and centers the <code><div></code> inside the <code><body></code>, horizontally and vertically.</p> + + <pre class="brush: css notranslate">html { + background-color: white; + height: 100%; +} + +body { + height: inherit; + background-color: red; + margin: 0; + display: flex; + justify-content: center; + align-items: center; +} + +div { + display: inline-block; + font-size: 10rem; +}</pre> + </li> + <li> + <p>Insert a {{htmlelement("script")}} element just above the <code></body></code> tag.</p> + </li> + <li> + <p>Insert the following JavaScript inside your <code><script></code> element. Here, you're storing a reference to the <code><div></code> inside a constant, setting a <code>rotateCount</code> variable to <code>0</code>, setting an uninitialized variable that will later be used to contain a reference to the <code>requestAnimationFrame()</code> call, and setting a <code>startTime</code> variable to <code>null</code>, which will later be used to store the start time of the <code>requestAnimationFrame()</code>.</p> + + <pre class="brush: js notranslate">const spinner = document.querySelector('div'); +let rotateCount = 0; +let startTime = null; +let rAF; +</pre> + </li> + <li> + <p>Below the previous code, insert a <code>draw()</code> function that will be used to contain our animation code, which includes the <code>timestamp</code> parameter:</p> + + <pre class="brush: js notranslate">function draw(timestamp) { + +}</pre> + </li> + <li> + <p>Inside <code>draw()</code>, add the following lines. They will define the start time if it is not defined already (this will only happen on the first loop iteration), and set the <code>rotateCount</code> to a value to rotate the spinner by (the current timestamp, take the starting timestamp, divided by three so it doesn't go too fast):</p> + + <pre class="brush: js notranslate"> if (!startTime) { + startTime = timestamp; + } + + rotateCount = (timestamp - startTime) / 3; +</pre> + </li> + <li> + <p>Below the previous line inside <code>draw()</code>, add the following block — this checks to see if the value of <code>rotateCount</code> is above <code>359</code> (e.g. <code>360</code>, a full circle). If so, it sets the value to its modulo of 360 (i.e. the remainder left over when the value is divided by <code>360</code>) so the circle animation can continue uninterrupted, at a sensible, low value. Note that this isn't strictly necessary, but it is easier to work with values of 0–359 degrees than values like <code>"128000 degrees"</code>.</p> + + <pre class="brush: js notranslate">if (rotateCount > 359) { + rotateCount %= 360; +}</pre> + </li> + <li>Next, below the previous block add the following line to actually rotate the spinner: + <pre class="brush: js notranslate">spinner.style.transform = `rotate(${rotateCount}deg)`;</pre> + </li> + <li> + <p>At the very bottom inside the <code>draw()</code> function, insert the following line. This is the key to the whole operation — you are setting the variable defined earlier to an active <code>requestAnimation()</code> call, which takes the <code>draw()</code> function as its parameter. This starts the animation off, constantly running the <code>draw()</code> function at a rate as near 60 FPS as possible.</p> + + <pre class="brush: js notranslate">rAF = requestAnimationFrame(draw);</pre> + </li> +</ol> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: You can find this <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">example live on GitHub</a>. (You can see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/simple-raf-spinner.html">source code</a>, also.)</p> +</div> + +<h3 id="Clearing_a_requestAnimationFrame_call">Clearing a requestAnimationFrame() call</h3> + +<p>Clearing a <code>requestAnimationFrame()</code> call can be done by calling the corresponding <code>cancelAnimationFrame()</code> method. (Note that the function name starts with "cancel", not "clear" as with the "set..." methods.) </p> + +<p>Just pass it the value returned by the <code>requestAnimationFrame()</code> call to cancel, which you stored in the variable <code>rAF</code>:</p> + +<pre class="brush: js notranslate">cancelAnimationFrame(rAF);</pre> + +<h3 id="Active_learning_Starting_and_stopping_our_spinner">Active learning: Starting and stopping our spinner</h3> + +<p>In this exercise, we'd like you to test out the <code>cancelAnimationFrame()</code> method by taking our previous example and updating it, adding an event listener to start and stop the spinner when the mouse is clicked anywhere on the page.</p> + +<p>Some hints:</p> + +<ul> + <li>A <code>click</code> event handler can be added to most elements, including the document <code><body></code>. It makes more sense to put it on the <code><body></code> element if you want to maximize the clickable area — the event bubbles up to its child elements.</li> + <li>You'll want to add a tracking variable to check whether the spinner is spinning or not, clearing the animation frame if it is, and calling it again if it isn't.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Try this yourself first; if you get really stuck, check out of our <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html">live example</a> and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/start-and-stop-spinner.html">source code</a>.</p> +</div> + +<h3 id="Throttling_a_requestAnimationFrame_animation">Throttling a requestAnimationFrame() animation</h3> + +<p>One limitation of <code>requestAnimationFrame()</code> is that you can't choose your frame rate. This isn't a problem most of the time, as generally you want your animation to run as smoothly as possible. But what about when you want to create an old school, 8-bit-style animation?</p> + +<p>This was a problem, for example, in the Monkey Island-inspired walking animation from our <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Drawing Graphics</a> article:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/apis/drawing-graphics/loops_animation/7_canvas_walking_animation.html", '100%', 260)}}</p> + +<p>In this example, you have to animate both the position of the character on the screen, and the sprite being shown. There are only 6 frames in the sprite's animation. If you showed a different sprite frame for every frame displayed on the screen by <code>requestAnimationFrame()</code>, Guybrush would move his limbs too fast and the animation would look ridiculous. This example therefore throttles the rate at which the sprite cycles its frames using the following code:</p> + +<pre class="brush: js notranslate">if (posX % 13 === 0) { + if (sprite === 5) { + sprite = 0; + } else { + sprite++; + } +}</pre> + +<p>So the code only cycles the sprite once every 13 animation frames.</p> + +<p>...Actually, it's about every 6.5 frames, as we update <code>posX</code> (character's position on the screen) by two each frame:</p> + +<pre class="brush: js notranslate">if (posX > width/2) { + newStartPos = -( (width/2) + 102 ); + posX = Math.ceil(newStartPos / 13) * 13; + console.log(posX); +} else { + posX += 2; +}</pre> + +<p>This is the code that calculates how to update the position in each animation frame.</p> + +<p>The method you use to throttle your animation will depend on your particular code. For instance, in the earlier spinner example, you could make it appear to move slower by only increasing <code>rotateCount</code> by one on each frame, instead of two.</p> + +<h2 id="Active_learning_a_reaction_game">Active learning: a reaction game</h2> + +<p>For the final section of this article, you'll create a 2-player reaction game. The game will have two players, one of whom controls the game using the <kbd>A</kbd> key, and the other with the <kbd>L</kbd> key.</p> + +<p>When the <em>Start</em> button is pressed, a spinner like the one we saw earlier is displayed for a random amount of time between 5 and 10 seconds. After that time, a message will appear saying <code>"PLAYERS GO!!"</code> — once this happens, the first player to press their control button will win the game.</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html", '100%', 500)}}</p> + +<p>Let's work through this:</p> + +<ol> + <li> + <p>First of all, download the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game-starter.html">starter file for the app</a>. This contains the finished HTML structure and CSS styling, giving us a game board that shows the two players' information (as seen above), but with the spinner and results paragraph displayed on top of one another. You just have to write the JavaScript code.</p> + </li> + <li> + <p>Inside the empty {{htmlelement("script")}} element on your page, start by adding the following lines of code that define some constants and variables you'll need in the rest of the code:</p> + + <pre class="brush: js notranslate">const spinner = document.querySelector('.spinner p'); +const spinnerContainer = document.querySelector('.spinner'); +let rotateCount = 0; +let startTime = null; +let rAF; +const btn = document.querySelector('button'); +const result = document.querySelector('.result');</pre> + + <p>In order, these are:</p> + + <ol> + <li>A reference to the spinner, so you can animate it.</li> + <li>A reference to the {{htmlelement("div")}} element that contains the spinner, used for showing and hiding it.</li> + <li>A rotate count. This determines how much you want to show the spinner rotated on each frame of the animation.</li> + <li>A null start time. This will be populated with a start time when the spinner starts spinning.</li> + <li>An uninitialized variable to later store the {{domxref("Window.requestAnimationFrame", "requestAnimationFrame()")}} call that animates the spinner.</li> + <li>A reference to the Start button.</li> + <li>A reference to the results paragraph.</li> + </ol> + </li> + <li> + <p>Next, below the previous lines of code, add the following function. It simply takes two numbers and returns a random number between the two. You'll need this to generate a random timeout interval later on.</p> + + <pre class="brush: js notranslate">function random(min,max) { + var num = Math.floor(Math.random()*(max-min)) + min; + return num; +}</pre> + </li> + <li> + <p>Next add the <code>draw()</code> function, which animates the spinner. This is very similar to the version from the simple spinner example, earlier:</p> + + <pre class="brush: js notranslate">function draw(timestamp) { + if(!startTime) { + startTime = timestamp; + } + + rotateCount = (timestamp - startTime) / 3; + + if(rotateCount > 359) { + rotateCount %= 360; + } + + spinner.style.transform = 'rotate(' + rotateCount + 'deg)'; + rAF = requestAnimationFrame(draw); +}</pre> + </li> + <li> + <p>Now it is time to set up the initial state of the app when the page first loads. Add the following two lines, which simply hide the results paragraph and spinner container using <code>display: none;</code>.</p> + + <pre class="brush: js notranslate">result.style.display = 'none'; +spinnerContainer.style.display = 'none';</pre> + </li> + <li> + <p>Next, define a <code>reset()</code> function, which sets the app back to the original state required to start the game again after it has been played. Add the following at the bottom of your code:</p> + + <pre class="brush: js notranslate">function reset() { + btn.style.display = 'block'; + result.textContent = ''; + result.style.display = 'none'; +}</pre> + </li> + <li> + <p>Okay, enough preparation! It's time to make the game playable! Add the following block to your code. The <code>start()</code> function calls <code>draw()</code> to start the spinner spinning and display it in the UI, hides the <em>Start</em> button so you can't mess up the game by starting it multiple times concurrently, and runs a <code>setTimeout()</code> call that runs a <code>setEndgame()</code> function after a random interval between 5 and 10 seconds has passed. The following block also adds an event listener to your button to run the <code>start()</code> function when it is clicked.</p> + + <pre class="brush: js notranslate">btn.addEventListener('click', start); + +function start() { + draw(); + spinnerContainer.style.display = 'block'; + btn.style.display = 'none'; + setTimeout(setEndgame, random(5000,10000)); +}</pre> + + <div class="blockIndicator note"> + <p><strong>Note</strong>: You'll see this example is calling <code>setTimeout()</code> without storing the return value. (So, not <code>let myTimeout = setTimeout(functionName, interval)</code>.) </p> + + <p>This works just fine, as long as you don't need to clear your interval/timeout at any point. If you do, you'll need to save the returned identifier!</p> + </div> + + <p>The net result of the previous code is that when the <em>Start</em> button is pressed, the spinner is shown and the players are made to wait a random amount of time before they are asked to press their button. This last part is handled by the <code>setEndgame()</code> function, which you'll define next.</p> + </li> + <li> + <p>Add the following function to your code next:</p> + + <pre class="brush: js notranslate">function setEndgame() { + cancelAnimationFrame(rAF); + spinnerContainer.style.display = 'none'; + result.style.display = 'block'; + result.textContent = 'PLAYERS GO!!'; + + document.addEventListener('keydown', keyHandler); + + function keyHandler(e) { + console.log(e.key); + if(e.key === 'a') { + result.textContent = 'Player 1 won!!'; + } else if(e.key === 'l') { + result.textContent = 'Player 2 won!!'; + } + + document.removeEventListener('keydown', keyHandler); + setTimeout(reset, 5000); + }; +}</pre> + + <p>Stepping through this:</p> + + <ol> + <li>First, cancel the spinner animation with {{domxref("window.cancelAnimationFrame", "cancelAnimationFrame()")}} (it is always good to clean up unneeded processes), and hide the spinner container.</li> + <li>Next, display the results paragraph and set its text content to "PLAYERS GO!!" to signal to the players that they can now press their button to win.</li> + <li>Attach a <code><a href="/en-US/docs/Web/API/Document/keydown_event">keydown</a></code> event listener to the document. When any button is pressed down, the <code>keyHandler()</code> function is run.</li> + <li>Inside <code>keyHandler()</code>, the code includes the event object as a parameter (represented by <code>e</code>) — its {{domxref("KeyboardEvent.key", "key")}} property contains the key that was just pressed, and you can use this to respond to specific key presses with specific actions.</li> + <li>Log <code>e.key</code> to the console, which is a useful way of finding out the <code>key</code> value of different keys you are pressing.</li> + <li>When <code>e.key</code> is "a", display a message to say that Player 1 won, and when <code>e.key</code> is "l", display a message to say Player 2 won. (<strong>Note:</strong> This will only work with lowercase a and l — if an uppercase A or L is submitted (the key plus <kbd>Shift</kbd>), it is counted as a different key!)</li> + <li>Regardless of which one of the player control keys was pressed, remove the <code>keydown</code> event listener using {{domxref("EventTarget.removeEventListener", "removeEventListener()")}} so that once the winning press has happened, no more keyboard input is possible to mess up the final game result. You also use <code>setTimeout()</code> to call <code>reset()</code> after 5 seconds — as explained earlier, this function resets the game back to its original state so that a new game can be started.</li> + </ol> + </li> +</ol> + +<p>That's it—you're all done!</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you get stuck, check out <a href="https://mdn.github.io/learning-area/javascript/asynchronous/loops-and-intervals/reaction-game.html">our version of the reaction game</a> (see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/loops-and-intervals/reaction-game.html">source code</a> also).</p> +</div> + +<h2 id="Conclusion">Conclusion</h2> + +<p>So that's it — all the essentials of async loops and intervals covered in one article. You'll find these methods useful in a lot of situations, but take care not to overuse them! Because they still run on the main thread, heavy and intensive callbacks (especially those that manipulate the DOM) can really slow down a page if you're not careful.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/a_first_splash/index.html b/files/pt-br/learn/javascript/first_steps/a_first_splash/index.html new file mode 100644 index 0000000000..1d5498ab11 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/a_first_splash/index.html @@ -0,0 +1,683 @@ +--- +title: Um primeiro mergulho no JavaScript +slug: Learn/JavaScript/First_steps/A_first_splash +translation_of: Learn/JavaScript/First_steps/A_first_splash +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Agora você poderá aprender um pouco sobre a Teoria do Javascript e o que você poderá fazer com ele. Nós vamos lhe fornecer aqui um Curso rápido sobre as características básicas do JavaScript através de um tutorial completamente prático. Você irá construir um simples jogo de "Adivinhe o número", passo a passo. </p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimentos básicos de informática, uma compreensão básica de HTML e CSS, uma compreensão do que é JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Ter um primeiro bit de experiência em escrever um pouco de JavaScript, e adquirir pelo menos uma compreensão básica do que envolve escrever um programa em JavaScript.</p> + </td> + </tr> + </tbody> +</table> + +<p>Nós não esperamos que você entenda todo o código imediatamente - Apenas queremos ensinar-lhe os melhores conceitos por enquanto e dar a você uma idéia de como o JavaScript (e outras linguagens de programação) funcionam. Em artigos posteriores você vai rever todos esses recursos com muito mais detalhes!</p> + +<div class="note"> +<p><strong>Nota</strong>: Muitos dos recursos de código que você verá no JavaScript são iguais aos de outra linguagem de programação - funções, loops, etc. A sintaxe do código parece diferente, mas os conceitos ainda são praticamente os mesmos.</p> +</div> + +<h2 id="Pensando_como_um_Programador">Pensando como um Programador</h2> + +<p>Uma das coisas mais difíceis de aprender na programação não é a sintaxe que você precisa aprender, mas como aplicá-la para resolver problemas do mundo real. Você precisa começar a pensar como um programador - isso geralmente envolve olhar para as descrições do que seu programa precisa fazer e analisar como eles podem ser aplicados na solução real (prática), quais recursos de código são necessários para alcançar esse objetivo, e como fazê-los trabalhar em conjunto.</p> + +<p>Isso requer um mistura de trabalho duro, experiência com a sintaxe de programação utilizada e prática, além de um pouco de criatividade, é claro. Quanto mais você programa, melhor programador se torna. Nós não prometemos transformar seu cérebro em um "cérebro de programador" em 5 minutos, mas vamos te dar todas as oportunidades para pensar na prática como um programador ao longo deste curso. </p> + +<p>Com isso em mente, vejamos o exemplo que estaremos construindo neste artigo e analisaremos o processo geral de dissecá-lo em tarefas tangíveis.</p> + +<p> </p> + +<h2 id="Exemplo_—_Jogo_adivinhe_um_número">Exemplo — Jogo adivinhe um número</h2> + +<p>Neste artigo vamos mostrar a você como construir este simples jogo, que pode ser visto abaixo:</p> + +<div class="hidden"> +<h6 id="Top_hidden_code">Top hidden code</h6> + +<p> </p> + +<pre class="brush: html"><!DOCTYPE html> +<html> + +<head> + <meta charset="utf-8"> + <title>Jogo adivinhe o número</title> + <style> + html { + font-family: sans-serif; + } + + body { + width: 50%; + max-width: 800px; + min-width: 480px; + margin: 0 auto; + } + + .lastResult { + color: white; + padding: 3px; + } + </style> +</head> + +<body> + <h1>Jogo Adivinhe um número</h1> + <p>Selecionamos um número aleatório entre 1 e 100. Veja se consegue adivinhar em 10 chances ou menos. Lhe diremos se seu palpite está com valor alto ou baixo.</p> + <div class="form"> <label for="guessField">Digite seu palpite: </label><input type="text" id="guessField" class="guessField"> <input type="submit" value="Enviar palpite" class="guessSubmit"> </div> + <div class="resultParas"> + <p class="guesses"></p> + <p class="lastResult"></p> + <p class="lowOrHi"></p> + </div> +</body> +<script> + // Seu JavaScipt vem aqui + var randomNumber = Math.floor(Math.random() * 100) + 1; + var guesses = document.querySelector('.guesses'); + var lastResult = document.querySelector('.lastResult'); + var lowOrHi = document.querySelector('.lowOrHi'); + var guessSubmit = document.querySelector('.guessSubmit'); + var guessField = document.querySelector('.guessField'); + var guessCount = 1; + var resetButton; + + function checkGuess() { + var userGuess = Number(guessField.value); + if (guessCount === 1) { + guesses.textContent = 'Palpites anteriores: '; + } + + guesses.textContent += userGuess + ' '; + + if (userGuess === randomNumber) { + lastResult.textContent = 'Parabéns! Seu número está certo!'; + lastResult.style.backgroundColor = 'green'; + lowOrHi.textContent = ''; + setGameOver(); + } else if (guessCount === 10) { + lastResult.textContent = '!!!FIM DE JOGO!!!'; + lowOrHi.textContent = ''; + setGameOver(); + } else { + lastResult.textContent = 'Errado!'; + lastResult.style.backgroundColor = 'red'; + if(userGuess < randomNumber) { + lowOrHi.textContent='Seu palpite está muito baixo!' ; + } else if(userGuess > randomNumber) { + lowOrHi.textContent = 'Seu palpite está muito alto!'; + } + } + + guessCount++; + guessField.value = ''; + } + + guessSubmit.addEventListener('click', checkGuess); + + function setGameOver() { + guessField.disabled = true; + guessSubmit.disabled = true; + resetButton = document.createElement('button'); + resetButton.textContent = 'Iniciar novo jogo'; + document.body.appendChild(resetButton); + resetButton.addEventListener('click', resetGame); + } + + function resetGame() { + guessCount = 1; + var resetParas = document.querySelectorAll('.resultParas p'); + for(var i = 0 ; i < resetParas.length ; i++) { + resetParas[i].textContent=''; + } + + resetButton.parentNode.removeChild(resetButton); + guessField.disabled = false; + guessSubmit.disabled = false; + guessField.value=''; + guessField.focus(); + lastResult.style.backgroundColor='white'; + randomNumber=Math.floor(Math.random() * 100) + 1; + } +</script> + +</html></pre> + +<p> </p> +</div> + +<p>{{ EmbedLiveSample('Top_hidden_code', '100%', 320) }}</p> + +<p>Vá em frente e jogue por um tempo para se familiarizar com o jogo antes de continuar.</p> + +<p>Vamos imaginar que o seu chefe te deu as seguintes diretrizes para criar este jogo:</p> + +<blockquote> +<p>Quero que você crie um jogo simples do tipo adivinhe um número. Ele deve gerar um número aleatório de 1 a 100, depois desafiar o jogador a adivinhar o número em 10 rodadas. A cada rodada deve ser dito ao jogador se ele está certo ou errado, se estiver errado, deve ser dito se o palpite é muito baixo ou muito alto. Também deve ser mostrado ao jogador os números que ele tentou adivinhar anteriormente. O jogo termina se o jogador acertar o número ou acabarem o número de tentativas. Quando o jogo acabar, deve ser dado ao jogador a opção de jogar novamente.</p> +</blockquote> + +<p>Olhando para o enunciado, a primeira coisa que devemos fazer é quebrá-lo em pequenas tarefas, da forma mais parecida com o pensamento de um programador quanto possível:</p> + +<ol> + <li>Gerar um número aleatório entre 1 e 100.</li> + <li>Gravar o número do turno que o jogador está. Iniciar em 1.</li> + <li>Dar ao jogador uma forma de adivinhar o número.</li> + <li>Após a tentativa ter sido submetida, primeiro gravar em algum lugar para que o usuário possa ver as tentativas anteriores.</li> + <li>Depois, verificar se o palpite está correto.</li> + <li>Se estiver correto: + <ol> + <li>Escrever mensagem de parabéns.</li> + <li>Impedir que o jogador insira mais respostas (isso pode bugar o jogo).</li> + <li>Mostrar controle que permita ao jogador reiniciar o jogo.</li> + </ol> + </li> + <li>Se o palpite estiver errado e o jogador ainda tem turnos sobrando: + <ol> + <li>Dizer ao jogador que ele está errado.</li> + <li>Permitir que ele insira outra resposta.</li> + <li>Incrementar o número do turno em 1.</li> + </ol> + </li> + <li>Se o jogador está errado mas não tem turnos sobrando: + <ol> + <li>Dizer ao jogador que o jogo acabou.</li> + <li>Impedir que o jogador insira mais respostas (isso pode bugar o jogo).</li> + <li>Mostrar controle que permita ao jogador reiniciar o jogo.</li> + </ol> + </li> + <li>Quando reiniciar, tenha certeza de resetar todas as variáveis e a interface do jogo, então volte para o passo 1.</li> +</ol> + +<p>Então vamos em frente, olhando como podemos transformar esses passos em código, construindo esse exemplo e explorando as ferramentas do JavaScript ao longo do caminho.</p> + +<h3 id="Configuração_Inicial">Configuração Inicial</h3> + +<p>Para iniciar este tutorial, gostaríamos que você fizesse uma cópia do arquivo <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/first-splash/jogo-advinhe-o-numero-inicio.html">jogo-adivinhe-o-numero-inicio.html</a> (<a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/first-splash/jogo-advinhe-o-numero-inicio.html">ver demonstração</a>). Abra-o em um editor de texto e também no seu browser. No momento você vai apenas ver um simples cabeçalho, parágrafo de instruções e um formulário para entrada de informações, mas o formulário não fará nada por enquanto.</p> + +<p>O lugar em que começaremos a escrever nosso código será dentro da tag {{htmlelement("script")}} na parte inferior do HTML:</p> + +<pre class="brush: html"><script> + + // Seu JavaScript vai aqui + +</script> +</pre> + +<h3 id="Adicionando_variáveis_para_armazenar_nossos_dados">Adicionando variáveis para armazenar nossos dados</h3> + +<p>Vamos começar. Primeiramente, adicione as seguintes linhas na sua tag {{htmlelement("script")}} :</p> + +<pre class="brush: js">var numeroAleatorio= Math.floor(Math.random() * 100) + 1; + +var palpites = document.querySelector('.palpites'); +var ultimoResultado = document.querySelector('.ultimoResultado'); +var baixoOuAlto = document.querySelector('.baixoOuAlto'); + +var envioPalpite = document.querySelector('.envioPalpite'); +var campoPalpite = document.querySelector('.campoPalpite'); + +var contagemPalpites = 1; +var botaoReinicio;</pre> + +<p>Aqui estamos setando as variáveis que precisamos para guardar os dados que nosso programa irá utilizar. Variáveis são basicamente recipientes para valores (como números, ou strings ou textos). Variáveis são criadas com a palavra-chave <code>var</code> seguida de um nome para sua variável. Você pode atribuir um valor para sua variável com um sinal de igual (<code>=</code>) seguido do valor que você quer dar a ela.</p> + +<p>No nosso exemplo:</p> + +<ul> + <li>À primeira variável — <code>numeroAleatorio</code> — é atribuído um número aleatório entre 1 e 100, calculado usando um algoritmo matemático.</li> + <li>As próximas três variáveis são criadas para guardar uma referência para os parágrafos resultantes em nosso HTML, e são usadas para inserir valores nos parágrafos no código: + <pre class="brush: html"><p class="palpites"></p> +<p class="ultimoResultado"></p> +<p class="baixoOuAlto"></p></pre> + </li> + <li>As próximas duas variáveis armazenam referências para o campo de texto e o botão de envio e são usados para controlar o envio do palpite. + <pre class="brush: html"><label for="campoPalpite">Digite seu palpite: </label><input type="text" id="campoPalpite" class="campoPalpite"> +<input type="submit" value="Enviar palpite" class="envioPalpite"></pre> + </li> + <li>As últimas duas variáveis (contagemPalpites e botaoReinicio) são usadas para armazenar a contagem dos palpites do usuário, e o outro é uma referência para o botão de reset, que não existe ainda (mas irá existir).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Você irá aprender muito mais sobre variáveis a partir do <a href="https://developer.mozilla.org/en-US/docs/user:chrisdavidmills/variables">próximo artigo</a>.</p> +</div> + +<h3 id="Funções">Funções</h3> + +<p>Em seguida, adicione o seguinte código abaixo do JavaScript anterior:</p> + +<pre class="brush: js">function conferirPalpite() { + alert('Eu sou um placeholder'); +}</pre> + +<p>Funções são blocos reutilizáveis de código que você pode escrever uma vez e executá-lo de novo e de novo, eliminando a necessidade de repetir o código todas as vezes. Isso é realmente útil. Há várias formas de se definir funções, mas, por agora, vamos nos concentrar em um tipo simples. Aqui nós definimos uma função usando a palavra chave <code>function</code>, seguida de um nome, com parênteses colocados na sequência. Depois disso nós colocamos duas chaves (<code>{ }</code>). Dentro das chaves vai todo o código que queremos executar sempre que chamarmos a função.</p> + +<p>O código é executado digitando o nome da função seguido pelos parênteses.</p> + +<p>Tente salvar o seu código agora e atualizá-lo no navegador.</p> + +<p>Vá até o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a>, e insirá a seguinte linha:</p> + +<pre class="brush: js">conferirPalpite();</pre> + +<p>Você deverá ver um alerta aparecer dizendo "Eu sou um placeholder"; nós definimos uma função em nosso código que cria um alerta a qualquer hora em que a chamarmos.</p> + +<div class="note"> +<p><strong>Nota</strong>: Você irá aprender muito mais sobre funções mais tarde no curso.</p> +</div> + +<h3 id="Operadores">Operadores</h3> + +<p>Os operadores JavaScript nos permite realizar testes, fazer cálculos matemáticos, unir sequências de texto, e outras coisas do tipo.</p> + +<p>Vamos salvar nosso código e atualizar a página exibida em nosso navegador. Abra o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a> se você ainda não o tiver aberto, para que possamos digitar os exemplos mostrados abaixo — digite cada um exatamente como mostrado na coluna "Exemplo", pressionando Return/Enter na sequência, e veja quais resultados são retornados. Se você não tiver fácil acesso às ferramentas de desenvolvimento do navegador você pode sempre utilizar o console embutido simples, como no exemplo abaixo:</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Console JavaScript</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class','input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + inputDiv.focus(); + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300) }}</p> + +<p>Primeiro vamos ver os operadores matemáticos, como por exemplo:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Nome</th> + <th scope="col">Exemplo</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+</code></td> + <td>Adição</td> + <td><code>6 + 9</code></td> + </tr> + <tr> + <td><code>-</code></td> + <td>Subtração</td> + <td><code>20 - 15</code></td> + </tr> + <tr> + <td><code>*</code></td> + <td>Multiplicação</td> + <td><code>3 * 7</code></td> + </tr> + <tr> + <td><code>/</code></td> + <td>Divisão</td> + <td><code>10 / 5</code></td> + </tr> + </tbody> +</table> + +<p>Você também pode usar o operador <code>+</code> para unir sequências de texto (isso é chamado de concatenação em programação). Tente inserir as seguintes linhas:</p> + +<pre class="brush: js">var nome = 'Bingo'; +nome; +var ola = ' diz olá!'; +ola; +var cumprimento = nome + ola; +cumprimento;</pre> + +<p>Há também alguns atalhos para operadores disponíveis, chamados de operadores de atribuição ampliada (ou atribuição composta). Por exemplo, se você quer adicionar uma nova sequência de texto à uma existente e retornar o resultado, você pode fazer o seguinte:</p> + +<pre class="brush: js">nome += ' diz olá!';</pre> + +<p>Isso é equivalente a:</p> + +<pre class="brush: js">nome = nome + ' diz olá!';</pre> + +<p>Quando estamos rodando testes de verdadeiro/falso (por exemplo, condicinais internas — veja {{anch("Conditionals", "abaixo")}}, usamos operadores de comparação, por exemplo:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Nome</th> + <th scope="col">Exemplo</th> + </tr> + <tr> + <td><code>===</code></td> + <td>Igualdade estrita (é estritamente o mesmo?)</td> + <td><code>5 === 2 + 4</code></td> + </tr> + <tr> + <td><code>!==</code></td> + <td>Não-igualdade (não é o mesmo?)</td> + <td><code>'Chris' !== 'Ch' + 'ris'</code></td> + </tr> + <tr> + <td><code><</code></td> + <td>Menor que</td> + <td><code>10 < 6</code></td> + </tr> + <tr> + <td><code>></code></td> + <td>Maior que</td> + <td><code>10 > 20</code></td> + </tr> + </thead> +</table> + +<h3 id="Condicionais">Condicionais</h3> + +<p>Voltando à nossa função <code>conferirPalpite()</code>, imagino que seja seguro dizer que não queremos que ela apenas exiba uma mensagem de teste (placeholder). Nós queremos verificar se o palpite do jogador está correto ou não, e responder apropriadamente.</p> + +<p>Neste ponto, substitua sua função <code>conferirPalpite()</code> atual por esta versão:</p> + +<pre class="brush: js">function conferirPalpite() { + var palpiteUsuario = Number(campoPalpite.value); + if (contagemPalpites === 1) { + palpites.textContent = 'Palpites anteriores: '; + } + palpites.textContent += palpiteUsuario + ' '; + + if (palpiteUsuario === numeroAleatorio) { + ultimoResultado.textContent = 'Parabéns! Você acertou!'; + ultimoResultado.style.backgroundColor = 'green'; + baixoOuAlto.textContent = ''; + configFimDeJogo(); + } else if (contagemPalpites === 10) { + ultimoResultado.textContent = '!!!FIM DE JOGO!!!'; + baixoOuAlto.textContent = ''; + configFimDeJogo(); + } else { + ultimoResultado.textContent = 'Errado!'; + ultimoResultado.style.backgroundColor = 'red'; + if(palpiteUsuario < numeroAleatorio) { + baixoOuAlto.textContent = 'Seu palpite está muito baixo!'; + } else if(palpiteUsuario > numeroAleatorio) { + baixoOuAlto.textContent = 'Seu palpite está muito alto!'; + } + } + + contagemPalpites++; + campoPalpite.value = ''; + campoPalpite.focus(); +}</pre> + +<p>Isso é bastante código — ufa! Vamos abordar cada seção e explicar o que faz.</p> + +<ul> + <li>A primeira linha (linha 2 no código acima) declara uma variável chamada <code>palpiteUsuario</code> e define seu valor igual ao valor inserido pelo jogador no campo de texto. Nós também rodamos esse valor através do método embutido <code>Number()</code>, apenas para ter certeza de que o valor inserido é um número.</li> + <li>Em seguida, encontramos nosso primero bloco de código condicional (linhas 3–5 no código acima). Um bloco de código condicional lhe permite executar código seletivamente, dependendo se uma condição é verdadeira ou não. Se parece um pouco com uma função, mas não é. A forma mais simples de um bloco condicional começa com a palavra chave <code>if</code>, depois os parênteses, depois as chaves. Dentro dos parênteses nós incluímos um teste. Se o teste retornar <code>true</code>(verdadeiro), o código dentro das chaves é executado. Caso contrário, não é executado, e seguimos para a próxima parte do código. Neste caso, o teste está verificando se a variável <code>contagemPalpites</code> é igual a <code>1</code> (isto é, se essa é ou não a primeira tentativa do jogador): + <pre class="brush: js">contagemPalpites === 1</pre> + Se a condição for verdadeira, nós tornamos o conteúdo do parágrafo de palpites, <code><p class="palpites"></p></code> igual a "Palpites anteriores: ". Caso contrário, o texto não é exibido.</li> + <li>A linha 6 acrescenta o valor atual de <code>palpiteUsuario</code> ao final do parágrafo <code>palpites</code>, mais um espaço em branco para que haja espaçamento entre cada palpite mostrado.</li> + <li>O próximo bloco (linhas 8–24 acima) fazem as seguintes conferências: + <ul> + <li>O primeiro <code>if(){ }</code> confere se o palpite do jogador é igual ao número aleatório (<code>numeroAleatorio</code>) definido no topo do nosso JavaScript. Se for, o jogador adivinhou corretamente o número e venceu o jogo. Então mostramos ao jogador uma mensagem de parabenização com uma agradável cor verde, limpamos o conteúdo do parágrado que informa sobre o palpite ser alto ou baixo <code><p class="baixoOuAlto"></p></code>, e executamos uma função chamada <code>configFimDeJogo()</code>, que iremos discutir mais tarde.</li> + <li>Agora nós encadeamos outro teste ao final deste anterior usando uma estrutura <code>else if(){ }</code>. Este confere se o palpite do jogador é sua última tentativa. Se for, o programa faz o mesmo que no bloco anterior, porém com uma mensagem de fim de jogo ao invés do texto de parabeninzação.</li> + <li>O bloco final encadeado ao final do código (<code>else { }</code>) contém código que só é executado se nenhum dos outros dois testes retornar verdadeiro (ou seja, o jogador não acertou o número, porém ainda tem mais tentativas restantes). Neste caso nós dizemos a ele que está errado, e então rodamos outro teste condicional para checar se o palpite foi maior ou menor do que a resposta certa, exibindo então uma mensagem apropriada para informá-lo se foi maior ou menor.</li> + </ul> + </li> + <li>As próximas três linhas da função (linhas 26–28) nos deixa preparados para o próximo palpite ser submetido. Nós somamos 1 à variável <code>contagemPalpites</code> para que o jogador use sua tentativa (<code>++</code> é uma operação de incremento — incrementa em 1), e o campo de texto do formulário de inserção seja esvaziado e focado novamente, pronto para que o próximo palpite seja inserido.</li> +</ul> + +<h3 id="Eventos">Eventos</h3> + +<p>Neste ponto temos uma função <code>conferirPalpite()</code> bem implementada, mas ela não irá fazer nada pois nós não a chamamos ainda. Idealmente nós queremos que ela seja acionada quando o botão "Enviar palpite" for pressionado, e para fazer isso precisamos usar um evento. Eventos são ações que acontencem no navegador, como um botão sendo clicado, ou uma página carregada, ou um vídeo tocando; ações as quais podemos responder executando blocos de código. Os construtores que monitoram os acontecimentos de eventos são chamados de <strong>event listeners</strong>, e os blocos de código executados em resposta ao acontecimento do evento são chamados de <strong>event handlers</strong>.</p> + +<p>Adicione a seguinte linha abaixo da chave de fechamento da sua função <code>conferirPalpite()</code>:</p> + +<pre class="brush: js">envioPalpite.addEventListener('click', conferirPalpite);</pre> + +<p>Aqui nós estamos adicionando um <em>event listener</em> ao botão <code>envioPalpite</code>. Esse é um método que aceita a inserção de dois valores (chamados de argumentos) — o tipo de envento que estamos monitorando (neste caso o evento <code>click</code>) como um <em>string</em> (sequência de texto), e o código que queremos executar quando o evento ocorrer (neste caso a função <code>conferirPalpite()</code> — note que não temos que especificar os parênteses quando estivermos escrevendo dentro de {{domxref("EventTarget.addEventListener", "addEventListener()")}}).</p> + +<p>Tente agora salvar e atualizar seu código, e seu exemplo deve funcionar agora, até um ponto. O único problema agora é que se você acertar o palpite ou ficar sem mais tentativas o jogo irá falhar, porque ainda não definimos a função <code>configFimDeJogo()</code> que deve ser executada uma vez que o jogo terminar. Vamos adicionar agora o código restante e completar a funcionalidade do nosso exemplo.</p> + +<h3 id="Finalizando_a_funcionalidade_do_jogo">Finalizando a funcionalidade do jogo</h3> + +<p>Vamos adicionar a função <code>configFimDeJogo()</code> ao final do nosso código e então explorá-lo. Adicione agora isso, abaixo do restante do seu JavaScript:</p> + +<pre class="brush: js">function configFimDeJogo() { + campoPalpite.disabled = true; + envioPalpite.disabled = true; + botaoReinicio = document.createElement('button'); + botaoReinicio.textContent = 'Iniciar novo jogo'; + document.body.appendChild(botaoReinicio); + botaoReinicio.addEventListener('click', reiniciarJogo); +}</pre> + +<ul> + <li>As primeiras duas linhas desabilitam a entrada de texto do formulário e o clique do botão, definindo a propriedade <em>disabled</em> (desabilitado) de cada um como <code>true</code> (verdadeiro). Isso é necessário, pois se não o fizermos, o usuário poderia submeter mais palpites depois do jogo ter terminado, o que iria bagunçar as coisas.</li> + <li>As próximas três linhas geram um novo elemento {{htmlelement("button")}}, define o texto de seu rótulo como "Iniciar novo jogo", e o adiciona ao final do nosso HTML existente.</li> + <li>A linha final define um monitor de evento (<em>event listener</em>) em nosso botão, para que quando seja clicado, uma função chamada <code>reiniciarJogo()</code> seja executada.</li> +</ul> + +<p>Agora precisamos definir essa função também! Adicione o seguinte código, novamente ao final do nosso JavaScript:</p> + +<pre class="brush: js">function reiniciarJogo() { + contagemPalpites = 1; + + var reiniciarParas = document.querySelectorAll('.resultadoParas p'); + for (var i = 0 ; i < reiniciarParas.length ; i++) { + reiniciarParas[i].textContent = ''; + } + + botaoReinicio.parentNode.removeChild(botaoReinicio); + + campoPalpite.disabled = false; + envioPalpite.disabled = false; + campoPalpite.value = ''; + campoPalpite.focus(); + + ultimoResultado.style.backgroundColor = 'white'; + + numeroAleatorio = Math.floor(Math.random() * 100) + 1; +}</pre> + +<p>Esse longo bloco de código redefine completamente tudo do modo como era no início do jogo, para que o jogador possa jogá-lo novamente. Ele:</p> + +<ul> + <li>Coloca o valor da variável <code>contagemPalpites</code> novamente igual a 1.</li> + <li>Limpa todos os parágrafos de informativos.</li> + <li>Remove o botão resete do nosso código.</li> + <li>Habilita os elementos do formulários, esvazia e direciona o foco ao campo de texto, pronto para que um novo palpite seja inserido.</li> + <li>Remove a cor de fundo do parágrafo <code>ultimoResultado</code>.</li> + <li>Gera um novo número aleatório para que o jogador não esteja tentando adivinhar o mesmo número novamente!</li> +</ul> + +<p><strong>Neste ponto você deve ter um jogo (simples) completamente funcional — parabéns!</strong></p> + +<p>Tudo o que temos que fazer agora neste artigo é falar sobre alguns outros recursos importantes que você já viu, mesmo que não os tenha notado ainda.</p> + +<h3 id="Loops">Loops</h3> + +<p>Uma parte do código acima que precisamos olhar mais detalhadamente é o loop <a href="/en-US/docs/Web/JavaScript/Reference/Statements/for">for</a>. Loop é um conceito muito importante em programação, que permite a você continuar executando um pedaço do código repetidamente, até que determinada condição seja satisfeita.</p> + +<p>Para começar, vá novamente até o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a> do seu navegador, e insira o seguinte:</p> + +<pre class="brush: js">for (var i = 1 ; i < 21 ; i++) { console.log(i) }</pre> + +<p>O que aconteceu? Os números de 1 a 20 foram exibidos no seu console. Isso acontece por causa do loop. Um loop <code>for</code> utiliza a inserção de três valores (argumentos):</p> + +<ol> + <li><strong>Um valor inicial</strong>: Nesse caso estamos iniciando a contagem em 1, mas poderia ser qualquer outro número que quisesse utilizar. Você pode substituir <code>i</code> por qualquer número que quiser também, mas <code>i</code> é utilizado por convenção porque é curto e fácil de lembrar.</li> + <li><strong>Uma condição de saída</strong>: Aqui nós especificamos <code>i < 21</code> — o loop irá continuar rodando até que <code>i</code> não seja mais menor que 21. Quando <code>i</code> alcançar 21, o loop não será mais executado.</li> + <li><strong>Incremento</strong>: Nós especificamos <code>i++</code>, que siginifica "adicione 1 à i". O loop irá rodar uma vez para cada valor de <code>i</code>, até que <code>i</code> alcance o valor de 21 (como abordado acima). Nesse caso, nós estamos simplesmente imprimindo o valor de <code>i</code> no console em cada iteração usando {{domxref("Console.log", "console.log()")}}.</li> +</ol> + +<p>Agora vamos olhar o loop em nosso jogo de adivinhar o número — o código seguinte pode ser encontrado dentro da função <code>reiniciarJogo()</code>:</p> + +<pre class="brush: js">var reiniciarParas = document.querySelectorAll('.resultadoParas p'); +for (var i = 0 ; i < reiniciarParas.length ; i++) { + reiniciarParas[i].textContent = ''; +}</pre> + +<p>Esse código cria uma variável contendo uma lista de todos os parágrafos dentro de <code><div class="resultadoParas"></code> usando o método {{domxref("Document.querySelectorAll", "querySelectorAll()")}}, e então faz o loop em cada um, removendo o conteúdo de texto dos mesmos.</p> + +<h3 id="Uma_pequena_discussão_sobre_objetos">Uma pequena discussão sobre objetos</h3> + +<p>Vamos adicionar uma melhoria final antes de chegarmos a essa discussão. Adicione a linha seguinte logo abaixo da linha <code>var botaoReinicio;</code> próximo ao topo do seu JavaScript, em seguida salve nosso arquivo:</p> + +<pre class="brush: js">campoPalpite.focus();</pre> + +<p>Essa linha usa o método {{domxref("HTMLElement.focus", "focus()")}} para automaticamente colocar o cursor dentro campo de texto do {{htmlelement("input")}} assim que a página carrega, significando que o usuário já pode começar a digitar o primeiro palpite, e não precisa clicar no campo do formulário primeiro. É apenas uma pequena adição, mas melhora a usabilidade — dando ao usuário uma boa dica visual do que ele deve fazer para jogar o jogo.</p> + +<p>Vamos analisar o que está acontencedo aqui com um pouco mais de detalhes. Em JavaScript, tudo é um objeto. Um objeto é uma coleção de funcionalidades relacionadas armazenadas em um único agrupamento. Você pode criar seus próprios objetos, mas isso é bastante avançado e nós não iremos abordar até mais tarde no curso. Por agora, vamos apenas discutir brevemente os objetos pré-construídos presentes em seu navegador, que lhe permite fazer várias coisas úteis.</p> + +<p>Neste caso particular, nós primeiro criamos a variável <code>campoPalpite</code> que armazena uma referência ao campo de inserção de texto do formulário em nosso HTML — a linha seguinte pode ser achada entre nossas declarações de variáveis próximas ao topo:</p> + +<pre class="brush: js">var campoPalpite = document.querySelector('.campoPalpite');</pre> + +<p>Para pegar essa referência, usamos o método {{domxref("document.querySelector", "querySelector()")}} do objeto {{domxref("document")}}. <code>querySelector()</code> pega um pedaço de informação — um <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Selectors">seletor CSS</a> que seleciona o elemento ao qual você quer referenciar.</p> + +<p>Como agora <code>campoPalpite</code> contém referência ao elemento {{htmlelement("input")}}, ele terá agora acesso a um número de propriedades (basicamente variáveis armazenadas dentro de objetos, sendo que alguns não podem ter seus valores alterados) e métodos (basicamente, funções armazenadas dentro de objetos). Um método disponível para elementos de inserção <code><input></code>, é o <code>focus()</code>, então agora podemos usar essa linha para focar o campo de inserção de texto:</p> + +<pre class="brush: js">campoPalpite.focus();</pre> + +<p>Variáveis que não contém referências a elementos de formulário não terão <code>focus()</code> disponível para elas. Por exemplo, a variável <code>palpites</code> contém referência de um elemento {{htmlelement("p")}}, e <code>contagemPalpites</code> contém um número.</p> + +<h3 id="Brincando_com_objetos_do_navegador">Brincando com objetos do navegador</h3> + +<p>Vamos brincar um pouco com alguns objetos do navegador.</p> + +<ol> + <li>Primeiro abra seu programa em um navegador.</li> + <li>Em seguida, abra as <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">ferramentas de desenvolvimento do navegador</a>, e certifique-se de que a aba do console JavaScript esteja aberta.</li> + <li>Digite <code>campoPalpite</code> e o console irá lhe mostrar que a variável contém um elemento {{htmlelement("input")}}. Você também irá notar que o console completa automaticamente os nomes de objetos existentes dentro do ambiente de execução, incluindo suas variáveis! + <ol> + <li>Agora digite o seguinte: + <pre class="brush: js">campoPalpite.value = 'Olá';</pre> + A propriedade <code>value</code> representa o valor atual inserido no campo de texto. Você verá que inserindo esse comando, nós mudamos o valor desse objeto!</li> + </ol> + </li> + <li>Agora tente digitar <code>palpites</code> e pressione <em>return</em>. O console irá mostrar que a variável contém um elemento {{htmlelement("p")}}.</li> + <li>Agora tente inserir a linha seguinte: + <pre class="brush: js">palpites.value</pre> + O navegador irá retornar <code>undefined</code>, porque <code>value</code> não existe em parágrafos.</li> + <li>Para mudar o texto dentro de um parágrafo, você precisa da propriedade {{domxref("Node.textContent", "textContent")}}. Tente isso: + <pre class="brush: js">palpites.textContent = 'Onde está meu parágrafo?';</pre> + </li> + <li>Agora algo divertido. Tente inserir as linhas abaixo, uma por uma: + <pre class="brush: js">palpites.style.backgroundColor = 'yellow'; +palpites.style.fontSize = '200%'; +palpites.style.padding = '10px'; +palpites.style.boxShadow = '3px 3px 6px black';</pre> + Cada elemento em uma página tem uma propriedade <code>style</code>, que contém um objeto no qual estão inseridos em suas propriedades todos os estilos incorporados de CSS aplicados ao respectivo elemento. Isso nos permite configurar dinamicamente novos estilos CSS nos elementos usando JavaScript.</li> +</ol> + +<h2 id="Finalizado_por_enquanto...">Finalizado por enquanto...</h2> + +<p>Então é isso, para construir o exemplo — você chegou ao final, muito bem! Teste o resultado do seu código, ou <a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/first-splash/jogo-advinhe-o-numero.html">jogue com nossa versão finalizada aqui</a>. Se você não conseguir fazer o exemplo funcionar, compare com o <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/first-splash/jogo-advinhe-o-numero.html">código fonte</a>.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}</p> diff --git a/files/pt-br/learn/javascript/first_steps/arrays/index.html b/files/pt-br/learn/javascript/first_steps/arrays/index.html new file mode 100644 index 0000000000..823b4c21f7 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/arrays/index.html @@ -0,0 +1,662 @@ +--- +title: Arrays +slug: Learn/JavaScript/First_steps/Arrays +translation_of: Learn/JavaScript/First_steps/Arrays +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Neste artigo final do módulo, nós vamos dar uma olhada em arrays - um elegante meio de armazenar uma lista de itens em uma mesmo variável. Aqui nós vemos o porquê isto é útil, depois exploraremos como criar uma array, recuperar, adicionar e remover itens armazenados em uma array, e mais.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Leitura básica sobre computadores, um básico entendimento de HTML e CSS, e conhecimento sobre o que é JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender o que é array e como manipular ela em JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="O_que_é_uma_array">O que é uma array?</h2> + +<p>Arrays são geralmente descritas como "lista de objetos"; elas são basicamente objetos que contem múltiplos valores armazenados em uma lista. Um objeto array pode ser armazenado em variáveis e ser tratado de forma muito similar a qualquer outro tipo de valor, a diferença está em podermos acessar cada valor dentro da lista individualmente, e fazer super úteis e eficientes coisas com a lista, como laço através da lista e fazer a mesma coisa para cada valor. Talvez nós pegamos uma série de produtos e seus preços armazenados em uma array, e nós queremos fazer um laço através de todos eles e mostrar em um recibo, enquanto somamos todos os preços e mostramos o preço total ao final.</p> + +<p>Se nós não tivessemos arrays, teríamos que armazenar cada item em uma variável separada, então chamar o código para mostrar e adicionar separadamente cada item. Isto seria muito mais longo de escrever, menos eficiente e mais suscetível a erros. Se nós temos 10 itens para adicionar na fatura, isto é ruim o bastante, mas e se fosse 100 itens ou 1000? Nós vamos retornar a este exemplo mais tarde neste artigo.</p> + +<p>Como no artigo anterior, vamos aprender o básico de arrays introduzindo com alguns exemplos dentro de um console JavaScript. Nós fornecemos um abaixo (você também pode <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">abrir este console</a> em uma aba separada ou janela, ou usar o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console de desenvolvedor do navegador</a> se preferir).</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class','input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + + if(document.querySelectorAll('div').length > 1) { + inputForm.focus(); + } + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Criando_uma_array">Criando uma array</h3> + +<p>Arrays são contruídas de colchetes, os quais contém uma lista de itens separada por vírgulas.</p> + +<ol> + <li>Vamos supor que queremos armazenar uma lista de compras em uma array — nós temos algo como o seguinte. Digite as linhas abaixo no seu console: + <pre class="brush: js">var shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles']; +shopping;</pre> + </li> + <li>Neste caso, cada item na array é uma string, mas tenha em mente que você pode armazenar qualquer item em uma array — string, número, objeto, outra variável, até outra array. Você pode também misturar e combinar tipos de itens — eles não têm que ser todos números, strings, etc. Tente isto: + <pre class="brush: js">var sequence = [1, 1, 2, 3, 5, 8, 13]; +var random = ['tree', 795, [0, 1, 2]];</pre> + </li> + <li>Tente criar um par de arrays você mesmo, antes de seguir em frente.</li> +</ol> + +<h3 id="Acessando_e_modificando_itens_de_uma_array">Acessando e modificando itens de uma array</h3> + +<p>Você pode acessar itens individuais em uma array usando a notação de colchetes, da mesma forma que você <a href="/en-US/Learn/JavaScript/First_steps/Useful_string_methods#Retrieving_a_specific_string_character">acessa as letras em uma string</a>.</p> + +<ol> + <li>Digite o seguinte no seu console: + <pre class="brush: js">shopping[0]; +// returns "bread"</pre> + </li> + <li>Você também pode modificar um item em uma array simplesmente dando um novo valor ao item. Tente isto: + <pre class="brush: js">shopping[0] = 'tahini'; +shopping; +// shopping vai retornar agora [ "tahini", "milk", "cheese", "hummus", "noodles" ]</pre> + + <div class="note"><strong>Note</strong>: Nós dissemos isto antes, mas como lembrete — computadores começam a contar do 0!</div> + </li> + <li>Note que uma array dentro de uma array é chamada de array multidimensional. Você pode acessar um item dentro de uma array que está localizada dentro de outra array, colocando dois conjuntos de colchetes juntos. Por exemplo, para acessar um dos itens dentro de uma array, que é o terceiro item dentro da array <code>random</code> (veja a seção anterior), nós podemos fazer algo tipo isto: + <pre class="brush: js">random[2][2];</pre> + </li> + <li>Antes de continuar, faça algumas modificações nos exemplos, crie seus próprios arrays e veja o que funciona e o que não funciona. Divirta-se!</li> +</ol> + +<h3 id="Encontrando_o_comprimento_de_uma_array">Encontrando o comprimento de uma array</h3> + +<p>Você pode encontrar o comprimento de uma array (quantos itens existem nela) exatamente do mesmo jeito que você encontra o comprimento (em caracteres) de uma string — usando a propriedade {{jsxref("Array.prototype.length","length")}}. Tente o seguinte:</p> + +<pre class="brush: js">sequence.length; +// deve retornar 7</pre> + +<p>Isto tem outras funcionalidades, mas é mais comum usar em um laço para seguir todos os itens em uma array. Então, por exemplo:</p> + +<pre class="brush: js">var sequence = [1, 1, 2, 3, 5, 8, 13]; +for (var i = 0; i < sequence.length; i++) { + console.log(sequence[i]); +}</pre> + +<p>Você irá aprender sobre laços propriamente em um artigo futuro, mas, brevemente, este código está dizendo:</p> + +<ol> + <li>Comece o laço no item número 0 na array.</li> + <li>Pare o laço no item de número igual ao comprimento da array. Isto funcionará para uma array de qualquer tamanho, mas neste caso vai parar o laço no item 7 (isto é bom, como o último item — que nós queremos que o laço cubra — é 6.</li> + <li>Para cada item, imprima no console do navegador com <code><a href="/en-US/docs/Web/API/Console/log">console.log()</a></code>.</li> +</ol> + +<h2 id="Alguns_métodos_úteis_em_array">Alguns métodos úteis em array</h2> + +<p>Nesta seção vamos ver alguns métodos relacionados a array úteis que nos permitem dividir strings em itens de array e vice-versa, e adicionar novos itens em arrays.</p> + +<h3 id="Convertendo_entre_strings_e_arrays">Convertendo entre strings e arrays</h3> + +<p>Frequentemente você vai se deparar com alguns dados contidos em uma grande e longa string, e você pode querer separar os itens em uma forma mais útil e então manipular eles, como mostrar em uma tabela. Para fazer isto, nós podemos usar o método {{jsxref("String.prototype.split()","split()")}}. Nesta forma mais simples, ela pega um parâmetro solitário, o caracter que você deseja separar da string e retorna o restante antes e depois do item separado na array.</p> + +<div class="note"> +<p><strong>Nota</strong>: Ok, isto é tecnicamente um método de string, não um método de array, mas nós podemos colocar em arrays já que cai bem.</p> +</div> + +<ol> + <li>Vamos brincar com isto para ver como funciona. Primeiro, crie uma string no seu console: + <pre class="brush: js">var myData = 'Manchester,London,Liverpool,Birmingham,Leeds,Carlisle';</pre> + </li> + <li>Agora vamos dividir isto em cada vírgula: + <pre class="brush: js">var myArray = myData.split(','); +myArray;</pre> + </li> + <li>Finalmente, tentamos encontrar o comprimento da sua nova array, e recuperar alguns itens dela: + <pre class="brush: js">myArray.length; +myArray[0]; // the first item in the array +myArray[1]; // the second item in the array +myArray[myArray.length-1]; // the last item in the array</pre> + </li> + <li>Você também pode ir no sentido oposto usando o método {{jsxref("Array.prototype.join()","join()")}}. Tente o seguinte: + <pre class="brush: js">var myNewString = myArray.join(','); +myNewString;</pre> + </li> + <li>Outro jeito de converter uma array em uma string é usar o método {{jsxref("Array.prototype.toString()","toString()")}}. <code>toString()</code> é indiscutivelmente mais simples <code>join()</code> pois não necessita um parâmetro, mas mais limitado. Com <code>join()</code> você pode especificar diferentes separadores (tente o passo 4 com um caracter diferente da vírgula). + <pre class="brush: js">var dogNames = ['Rocket','Flash','Bella','Slugger']; +dogNames.toString(); //Rocket,Flash,Bella,Slugger</pre> + </li> +</ol> + +<h3 id="Adicionando_e_removendo_itens_de_arrays">Adicionando e removendo itens de arrays</h3> + +<p>Nós ainda não falamos sobre adicionar e remover itens de uma array — vamos dar uma olhada agora. Nós vamos usar a array <code>myArray</code> que acabamos de criar na última seção. Se você não viu a última seção, primeiro crie a array no seu console:</p> + +<pre class="brush: js">var myArray = ['Manchester', 'London', 'Liverpool', 'Birmingham', 'Leeds', 'Carlisle'];</pre> + +<p>Antes de tudo, para adicionar ou remover um item no final de uma array, nós podemos usar {{jsxref("Array.prototype.push()","push()")}} e {{jsxref("Array.prototype.pop()","pop()")}} respectivamente.</p> + +<ol> + <li>note que você precisa para incluir um ou mais itens ao final da sua array. Tente isto: + <pre class="brush: js">myArray.push('Cardiff'); +myArray; +myArray.push('Bradford', 'Brighton'); +myArray; +</pre> + </li> + <li>O novo comprimento da array é retornado quando a chamada do método completa. Se você quer armazenar o novo comprimento da array em uma variável, você poderia fazer algo como isto: + <pre class="brush: js">var newLength = myArray.push('Bristol'); +myArray; +newLength;</pre> + </li> + <li>Removendo o último item da array é tão simples como um <code>pop()</code> nele. Tente isto: + <pre class="brush: js">myArray.pop();</pre> + </li> + <li>O item que foi removido é retornado quando a chamada do método completa. Para salvar o item em uma nova variável, você poderia fazer isto: + <pre class="brush: js">var removedItem = myArray.pop(); +myArray; +removedItem;</pre> + </li> +</ol> + +<p>{{jsxref("Array.prototype.unshift()","unshift()")}} e {{jsxref("Array.prototype.shift()","shift()")}} funciona exatamente do mesmo modo que <code>push()</code> e <code>pop()</code>, respectivamente, exceto que eles funcionam no começo da array, não no final.</p> + +<ol> + <li>Primeiro <code>unshift()</code> — tente os seguintes comandos: + + <pre class="brush: js">myArray.unshift('Edinburgh'); +myArray;</pre> + </li> + <li>Agora <code>shift()</code>;Tente estes! + <pre class="brush: js">var removedItem = myArray.shift(); +myArray; +removedItem;</pre> + </li> +</ol> + +<h2 id="Aprendizado_ativo_Imprimindo_aqueles_produtos!">Aprendizado ativo: Imprimindo aqueles produtos!</h2> + +<p>Vamos retornar ao exemplo que descrevemos antes — imprimindo nomes de produtos e preços em uma fatura, então totalizando os preços e imprindindo eles ao final. No exemplo editável abaixo há comentários contendo números — cada um deles marcam um lugar onde você tem que acidionar algo ao código. Eles são como segue:</p> + +<ol> + <li>Abaixo do comentário <code>// number 1</code> está um número de strings, cada uma contendo um nome de produto e preço separado por uma vírgula. Nós gostaríamos que você colocasse eles dentro de uma array e armazenasse eles na array chamada <code>products</code>.</li> + <li>Na mesma linha o comentário <code>// number 2 </code>está no começo de um laço for. Nesta linha nós temos <code>i<=0</code>, o qual é um teste condicional que faz o <a href="/en-US/Learn/JavaScript/First_steps/A_first_splash#Loops">laço for</a> parar imediatamente, porque está dizendo "pare quando <code>i</code> for menor ou igual a 0", e <code>i</code> começa em 0. Nós gostaríamos de substituir isto com um teste condicional que termina o laço quando o <code>i </code>for menor que o tamanho da array <code>products</code>.</li> + <li>Logo abaixo do comentário <code>// number 3 </code>nós queremos que você escreva uma linha de código que divide o item da array (<code>name:price</code>) em dois itens separados, um contendo somente o nome e outro só com o preço. Se você não tem certeza de como fazer isto, consulte o artigo <a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis em string </a>para alguma ajuda, ou ainda melhor, veja a seção {{anch("Converting between strings and arrays")}} neste artigo.</li> + <li>Como parte da linha de código acima, você também quer converter o preço de string para número. Se você não se lembra como fazer isto, veja o <a href="/en-US/Learn/JavaScript/First_steps/Strings#Numbers_versus_strings">artigo primeiras strings</a>.</li> + <li>Há uma variável chamada <code>total </code>que é criada e atribuída o valor 0 no começo do código. Dentro do loop (abaixo <code>// number 4</code>) nós queremos que você escreva uma linha que adicione o preço atual ao total em cada iteração do laço, então ao final do código o preço total é impresso na fatura. Você pode precisar de um <a href="/en-US/Learn/JavaScript/First_steps/Math#Assignment_operators">operador aritiméticos </a>para isto.</li> + <li>Nós queremos que você mude a linha logo abaixo de <code>// number 5</code> para que a variável <code>itemText</code> seja igual a "nome do item atual - $preço do item atual", por exemplo "Shoes - $23.99" em cada caso, então a informação correta para cada item é impressa na fatura. Esta é uma simples concatenação de string, a qual deveria ser familiar para você.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html"><h2>Live output</h2> + +<div class="output" style="min-height: 150px;"> + +<ul> + +</ul> + +<p></p> + +</div> + +<h2>Editable code</h2> + +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 410px;width: 95%"> +var list = document.querySelector('.output ul'); +var totalBox = document.querySelector('.output p'); +var total = 0; +list.innerHTML = ''; +totalBox.textContent = ''; +// number 1 + 'Underpants:6.99' + 'Socks:5.99' + 'T-shirt:14.99' + 'Trousers:31.99' + 'Shoes:23.99'; + +for (var i = 0; i <= 0; i++) { // number 2 + // number 3 + + // number 4 + + // number 5 + itemText = 0; + + var listItem = document.createElement('li'); + listItem.textContent = itemText; + list.appendChild(listItem); +} + +totalBox.textContent = 'Total: $' + total.toFixed(2); +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar totalBox = document.querySelector(\'.output p\');\nvar total = 0;\nlist.innerHTML = \'\';\ntotalBox.textContent = \'\';\n\nvar products = [\'Underpants:6.99\',\n \'Socks:5.99\',\n \'T-shirt:14.99\',\n \'Trousers:31.99\',\n \'Shoes:23.99\'];\n\nfor(var i = 0; i < products.length; i++) {\n var subArray = products[i].split(\':\');\n var name = subArray[0];\n var price = Number(subArray[1]);\n total += price;\n itemText = name + \' — $\' + price;\n\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n}\n\ntotalBox.textContent = \'Total: $\' + total.toFixed(2);'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> + +<pre class="brush: css">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background-color: #f5f9fa; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', '100%', 730, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Aprendizado_ativo_Top_5_buscadores">Aprendizado ativo: Top 5 buscadores</h2> + +<p>Um bom uso para os métodos de array como {{jsxref("Array.prototype.push()","push()")}} e {{jsxref("Array.prototype.pop()","pop()")}} está quando você está mantendo um registro de itens atuais ativos em um aplicativo web. Em uma cena animada, por exemplo, você pode ter uma array de objetos representando o gráfico de fundo mostrado atualmente, e você pode querer somente mostrar 50 por vez, para performace ou alguma razão de ordem. Como novos objetos são criados e adicionados na array, os antigos podem ser deletados da array para manter o número desejado.</p> + +<p>Neste exemplo nós vamos mostrar um uso bem mais simples — aqui nós estamos dando a você um falso site de busca, com uma caixa de busca. A idéia é que quando termos são digitados na caixa de busca, os 5 principais termos de busca anterior sejam mostrados na lista. Quando o número de termos passar de 5, o último termo começa sendo deletado. A cada vez um novo termo é adicionado ao topo, então os 5 termos anteriores são sempre mostrados.</p> + +<div class="note"> +<p><strong>Nota</strong>: Em um aplicativo de busca real, você seria, provavelmente, habilitado a clicar nos termos anteriores para retornar às pesquisas, e isto iria mostrar o reusltado atual! Nós estamos só mantendo simples, por agora.</p> +</div> + +<p>Para completar o aplicativo, nós precisamos que você:</p> + +<ol> + <li>Adicione uma linha abaixo do comentário <code>// number 1</code> que adicione o valor digitado atual na busca ao começo da array. Isto pode ser recuperado usando <code>searchInput.value</code>.</li> + <li>Adicione uma linha abaixo do comentário <code>// number 2</code> que remova o último valor no fim da array.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html"><h2>Live output</h2> +<div class="output" style="min-height: 150px;"> + +<input type="text"><button>Search</button> + +<ul> + +</ul> + +</div> + +<h2>Editable code</h2> + +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + + +<textarea id="code" class="playable-code" style="height: 370px; width: 95%"> +var list = document.querySelector('.output ul'); +var searchInput = document.querySelector('.output input'); +var searchBtn = document.querySelector('.output button'); + +list.innerHTML = ''; + +var myHistory = []; + +searchBtn.onclick = function() { + // we will only allow a term to be entered if the search input isn't empty + if (searchInput.value !== '') { + // number 1 + + // empty the list so that we don't display duplicate entries + // the display is regenerated every time a search term is entered. + list.innerHTML = ''; + + // loop through the array, and display all the search terms in the list + for (var i = 0; i < myHistory.length; i++) { + itemText = myHistory[i]; + var listItem = document.createElement('li'); + listItem.textContent = itemText; + list.appendChild(listItem); + } + + // If the array length is 5 or more, remove the oldest search term + if (myHistory.length >= 5) { + // number 2 + + } + + // empty the search input and focus it, ready for the next term to be entered + searchInput.value = ''; + searchInput.focus(); + } +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div></pre> + +<pre class="brush: css">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar searchInput = document.querySelector(\'.output input\');\nvar searchBtn = document.querySelector(\'.output button\');\n\nlist.innerHTML = \'\';\n\nvar myHistory= [];\n\nsearchBtn.onclick = function() {\n if(searchInput.value !== \'\') {\n myHistory.unshift(searchInput.value);\n\n list.innerHTML = \'\';\n\n for(var i = 0; i < myHistory.length; i++) {\n itemText = myHistory[i];\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n }\n\n if(myHistory.length >= 5) {\n myHistory.pop();\n }\n\n searchInput.value = \'\';\n searchInput.focus();\n }\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', '100%', 700, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Conclusão">Conclusão</h2> + +<p>Depois de ler este artigo, nós temos certeza que você concordará que arrays parecem muito úteis; você verá elas surgirem em todo lugar em JavaScript, frequentemente associadas com laços para fazer a mesma coisa para cada item de uma array. Nós estaremos ensinando a você todo o básico que há para saber sobre laços no próximo módulo, mas por agora você deve se dar uma palmada de incentivo e dar uma bem merecida parada; você trabalhou durante todo os artigos neste módulo!</p> + +<p>A única coisa que resta a fazer é trabalhar na avaliação deste módulo, a qual vai testar seu entendimento dos artigos anteriores a este.</p> + +<h2 id="Veja_também">Veja também</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Indexed_collections">Coleções indexadas</a> — um guia avançado guia de arrays e seus primos,<em> typed arrays</em>.</li> + <li>{{jsxref("Array")}} — a página de referência <code>Array</code> — para um guia de referência detalhado para as funcionalidades discutidas nesta página e muito mais.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">O que é JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Resolvendo problemas no JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables">Armazenando as informações que você precisa — Variáveis</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Matemática básica em JavaScript — números e operadores</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">Trabalhando com texto — strings em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis em String</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Silly_story_generator">Avaliação: geração de histórias bobas</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/gerador_de_historias_bobas/index.html b/files/pt-br/learn/javascript/first_steps/gerador_de_historias_bobas/index.html new file mode 100644 index 0000000000..cc8a8cc542 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/gerador_de_historias_bobas/index.html @@ -0,0 +1,123 @@ +--- +title: Gerador de histórias bobas +slug: Learn/JavaScript/First_steps/Gerador_de_historias_bobas +translation_of: Learn/JavaScript/First_steps/Silly_story_generator +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Nesta avaliação, você será encarregado de utilizar parte do conhecimento que você adquiriu nos artigos deste módulo e aplicá-lo para criar um aplicativo divertido que gera histórias bobas aleatórias. Divirta-se!</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Antes de tentar esta avaliação, você já deve ter trabalhado com todos os artigos deste módulo.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Testar a compreensão dos fundamentos de JavaScript, como variáveis, números, operadores, cadeias de caracteres e matrizes.</td> + </tr> + </tbody> +</table> + +<h2 id="Ponto_de_partida">Ponto de partida</h2> + +<p>Para começar esta avaliação, você deve:</p> + +<ul> + <li><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/index.html">Pegue o arquivo HTML</a> para o exemplo e salve uma cópia local deste arquivo como index.html em um novo diretório em algum local do seu computador. Este arquivo ainda contém o CSS para estilizar o exemplo contido no arquivo.</li> + <li>Vá para a <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/raw-text.txt">página que contém o texto bruto</a> e matenha-a aberta em uma aba separada do navegador em algum lugar. Você precisará dela mais tarde.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Alternativamente, você pode utilizar um site como <a class="external external-icon" href="http://jsbin.com/">JSBin</a> ou <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> para fazer a sua avaliação. Você pode colar o HTML, CSS e javaScript em um desses editores online. Se o editor online que você estiver utilizando não possuir um painel separado para javaScript, sinta-se a vontade para inseri-lo em um elemento <script> dentro da página HTML.</p> +</div> + +<h2 id="Resumo_do_projeto">Resumo do projeto</h2> + +<p>Você recebeu algum HTML/CSS em bruto e algumas strings de texto e funções de JavaScript; Você precisa escrever o JavaScript necessário para transformar este em um programa funcional, que faz o seguinte:</p> + +<ul> + <li>Gera uma história boba quando o botão "Gerar história aleatória" é pressionado.</li> + <li>Substitui o nome padrão "Bob" na história com um nome personalizado, somente se um nome personalizado for inserido no campo de texto "Inserir nome personalizado" antes que o botão de geração seja pressionado.</li> + <li>Gera outra história boba aleatória se você pressionar novamente o botão (e novamente...)</li> +</ul> + +<p>A seguinte captura de tela mostra um exemplo do que o programa concluído deve produzir:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13667/assessment-1.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Para dar-lhe mais uma ideia, <a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/assessment-finished/">dê uma olhada no exemplo concluído</a> (sem espreitar o código fonte!)</p> + +<h2 id="Passos_para_completar">Passos para completar</h2> + +<p>As seções a seguir descrevem o que você precisa fazer.</p> + +<p>Configuração básica:</p> + +<ol> + <li>Crie um novo arquivo chamado main.js, no mesmo diretório que o arquivo index.html.</li> + <li>Aplique o arquivo JavaScript externo ao seu HTML inserindo um elemento {{htmlelement ("script")}} no seu HTML referenciando o main.js. Coloque-o antes da etiqueta de fechamento {{htmlelement("body")}}.</li> +</ol> + +<p>Variáveis e funções iniciais:</p> + +<ol> + <li>No arquivo de texto cru, copie todo o código abaixo do cabeçalho "1. COMPLETE VARIABLE AND FUNCTION DEFINITIONS" e cole-o no topo do arquivo main.js. Isso dá a você três variáveis que armazenam referências ao campo de texto "Inserir nome personalizado" (customName), o botão "Gerar história aleatória" (randomizar), E o elemento {{htmlelement ("p")}} na parte inferior do corpo HTML para onde a história será copiada (história), respectivamente. Além disso, você tem uma função chamada randomValueFromArray () que recebe um vetor e retorna um dos itens armazenados dentro do vetor aleatoriamente.</li> + <li>Agora, veja a segunda seção do arquivo de texto bruto - "2. RAW TEXT STRINGS". Ele contém strings de texto que atuarão como entrada em nosso programa. Gostaríamos que você armazenasse essas strings dentro de variáveis no main.js: + <ol> + <li>Armazene a primeira, grande e longa linha de texto dentro de uma variável chamada storyText.</li> + <li>Armazene o primeiro conjunto de três strings dentro de um vetor chamado insertX.</li> + <li>Armazene o segundo conjunto de três strings dentro de um vetor chamado insertY.</li> + <li>Armazene o terceiro conjunto de três strings dentro de um vetor chamado insertZ.</li> + </ol> + </li> +</ol> + +<p>Colocando o manipulador de eventos e a função incompleta:</p> + +<ol> + <li>Agora volte ao arquivo de texto bruto.</li> + <li>Copie o código encontrado abaixo do cabeçalho "3. EVENT LISTENER AND PARTIAL FUNCTION DEFINITION" E cole ele na parte inferior do arquivo main.js. Isto: + <ul> + <li>Adicione um ouvinte de evento de clique à variável randomize para que, quando o botão que ele representa, for clicado, a função <code>result()</code> seja executada.</li> + <li>Adicione a função <code>result()</code> parcialmente concluída ao seu código. Para o restante da avaliação, você estará preenchendo linhas dentro desta função para completá-la e fazê-la funcionar corretamente.</li> + </ul> + </li> +</ol> + +<p>Completando a função <code>result()</code>:</p> + +<ol> + <li>Crie uma nova variável chamada <code>newStory</code>, e defina seu valor como igual a <code>storyText</code>. Isso é necessário para que possamos criar uma nova história aleatória toda vez que o botão for pressionado e a função for executada. Se fizermos alterações diretamente no <code>storyText</code>, só poderemos gerar uma nova história uma vez.</li> + <li>Crie três novas variáveis chamadas <code>xItem</code>, <code>yItem</code>, e <code>zItem</code>, e torne-as iguais ao resultado da chamada da função <code>randomValueFromArray()</code> em seus três arrays (o resultado em cada caso será um item aleatório de cada array em que é chamado). Por exemplo, você pode chamar a função e fazer com que ela retorne uma string aleatória de <code>insertX</code> escrevendo <code>randomValueFromArray(insertX)</code>.</li> + <li>Em seguida, queremos substituir os três espaços reservados na variável <code>newStory</code> — <code>:insertx:</code>, <code>:inserty:</code>, e <code>:insertz:</code> — com strings armazenadas em <code>xItem</code>, <code>yItem</code>, e <code>zItem</code>. Existe um método de string específico que irá ajudá-lo aqui - em cada caso, faça a chamada para o método igual a <code>newStory</code>,então cada vez que é chamado, newStory é igual a si mesmo, mas com substituições feitas. Assim, cada vez que o botão é pressionado, esses espaços reservados são substituídos por uma string boba aleatória. Como uma dica adicional, o método em questão substitui apenas a primeira ocorrência da subseqüência de caracteres encontrada, portanto, talvez seja necessário fazer uma das chamadas duas vezes.</li> + <li>Dentro do primeiro bloco <code>if</code>, adicione outra chamada de método de substituição de string para substituir o nome 'Bob' encontrado na string <code>newStory</code> pela variável <code>name</code>. Neste bloco estamos dizendo "Se um valor foi inserido na entrada de texto <code>customName</code>, substitua Bob na história por esse nome personalizado ".</li> + <li>Dentro do segundo bloco <code>if</code>, estamos verificando se o botão de opção <code>uk</code> foi selecionado. Se assim for, converteremos os valores de peso e temperatura na história de libras e Fahrenheit em graus centígrados. O que você precisa fazer é o seguinte: + <ol> + <li>Procure as fórmulas para converter libras em pedras e Fahrenheit em centígrados.</li> + <li>Dentro da linha que define a variável <code>weight</code>, substitua 300 por um cálculo que converta 300 libras em pedras. Concatene <code>' stone'</code> no final do resultado da chamada geral <code>Math.round()</code>.</li> + <li>Dentro da linha que define a variável <code>temperature</code>, substitua 94 por um cálculo que converta 94 graus Fahrenheit em graus centígrados. Concatene <code>' centigrade'</code> no resultado da chamada geral <code>Math.round()</code>.</li> + <li>Apenas sob as duas definições de variáveis, adicione mais duas linhas de substituição de string que substituem '94 fahrenheit' pelo conteúdo da variável <code>temperature</code>, e '300 libras' com o conteúdo da variável <code>weight</code>.</li> + </ol> + </li> + <li>Finalmente, na segunda e última linha da função, torne a propriedade<code>textContent</code> da variável <code>story</code> (que faz referência ao parágrafo) igual a <code>newStory</code>.</li> +</ol> + +<h2 id="Dicas_e_sugestões">Dicas e sugestões</h2> + +<ul> + <li>Você não precisa editar o HTML de nenhuma maneira, exceto para adicionar o JavaScript ao seu HTML.</li> + <li>Se você não tiver certeza se o JavaScript é aplicado ao seu HTML corretamente, tente remover todo o restante do arquivo JavaScript temporariamente, adicionando um pouco de JavaScript que você sabe que criará um efeito óbvio, salvando e atualizando. Por exemplo, o seguinte transforma o plano de fundo do elemento {{htmlelement ("html")}} em vermelho - para que a janela inteira do navegador fique vermelha se o JavaScript for aplicado corretamente: + <pre class="brush: js">document.querySelector('html').style.backgroundColor = 'red';</pre> + </li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round">Math.round()</a> é um método JavaScript integrado que simplesmente arredonda o resultado de um cálculo para o número inteiro mais próximo.</li> +</ul> + +<h2 id="Avaliação">Avaliação</h2> + +<p>Se você estiver seguindo esta avaliação como parte de um curso organizado, você está apto a entregar seu trabalho ao seu professor/mentor para avaliação. Se você é auto-didata, então você pode consultar o guia de marcação com bastante facilidade perguntando no <a href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">tópico do Discurso da área de aprendizagem</a>, ou no no canal <a href="irc://irc.mozilla.org/mdn">#mdn</a> IRC no <a href="https://wiki.mozilla.org/IRC">IRC Mozilla</a>. Tente realizar o exercício primeiro — não há nada a ganhar com a trapaça!</p> + +<p>{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</p> diff --git a/files/pt-br/learn/javascript/first_steps/index.html b/files/pt-br/learn/javascript/first_steps/index.html new file mode 100644 index 0000000000..a7b30d2ad0 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/index.html @@ -0,0 +1,73 @@ +--- +title: Primeiros passos com JavaScript +slug: Learn/JavaScript/First_steps +tags: + - Arrays + - Artigo + - Assessment + - Beginner + - CodingScripting + - Guia(2) + - Guide + - Iniciante + - JavaScript + - Landing + - Matrizes + - Module + - NeedsTranslation + - Numbers + - Operadores + - Operators + - TopicStub + - Variables + - maths + - strings +translation_of: Learn/JavaScript/First_steps +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Em nosso primeiro módulo de JavaScript, vamos responder algumas questões fundamentais como "o que é JavaScript?", "com o que se parece?", e "o que ele pode fazer?", antes de levá-lo a sua primeira experiência em escrever JavaScript. Depois disso, vamos discutir em detalhes algumas peças chaves, como variáveis, cadeias de caracteres (<em>strings</em>), números (<em>numbers</em>) e matrizes (<em>arrays</em>).</p> + +<h2 id="Pré-requisitos">Pré-requisitos</h2> + +<p>Antes de iniciar esse módulo, você não precisa de nenhum conhecimento prévio de JavaScript, mas você deve ter alguma familiaridade com HTML e CSS. Te recomendamos a estudar os seguintes módulos antes de começar com o JavaScript:</p> + +<ul> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/Getting_started_with_the_web">Iniciando com a Web</a> (o que inclui uma <a href="/pt-BR/docs/Learn/Getting_started_with_the_web/JavaScript_basics">introdução rápida ao JavaScript</a>)</li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Web/Guide/HTML/Introduction">Introdução ao HTML</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/CSS/Introduction_to_CSS">Introdução ao CSS</a></li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Se você está trabalhando em um computador/tablet/outro dispositivo onde você não pode criar os seus próprio arquivos, você pode experimentar (em sua maioria) os códigos de exemplo em um programa de codificação online como <a href="http://jsbin.com/">JSBin</a> ou <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guias">Guias</h2> + +<dl> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/What_is_JavaScript">O que é JavaScript?</a></dt> + <dd>Bem vindo ao curso para iniciantes em JavaScript do MDN! No primeiro artigo nós visualizaremos o JavaScript de uma perspectiva de alto nível, respondendo a questões como "o que é?" e "o que ele pode fazer?", permitindo-lhe entender confortavelmente o objetivo do JavaScript.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho no JavaScript</a></dt> + <dd>Agora que você tem uma noção teórica do JavaScript e o que você pode fazer com ele, nós vamos lhe dar um curso intensivo sobre as funcionalidades básicas do JavaScript através de um tutorial completamente prático. Aqui você ira construir, passo a passo, um jogo simples de "Advinhe o número".</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Solucionando problemas em JavaScript</a></dt> + <dd>Quando você construiu o jogo "Adivinhe o número" no artigo anterior, talvez tenha notado que ele não funcionou. Nunca tema — este artigo visa preservá-lo de ter que arrancar seus cabelos devido a esses problemas por prover-lhe alguns exemplos simples de como consertar erros em programas JavaScript.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Variables">Armazenando a informação necessária — Variáveis</a></dt> + <dd>Após ler os últimos artigos, você agora deve saber o que é o JavaScript, o que ele pode fazer para você, como usa-lo junto a com outras tecnologias web, e como sua funcionalidade principal se parece de um alto nível. Nesse artigo nós vamos ver o que é realmente básico, vendo como trabalhar com os mais básicos blocos de construção do JavaScript — Variáveis.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Math">Matemática básica com JavaScript — números e operadores</a></dt> + <dd>Nesse ponto do curso nós iremos discutir matemática no JavaScript — como nós combinamos operadores e outras funcionalidades para manipular números para fazer nosso comando.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Strings">Manuseando textos — cadeia de caracteres (strings) em JavaScript</a></dt> + <dd>Em seguida nós colocaremos nossa atenção em strings — isso é como pedaços de texto são chamados na programação. Nesse artigos nós vamos ver todas as coisas comuns que você realmente deve saber sobre strings quando estiver aprendendo JavaScript, como criar strings, manusear aspas nas strings, e juntando elas.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis sobre cadeias de caracteres (strings)</a></dt> + <dd>Agora nós vemos o mais básico sobre strings, vamos começar a pensar sobre quais operações úteis nós podemos fazer com elas com os metótos internos, como por exemplos encontrar o tamanho do texto em uma strings, juntar e separar strings, substrituir um caractere de uma string e mais.</dd> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Arrays">Matrizes</a></dt> + <dd>No artigo final desse módulo, nós iremos ver matrizes (arrays) — um jeito fácil de armazenar lista de dados em apenas um nome de variável. Aqui nós veremos o por quê disso ser útil, então exploraremos como criar uma matriz, retornar seus dados, adicionar e remover itens armazenas em um array, e mais além disso.</dd> +</dl> + +<h2 id="Avaliação">Avaliação</h2> + +<p>A avaliação seguinte vai testar o que você entendeu sobre o básico de JavaScript coberto pelos guias acima.</p> + +<dl> + <dt><a href="/pt-BR/docs/Learn/JavaScript/First_steps/Silly_story_generator">Gerador de histórias bobas</a></dt> + <dd>Nessa avaliação você será a desafiado a usar seu conhecimento adquirido nesse módulo e aplicará criando um divertido aplicativo que gerará histórias bobas aleatórias. Divirta-se.</dd> +</dl> diff --git a/files/pt-br/learn/javascript/first_steps/matematica/index.html b/files/pt-br/learn/javascript/first_steps/matematica/index.html new file mode 100644 index 0000000000..fce74528f7 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/matematica/index.html @@ -0,0 +1,418 @@ +--- +title: Matemática básica no JavaScript — números e operadores +slug: Learn/JavaScript/First_steps/Matematica +tags: + - Artigo + - Código + - Guía + - Iniciante + - JavaScript + - Matemática + - Operadores + - Script + - aprenda + - aumentada + - incremento + - modulo +translation_of: Learn/JavaScript/First_steps/Math +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Neste ponto do curso estaremos discutindo matemática em JavaScript — Como podemos usar {{Glossary("Operador","operadores")}} e outros recursos para manipular números e fazer cálculos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico em informática, uma compreensão básica de HTML e CSS, uma compreensão do que é o JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ganhar familiaridade com o básico em matemática no JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Todo_mundo_ama_matemática">Todo mundo ama matemática</h2> + +<p>Ok, talvez não. Alguns de nós gostam de matemática, alguns de nós tem a odiado desde que tivemos que aprender a tabuada de multiplicação e divisão na escola, e alguns de nós estão em algum lugar no meio dos dois cenários. Mas nenhum de nós pode negar que a matemática é uma parte fundamental da vida sem a qual não poderíamos ir muito longe. Isso é especialmente verdadeiro quando estamos aprendendo a programar em JavaScript (ou em qualquer outra linguagem, diga-se de passagem) — muito do que fazemos se baseia no processamento de dados numéricos, cálculo de novos valores, etc. Assim você não ficará surpreso em aprender que o JavaScript tem uma configuração completa de funções matemáticas disponíveis.</p> + +<p>Este artigo discute apenas as partes básicas que você precisa saber agora.</p> + +<h3 id="Tipos_de_números">Tipos de números</h3> + +<p>Em programação, até mesmo o humilde sistema de números decimais que todos nós conhecemos tão bem é mais complicado do que você possa pensar. Usamos diferentes termos para descrever diferentes tipos de números decimais, por exemplo:</p> + +<ul> + <li><em><strong>Integers</strong> </em>(inteiros) são números inteiros, ex. 10, 400 ou -5.</li> + <li><strong>Números de ponto flutuante</strong><em> (floats)</em> tem pontos e casas decimais, por exemplo 12.5 e 56.7786543.</li> + <li><em><strong>Doubles</strong> </em>são tipos de <em>floats </em>que tem uma precisão maior do que os números de ponto flutuante padrões (significando que eles são mais precisos, possuindo uma grande quantidade de casas decimais).</li> +</ul> + +<p>Temos até mesmo diferentes tipos de sistemas numéricos! O decimal tem por base 10 (o que significa que ele usa um número entre 0–9 em cada casa), mas temos também algo como:</p> + +<ul> + <li><strong>Binário</strong> — A linguagem de menor level dos computadores; 0s e 1s.</li> + <li><strong>Octal</strong> — Base 8, usa um caractere entre 0–7 em cada coluna.</li> + <li><strong>Hexadecimal</strong> — Base 16, usa um caractere entre 0–9 e depois um entre a–f em cada coluna. Você pode já ter encontrado esses números anteriormente, trabahando com <a href="/pt-BR/docs/Aprender/CSS/Introduction_to_CSS/Valores_e_unidades#Valores_hexadecimais">cores no CSS</a>.</li> +</ul> + +<p><strong>Antes de se preocupar com seu cérebro estar derretendo, pare agora mesmo!</strong> Para um começo, vamos nos ater aos números decimais no decorrer desse curso; você raramente irá se deparar com a necessidade de começar a pensar sobre os outros tipos, se é que vai precisar algum dia.</p> + +<p>A segunda boa notícia é que, diferentemente de outras linguagens de programação, o JavaScript tem apenas um tipo de dados para números, você advinhou, {{jsxref("Number")}}. Isso significa que qualquer que seja o tipo de números com os quais você está lidando em JavaScript, você os manipula do mesmo jeito.</p> + +<h3 id="Tudo_é_número_para_mim">Tudo é número para mim</h3> + +<p>Vamos brincar rapidamente com alguns números para nos familiarizarmos com a sintaxe básica que precisamos. Insira os comandos listados abaixo em seu <a href="/pt-BR/docs/Learn/Common_questions/ferramentas_de_desenvolvimento_do_navegador">console JavaScript</a>, ou use o console simples incorporado abaixo, se preferir.</p> + +<p>{{EmbedGHLiveSample("learning-area-pt-br/javascript/introduction-to-js-1/variables/index.html", '100%', 300)}}</p> + +<p><strong><a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/variables/">Abra em uma nova janela</a></strong></p> + +<ol> + <li>Primeiramente, vamos declarar duas variáveis e as inicializar com um <em>integer</em> e um <em>float</em>, respectivamente, então digitaremos os nomes das variávei para verificar se está tudo em ordem: + + <pre class="brush: js notranslate">var meuInt = 5; +var meuFloat = 6.667; +meuInt; +meuFloat;</pre> + </li> + <li>Valores numéricos são inseridos sem aspas — tente declarar e inicializar mais duas variáveis contendo números antes de seguir em frente.</li> + <li>Agora vamos checar se nossas duas variáveis originais são do mesmo tipo de dados. Há um operador chamado {{jsxref("Operators/typeof", "typeof")}} no JavaScript que faz isso. Insira as duas linhas conforme mostradas abaixo: + <pre class="brush: js notranslate">typeof meuInt; +typeof meuFloat;</pre> + Você deve obter <code>"number"</code> de volta nos dois casos — isso torna as coisas muito mais fáceis para nós do que se diferentes tipos de números tivessem diferentes tipos de dados, e tivéssemos que lidar com eles em diferentes maneiras. Ufa!</li> +</ol> + +<h2 id="Operadores_aritméticos">Operadores aritméticos</h2> + +<p>São os operadores que utilizamos para fazer as operações aritiméticas básicas:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Nome</th> + <th scope="col">Propósito</th> + <th scope="col">Exemplo</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+</code></td> + <td>Adição</td> + <td>Adiciona um número a outro.</td> + <td><code>6 + 9</code></td> + </tr> + <tr> + <td><code>-</code></td> + <td>Subtração</td> + <td>Subtrai o número da direita do número da esquerda.</td> + <td><code>20 - 15</code></td> + </tr> + <tr> + <td><code>*</code></td> + <td>Multiplicação</td> + <td>Multiplica um número pelo outro.</td> + <td><code>3 * 7</code></td> + </tr> + <tr> + <td><code>/</code></td> + <td>Divisão</td> + <td>Divide o número da esquerda pelo número da direita.</td> + <td><code>10 / 5</code></td> + </tr> + <tr> + <td><code>%</code></td> + <td>Restante <em>(Remainder</em> - as vezes chamado de modulo)</td> + <td> + <p>Retorna o resto da divisão em números inteiros do número da esquerda pelo número da direita.</p> + </td> + <td><code>8 % 3</code> (retorna 2; como três cabe duas vezes em 8, deixando 2 como resto.)</td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Nota</strong>: Você verá algumas vezes números envolvidos em aritimética chamados de {{Glossary("Operando", "operandos")}}.</p> +</div> + +<p>Nós provavelmente não precisamos ensinar a você como fazer matemática básica, mas gostaríamos de testar seu entendimento da sintaxe envolvida. Tente inserir os exemplos abaixo no seu <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a>, ou use o console incorporado visto anteriormente, se preferir, para familiarizar-se com a sintaxe.</p> + +<ol> + <li>Primeiro tente inserir alguns exemplos simples por sua conta, como + <pre class="brush: js notranslate">10 + 7 +9 * 8 +60 % 3</pre> + </li> + <li>Você pode tentar declarar e inicializar alguns números dentro de variáveis, e tentar usá-los nas operações — as variáveis irão se comportar exatamente como os valores que elas armazenam para a finalidade das operações. Por exemplo: + <pre class="brush: js notranslate">var num1 = 10; +var num2 = 50; +9 * num1; +num2 / num1;</pre> + </li> + <li>Por último, nesta seção, tente inserir algumas expressões mais complexas, como: + <pre class="brush: js notranslate">5 + 10 * 3; +num2 % 9 * num1; +num2 + num1 / 8 + 2;</pre> + </li> +</ol> + +<p>Alguns dos exemplos do último bloco podem não ter retornado os valores que você estava esperando; a seção abaixo pode lhe explicar o porquê.</p> + +<h3 id="Precedência_de_operador">Precedência de operador</h3> + +<p>Vamos olhar para o último exemplo, assumindo que <code>num2</code> guarda o valor 50 e <code>num1</code> possui o valor 10 (como iniciado acima):</p> + +<pre class="brush: js notranslate">num2 + num1 / 8 + 2;</pre> + +<p>Como um ser humano, talvez você leia isso como <em>"50 mais 10 é igual a 60"</em>, depois <em>"8 mais 2 é igual a 10"</em>, e então <em>"60 dividido por 10 é igual a 6"</em>.</p> + +<p>No entanto seu navegador vai ler <em>"10 dividido por 8 é igual a 1.25"</em>, então <em>"50 mais 1.25 mais 2 é igual a 53.25"</em>.</p> + +<p>Isto acontence por causa da <strong>precedência de operadores</strong> — algumas operações serão aplicadas antes de outras quando calcularmos o resultado de uma soma (referida em programação como uma expressão). A precedência de operadores em JavaScript é semelhante ao ensinado nas aulas de matemática na escola — Multiplicação e divisão são realizados primeiro, depois a adição e subtração (a soma é sempre realizada da esquerda para a direita).</p> + +<p>Se você quiser substituir a precedência do operador, poderá colocar parênteses em volta das partes que desejar serem explicitamente tratadas primeiro. Então, para obter um resultado de 6, poderíamos fazer isso:</p> + +<pre class="brush: js notranslate">(num2 + num1) / (8 + 2);</pre> + +<p>Tente fazer e veja como fica.</p> + +<div class="note"> +<p><strong>Nota</strong>: Uma lista completa de todos os operadores JavaScript e suas precedências pode ser vista em <a href="/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Operator_precedence">Expressões e operadores</a>.</p> +</div> + +<h2 id="Operadores_de_incremento_e_decremento">Operadores de incremento e decremento</h2> + +<p>Às vezes você desejará adicionar ou subtrair, repetidamente, um valor de uma variável numérica. Convenientemente isto pode ser feito usando os operadores incremento <code>++</code> e decremento <code>--</code>. Usamos <code>++</code> em nosso jogo "Adivinhe o número" no primeiro artigo <a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho no JavaScript</a>, quando adicionamos 1 ao nosso <code>contagemPalpites</code> para saber quantas adivinhações o usuário deixou após cada turno.</p> + +<pre class="brush: js notranslate">contagemPalpites++;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Eles são mais comumente usado em <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Lacos_e_iteracoes">Laços e iterações</a>, que será visto no curso mais tarde. Por exemplo, digamos que você queira passar por uma lista de preços e adicionar imposto sobre vendas a cada um deles. Você usaria um loop para passar por cada valor e fazer o cálculo necessário para adicionar o imposto sobre vendas em cada caso. O incrementador é usado para mover para o próximo valor quando necessário. Na verdade, fornecemos um exemplo simples mostrando como isso é feito - <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/loop.html">verifique ao vivo</a> e observe o <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/maths/loop.html">código-fonte</a> para ver se consegue identificar os incrementadores! Veremos os <em>loops</em> detalhadamente mais adiante no curso.</p> +</div> + +<p>Vamos tentar brincar com eles no seu console. Para começar, note que você não pode aplicá-las diretamente a um número, o que pode parecer estranho, mas estamos atribuindo a variável um novo valor atualizado, não operando no próprio valor. O seguinte retornará um erro:</p> + +<pre class="brush: js notranslate">3++;</pre> + +<p>Então, você só pode incrementar uma variável existente. Tente isto: </p> + +<pre class="brush: js notranslate">var num1 = 4; +num1++;</pre> + +<p>Ok, segunda coisa estranha! Quando você fizer isso, verá um valor 4 retornado - isso ocorre porque o navegador retorna o valor atual e, <em>em seguida</em>, incrementa a variável. Você pode ver que ele foi incrementado se você retornar o valor da variável novamente:</p> + +<pre class="brush: js notranslate">num1;</pre> + +<p>Acontece a mesma coisa com <code>--</code> : tente o seguinte</p> + +<pre class="brush: js notranslate">var num2 = 6; +num2--; +num2;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Você pode fazer o navegador fazer o contrário - incrementar/decrementar a variável e depois retornar o valor, colocando o operador no início da variável ao invés do final. Tente os exemplos acima novamente, mas desta vez use <code>++num1</code> e <code>--num2</code>.</p> +</div> + +<h2 id="Operadores_de_atribuição">Operadores de atribuição</h2> + +<p>Operadores de atribuição são os que atribuem um valor à uma variável. Nós já usamos o básico, <code>=</code>, muitas vezes, simplesmente atribuindo à variável do lado ersquerdo o valor indicado do lado direito do operador:</p> + +<pre class="brush: js notranslate">var x = 3; // x contém o valor 3 +var y = 4; // y contém o valor 4 +x = y; // x agora contém o mesmo valor de y, 4</pre> + +<p>Mas existem alguns tipos mais complexos, que fornecem atalhos úteis para manter seu código mais puro e mais eficiente. Os mais comuns estão listados abaixo:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operator</th> + <th scope="col">Name</th> + <th scope="col">Purpose</th> + <th scope="col">Example</th> + <th scope="col">Shortcut for</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+=</code></td> + <td>Atribuição de adição</td> + <td>Adiciona o valor à direita ao valor da variável à esquerda e, em seguida, retorna o novo valor da variável</td> + <td><code>x = 3;<br> + x += 4;</code></td> + <td><code>x = 3;<br> + x = x + 4;</code></td> + </tr> + <tr> + <td><code>-=</code></td> + <td>Atribuição de subtração</td> + <td>Subtrai o valor à direita do valor da variável à esquerda e retorna o novo valor da variável</td> + <td><code>x = 6;<br> + x -= 3;</code></td> + <td><code>x = 6;<br> + x = x - 3;</code></td> + </tr> + <tr> + <td><code>*=</code></td> + <td>Atribuição de multiplicação</td> + <td>Multiplica o valor da variável à esquerda pelo valor à direita e retorna o novo valor da variável</td> + <td><code>x = 2;<br> + x *= 3;</code></td> + <td><code>x = 2;<br> + x = x * 3;</code></td> + </tr> + <tr> + <td><code>/=</code></td> + <td>Atribuição de divisão</td> + <td>Divide o valor da variável à esquerda pelo valor à direita e retorna o novo valor da variável</td> + <td><code>x = 10;<br> + x /= 5;</code></td> + <td><code>x = 10;<br> + x = x / 5;</code></td> + </tr> + </tbody> +</table> + +<p>Tente digitar alguns dos exemplos acima em seu console para ter uma ideia de como eles funcionam. Em cada caso, veja se você pode adivinhar qual é o valor antes de digitar a segunda linha.</p> + +<p>Note que você pode muito bem usar outros valores no lado direito de cada expressão, por exemplo:</p> + +<pre class="brush: js notranslate">var x = 3; // x contém o valor 3 +var y = 4; // y contém o valor 4 +x *= y; // x agora contém o valor 12</pre> + +<div class="note"> +<p><strong>Nota</strong>: Existem muitos <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Expressions_and_Operators#operador_atribuicao">outros operadores de atribuição disponíveis</a>, mas estes são os básicos que você deve aprender agora.</p> +</div> + +<h2 id="Aprendizado_ativo_dimensionando_uma_canvas_box">Aprendizado ativo: dimensionando uma canvas box</h2> + +<p>Neste exercício, você manipulará alguns números e operadores para alterar o tamanho de uma caixa. A caixa é desenhada usando uma API do navegador chamada {{domxref("Canvas API", "", "", "true")}}. Não há necessidade de se preocupar sobre como isso funciona, apenas concentre-se na matemática por enquanto. A largura e altura da caixa (em pixels) são definidas pelas variáveis x e y, que recebem um valor inicial de 50.</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html", '100%', 520)}}</p> + +<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html">Abrir em nova janela</a></strong></p> + +<p>Na caixa de código editável acima, há duas linhas marcadas com um comentário que gostaríamos que você atualizasse para aumentar/diminuir a caixa para determinados tamanhos, usando determinados operadores e/ou valores em cada caso. Vamos tentar o seguinte:</p> + +<ul> + <li>Altere a linha que calcula x para que a caixa ainda tenha 50px de largura, mas que 50 seja calculado usando os números 43 e 7 e um operador aritmético.</li> + <li>Altere a linha que calcula y tenha 75px de altura, mas que 75 seja calculado usando os números 25 e 3 e um operador aritmético.</li> + <li>Altere a linha que calcula x para que a caixa tenha 250px de largura, mas que 250 seja calculado usando dois números e o operador resto (modulo).</li> + <li>Altere a linha que calcula y para que a caixa tenha 150px de altura, mas que 150 seja calculado usando três números e os operadores de subtração e divisão.</li> + <li>Altere a linha que calcula x para que a caixa tenha 200px de largura, mas que 200 seja calculado usando o número 4 e um operador de atribuição.</li> + <li>Altere a linha que calcula y para que a caixa tenha 200px de altura, mas que 200 seja calculado usando os números 50 e 3, o operador de multiplicação e o operador de atribuição de adição.</li> +</ul> + +<p>Não se preocupe se você estragar totalmente o código. Você sempre pode pressionar o botão Reset para fazer as coisas funcionarem novamente. Depois de ter respondido corretamente a todas as perguntas acima, sinta-se à vontade para brincar um pouco com o código ou crie seus próprios desafios.</p> + +<h2 id="Operadores_de_comparação">Operadores de comparação</h2> + +<p>Às vezes, queremos executar testes verdadeiro / falso e, em seguida, agir de acordo, dependendo do resultado desse teste, para fazer isso, usamos <strong>operadores de comparação</strong>.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operator</th> + <th scope="col">Name</th> + <th scope="col">Purpose</th> + <th scope="col">Example</th> + </tr> + <tr> + <td><code>===</code></td> + <td>Igualdade estrita</td> + <td>Verifica se o valor da esquerda e o da direita são idênticos entre si.</td> + <td><code>5 === 2 + 4</code></td> + </tr> + <tr> + <td><code>!==</code></td> + <td>Não-igualdade-estrita</td> + <td>Verifica se o valor da esquerda e o da direita <strong>não </strong>são idênticos entre si.</td> + <td><code>5 !== 2 + 3</code></td> + </tr> + <tr> + <td><code><</code></td> + <td>Menor que</td> + <td>Verifica se o valor da esquerda é menor que o valor da direita.</td> + <td><code>10 < 6</code></td> + </tr> + <tr> + <td><code>></code></td> + <td>Maior que</td> + <td>Verifica se o valor da esquerda é maior que o valor da direita.</td> + <td><code>10 > 20</code></td> + </tr> + <tr> + <td><=</td> + <td>Menor ou igual que</td> + <td>Verifica se o valor da esquerda é menor que ou igual ao valor da direita.</td> + <td><code>3 <= 2</code></td> + </tr> + <tr> + <td>>=</td> + <td>Maior ou igual que</td> + <td>Verifica se o valor da esquerda é maior que ou igual ao valor da direita.</td> + <td><code>5 >= 4</code></td> + </tr> + </thead> +</table> + +<div class="note"> +<p><strong>Nota</strong>: Talvez você já tenha visto alguém usando <code>==</code> e<code>!=</code> afim de testar igualdade ou desigualdade em JavaScript. Estes são operadores válidos em JavaScript, mas que diferem de <code>===</code>/<code>!==</code>. As versões anteriores testam se os valores são os mesmos, mas não se os tipos de dados dos valores são os mesmos. As últimas versões estritas testam a igualdade de ambos os valores e seus tipos de dados. Elas tendem a resultar em menos erros, por isso recomendamos que você as use.</p> +</div> + +<p>Se você tentar inserir alguns desses valores em um console, verá que todos eles retornam <code>true</code>/<code>false</code> — aqueles booleanos que mencionamos no último artigo. Eles são muito úteis, pois nos permitem tomar decisões em nosso código, e eles são usados toda vez que queremos fazer uma escolha de algum tipo. Por exemplo, booleanos podem ser usados para:</p> + +<ul> + <li>Exibir o text label em um botão, dependendo se um recurso está ativado ou desativado</li> + <li>Exibir uma mensagem de 'game over' se um jogoa acabou ou uma mensagem de vitória se o jogo foi vencido</li> + <li>Exibir uma saudação sazonal correta, dependendo da época de festas</li> + <li>Aumentar ou diminuir o zoom do mapa, dependendo do nível de zoom selecionado</li> +</ul> + +<p>Veremos como codificar essa lógica quando examinarmos instruções condicionais em um artigo futuro. Por enquanto, vamos dar uma olhada em um exemplo rápido:</p> + +<pre class="brush: html notranslate"><button>Iniciar máquina</button> +<p>A máquina está parada.</p> +</pre> + +<pre class="brush: js notranslate">var btn = document.querySelector('button'); +var txt = document.querySelector('p'); + +btn.addEventListener('click', updateBtn); + +function updateBtn() { + if (btn.textContent === 'Iniciar máquina') { + btn.textContent = 'Parar máquina'; + txt.textContent = 'A máquina iniciou!'; + } else { + btn.textContent = 'Iniciar máquina'; + txt.textContent = 'A máquina está parada.'; + } +}</pre> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/conditional.html", '100%', 100)}}</p> + +<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/conditional.html">Abrir em nova janela</a></strong></p> + +<p>Você pode ver o operador de igualdade sendo usado apenas dentro da função <code>updateBtn()</code>. Neste caso, não estamos testando se duas expressões matemáticas têm o mesmo valor, estamos testando se o conteúdo de texto de um botão contém uma certa string , mas ainda é o mesmo princípio em funcionamento. Se o botão estiver dizendo "Iniciar máquina" quando for pressionado, mudaremos o rótulo para "Parar máquina" e atualizaremos o rótulo conforme apropriado. Se o botão estiver dizendo "Parar máquina" quando for pressionado, nós trocamos a tela de volta.</p> + +<div class="note"> +<p><strong>Nota</strong>: Esse controle que troca entre dois estados geralmente é chamado de <strong>toggle</strong>. Ele alterna entre um estado e outro - acender, apagar, etc.</p> +</div> + +<h2 id="Resumo">Resumo</h2> + +<p>Neste artigo, cobrimos as informações fundamentais que você precisa saber sobre números em JavaScript, por enquanto. Você verá os números sendo usados de novo e de novo, durante todo o aprendizado de JavaScript. Portanto, é uma boa ideia tirar isso do caminho agora. Se você é uma daquelas pessoas que não gosta de matemática, pode se consolar com o fato de este capítulo ser muito curto.</p> + +<p>No próximo artigo, vamos explorar o texto e como o JavaScript nos permite manipulá-lo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Se você gosta de matemática e quer saber mais sobre como ela é implementada em JavaScriot, você pode encontrar muito mais detalhes na seção principal de JavaScript do MDN. Ótimos lugares para começar são os artigos <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Numeros_e_datas">Números e datas</a> e <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Expressions_and_Operators">Expressões e operadores</a> .</p> +</div> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}</p> diff --git a/files/pt-br/learn/javascript/first_steps/o_que_e_javascript/index.html b/files/pt-br/learn/javascript/first_steps/o_que_e_javascript/index.html new file mode 100644 index 0000000000..771541b047 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/o_que_e_javascript/index.html @@ -0,0 +1,435 @@ +--- +title: O que é JavaScript? +slug: Learn/JavaScript/First_steps/O_que_e_JavaScript +tags: + - API + - Aprender + - Artigo + - Código Script + - Iniciante + - JavaScript + - Navegador + - Núcleo + - O que + - Script + - comentários + - externo + - inline + - 'l10n:prioridade' + - terceiros +translation_of: Learn/JavaScript/First_steps/What_is_JavaScript +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</div> + +<p>Sejam bem-vindos ao curso de JavaScript para iniciantes do MDN! Neste primeiro artigo vamos fazer uma análise profunda da linguagem, respondendo questões como "O que é JavaScript?", e "O que ele faz?", para você se sentir confortável com a proposta da linguagem.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré requisitos:</th> + <td>Interação básica com o computador, entendimento básico de HTML e CSS.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Se familiarizar com a linguagem, com o que ela pode fazer, e como tudo isso pode ser utilizado em um website.</td> + </tr> + </tbody> +</table> + +<h2 id="Definição_de_alto_nível">Definição de alto nível</h2> + +<p>JavaScript é uma linguagem de programação que permite a você implementar itens complexos em páginas web — toda vez que uma página da web faz mais do que simplesmente mostrar a você informação estática — mostrando conteúdo que se atualiza em um intervalo de tempo, mapas interativos ou gráficos 2D/3D animados, etc. — você pode apostar que o JavaScript provavelmente está envolvido. É a terceira camada do bolo das tecnologias padrões da web, duas das quais (<a href="/en-US/docs/Learn/HTML">HTML</a> e <a href="/en-US/docs/Learn/CSS">CSS</a>) nós falamos com muito mais detalhes em outras partes da Área de Aprendizado.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13502/cake.png" style="display: block; margin: 0 auto;"></p> + +<ul> + <li>{{glossary("HTML")}} é a linguagem de marcação que nós usamos para estruturar e dar significado para o nosso conteúdo web. Por exemplo, definindo parágrafos, cabeçalhos, tabelas de conteúdo, ou inserindo imagens e vídeos na página.</li> + <li>{{glossary("CSS")}} é uma linguagem de regras de estilo que nós usamos para aplicar estilo ao nosso conteúdo HTML. Por exemplo, definindo cores de fundo e fontes, e posicionando nosso conteúdo em múltiplas colunas.</li> + <li>{{glossary("JavaScript")}} é uma linguagem de programação que permite a você criar conteúdo que se atualiza dinamicamente, controlar múltimídias, imagens animadas, e tudo o mais que há de intessante. Ok, não tudo, mas é maravilhoso o que você pode efetuar com algumas linhas de código JavaScript.</li> +</ul> + +<p>As três camadas ficam muito bem uma em cima da outra. Vamos exemplificar com um simples bloco de texto. Nós podemos marcá-lo usando HTML para dar estrutura e propósito: </p> + +<pre class="brush: html notranslate"><p>Jogador 1: Chris</p></pre> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15586/so-html.png" style="height: 28px; width: 118px;"></p> + +<p>Nós podemos adicionar um pouco de CSS na mistura, para deixar nosso parágrafo um pouco mais atraente:</p> + +<pre class="brush: css notranslate">p { + font-family: 'helvetica neue', helvetica, sans-serif; + letter-spacing: 1px; + text-transform: uppercase; + text-align: center; + border: 2px solid rgba(0,0,200,0.6); + background: rgba(0,0,200,0.3); + color: rgba(0,0,200,0.6); + box-shadow: 1px 1px 2px rgba(0,0,200,0.4); + border-radius: 10px; + padding: 3px 10px; + display: inline-block; + cursor:pointer; +}</pre> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15587/html-e-css.png" style="height: 48px; width: 208px;"></p> + +<p>E finalmente, nós podemos adicionar JavaScript para implementar um comportamento dinâmico:</p> + +<pre class="brush: js notranslate">const para = document.querySelector('p'); + +para.addEventListener('click', atualizarNome); + +function atualizarNome() { + var nome = prompt('Insira um novo nome'); + para.textContent = 'Jogador 1: ' + nome; +} +</pre> + +<p>{{ EmbedLiveSample('Definição_de_alto_nível', '100%', 80) }}</p> + +<p>Experimente clicar no botão acima para ver o que acontece (note também que você pode encontrar essa demonstração no GitHub — veja o <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/javascript-rotulo.html">código fonte</a> ou <a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/what-is-js/javascript-rotulo.html">veja funcionar</a>)!</p> + +<p>JavaScript pode fazer muito mais do que isso — vamos explorar com mais detalhes.</p> + +<h2 id="Então_o_que_ele_pode_realmente_fazer">Então o que ele pode realmente fazer?</h2> + +<p>O núcleo da linguagem JavaScript consiste em alguns benefícios comuns da programação que permite a você fazer coisas como:</p> + +<ul> + <li>Armazenar conteúdo útil em variáveis. No exemplo acima, a propósito, nós pedimos que um novo nome seja inserido e armazenamos o nome em uma variável chamada <code>nome</code>.</li> + <li>Operações com pedaços de texto (conhecidos como "strings" em programação). No exemplo acima, nós pegamos a string "Jogador 1: " e concatenamos (juntamos) com a variável <code>nome</code> para criar o texto completo "Jogador 1: Chris".</li> + <li>Executar o código em resposta a determinados eventos que ocorrem em uma página da Web. Nós usamos o {{Event("click")}} no nosso exemplo acima para que quando clicassem no botão, rodasse o código que atualiza o texto.</li> + <li>E muito mais!</li> +</ul> + +<p>O que é ainda mais empolgante é a funcionalidade construída no topo do núcleo da linguagem JavaScript. As APIs (Application Programming Interfaces - Interface de Programação de Aplicativos) proveem a você superpoderes extras para usar no seu código JavaScript.</p> + +<p>APIs são conjuntos prontos de blocos de construção de código que permitem que um desenvolvedor implemente programas que seriam difíceis ou impossíveis de implementar. Eles fazem o mesmo para a programação que os kits de móveis prontos para a construção de casas - é muito mais fácil pegar os painéis prontos e parafusá-los para formar uma estante de livros do que para elaborar o design, sair e encontrar a madeira, cortar todos os painéis no tamanho e formato certos, encontrar os parafusos de tamanho correto e <em> depois </em> montá-los para formar uma estante de livros.</p> + +<p>Elas geralmente se dividem em duas categorias.</p> + +<p><img alt="APIs de terceiros e APIs do navegador" src="https://mdn.mozillademos.org/files/14721/browser.png" style="display: block; height: 511px; margin: 0px auto; width: 815px;"></p> + +<p><strong>APIs de navegadores</strong> já vem implementadas no navegador, e são capazes de expor dados do ambiente do computador, ou fazer coisas complexas e úteis. Por exemplo:</p> + +<ul> + <li>A <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model">API DOM (Document Object Model)</a> permite a você manipular HTML e CSS, criando, removendo e mudando HTML, aplicando dinamicamente novos estilos para a sua página, etc. Toda vez que você vê uma janela pop-up aparecer em uma página, ou vê algum novo conteúdo sendo exibido (como nós vimos acima na nossa simples demonstração), isso é o DOM em ação.</li> + <li>A <a href="https://developer.mozilla.org/en-US/docs/Web/API/Geolocation">API de Geolocalização</a> recupera informações geográficas. É assim que o <a href="https://www.google.com/maps">Google Maps</a> consegue encontrar sua localização e colocar em um mapa.</li> + <li>As APIs <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">Canvas</a> e <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API">WebGL</a> permite a você criar gráficos 2D e 3D animados. Há pessoas fazendo algumas coisas fantásticas usando essas tecnologias web — veja <a href="https://www.chromeexperiments.com/webgl">Chrome Experiments</a> e <a href="http://webglsamples.org/">webglsamples</a>.</li> + <li><a href="https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery">APIs de áudio e vídeo</a> como {{domxref("HTMLMediaElement")}} e <a href="/en-US/docs/Web/API/WebRTC_API">WebRTC</a> permitem a você fazer coisas realmente interessantes com multimídia, tanto tocar música e vídeo em uma página da web, como capturar vídeos com a sua câmera e exibir no computador de outra pessoa (veja <a href="http://chrisdavidmills.github.io/snapshot/">Snapshot demo</a> para ter uma ideia).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Muitas demonstrações acima não vão funcionar em navegadores antigos — quando você for experimentar, é uma boa ideia usar browsers modernos como Firefox, Edge ou Opera para ver o código funcionar. Você vai precisar estudar <a href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing">testes cross browser</a> com mais detalhes quando você estiver chegando perto de produzir código (código real que as pessoas vão usar).</p> +</div> + +<p><strong>APIs de terceiros</strong> não estão implementados no navegador automaticamente, e você geralmente tem que pegar seu código e informações em algum lugar da Web. Por exemplo:</p> + +<ul> + <li>A <a href="https://dev.twitter.com/overview/documentation">API do Twitter</a> permite a você fazer coisas como exibir seus últimos tweets no seu website.</li> + <li>A <a href="https://developers.google.com/maps/">API do Google Maps</a> permite a você inserir mapas customizados no seu site e outras diversas funcionalidades.</li> +</ul> + +<div class="note"> +<p><strong>Note</strong>: Essas APIs são avançadas e nós não vamos falar sobre nenhuma delas nesse módulo.Vo cê pode achar muito mais sobre elas em nosso módulo <a href="/pt-BR/docs/Learn/JavaScript/Client-side_web_APIs">APIs web no lado cliente</a>.</p> +</div> + +<p>Tem muito mais coisas disponíveis! Contudo, não fique animado ainda. Você não estará pronto para desenvolver o próximo Facebook, Google Maps ou Instagram depois de estudar JavaScript por 24 horas — há um monte de coisas básicas para estudar primeiro. E é por isso que você está aqui — vamos começar! </p> + +<h2 id="O_que_JavaScript_está_fazendo_na_sua_página_web">O que JavaScript está fazendo na sua página web?</h2> + +<p>Aqui nós vamos realmente começar a ver algum código, e enquanto fazemos isso vamos explorar o que realmente acontece quando você roda algum código JavaScript na sua página.</p> + +<p>Vamos recaptular brevemente a história do que acontece quando você carrega uma página web em um navegador (falamos sobre isso no nosso artigo <a href="/en-US/Learn/CSS/Introduction_to_CSS/How_CSS_works#How_does_CSS_actually_work">Como o CSS funciona</a>). Quando você carrega uma página web no seu navegador, você está executando seu código (o HTML, CSS e JavaScript) dentro de um ambiente de execução (a guia do navegador). Isso é como uma fábrica que pega a matéria prima (o código) e transforma em um produto (a página web).</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13504/execution.png" style="display: block; margin: 0 auto;"></p> + +<p>Um uso muito comum do JavaScript é modificar dinamicamente HTML e CSS para atualizar uma interface do usuário, por meio da API do Document Object Model (conforme mencionado acima). Observe que o código em seus documentos web geralmente é carregado e executado na ordem em que aparece na página. Se o JavaScript carregar e tentar executar antes do carregamento do HTML e CSS afetado, poderão ocorrer erros. Você aprenderá maneiras de contornar isso mais adiante neste artigo, na seção <a href="/pt-BR/docs/Learn/JavaScript/First_steps/What_is_JavaScript#Script_loading_strategies"> Estratégias de carregamento de scripts </a>.</p> + +<h3 id="Segurança_do_navegador">Segurança do navegador</h3> + +<p>Cada guia do navegador tem seu próprio espaço para executar código (esses espaços são chamados de "ambientes de execução", em termos técnicos) — isso significa que na maioria dos casos o código em cada guia está sendo executado separadamente, e o código em uma guia não pode afetar diretamente o código de outra guia — ou de outro website. Isso é uma boa medida de segurança — se esse não fosse o caso, então hackers poderiam começar a escrever código para roubar informações de outros websites, e fazer outras coisas más.</p> + +<div class="note"> +<p><strong>Nota</strong>: Há muitas maneiras de trocar código e conteúdo entre diferentes websites/guias de uma forma segura, mas são técnicas avançadas que não serão estudadas nesse curso.</p> +</div> + +<h3 id="Ordem_de_execução_do_JavaScript">Ordem de execução do JavaScript</h3> + +<p>Quando o navegador encontra um bloco de código JavaScript, ele geralmente executa na ordem, de cima para baixo. Isso significa que você precisa ter cuidado com a ordem na qual você coloca as coisas. Por exemplo, vamos voltar ao bloco JavaScript que nós vimos no primeiro exemplo:</p> + +<pre class="brush: js notranslate">const para = document.querySelector('p'); + +para.addEventListener('click', atualizarNome); + +function atualizarNome() { + ;et nome = prompt('Informe um novo nome:'); + para.textContent = 'Jogador 1: ' + nome; +}</pre> + +<p>Aqui nós estamos selecionando um parágrafo (linha 1) e anexando a ele um <em>event listener</em> (linha 3). Então, quando o parágrafo recebe um clique, o bloco de código <code>atualizarNome()</code> (linhas 5 a 8) é executado. O bloco de código <code>atualizarNome()</code>(esses tipos de bloco de código reutilizáveis são chamados "funções") pede ao usuário que informe um novo nome, e então insere esse nome no parágrafo, atualizando-o.</p> + +<p>Se você inverte a ordem das duas primeiras linhas de código, ele não fucionaria — em vez disso, você receberia um erro no console do navegador — <code>TypeError: para is undefined</code>. Isso significa que o objeto <code>para</code> não existe ainda, então nós não podemos adicionar <em>um event listener</em> a ele.</p> + +<div class="note"> +<p><strong>Nota</strong>: Esse é um erro muito comum — você precisa verificar se os objetos aos quais você se refere no seu código existem antes de você tentar anexar coisas a eles.</p> +</div> + +<h3 id="Código_interpretado_x_compilado">Código interpretado x compilado</h3> + +<p>Você pode ouvir os termos <strong>interpretado </strong>e <strong>compilado</strong> no contexto da programação. JavaScript é uma linguagem interpretada — o código é executado de cima para baixo e o resultado da execução do código é imediatamente retornado. Você não tem que transformar o código em algo diferente antes do navegador executa-lo.</p> + +<p>Linguagens compiladas, por outro lado, são transformadas (compiladas) em algo diferente antes que sejam executadas pelo computador. Por exemplo, C/C++ são compiladas em linguagem Assembly, e depois são executadas pelo computador.</p> + +<p>JavaScript é uma linguagem de programação leve e interpretada. O navegador recebe o código JavaScript em sua forma de texto original e executa o script a partir dele. Do ponto de vista técnico, a maioria dos intérpretes modernos de JavaScript realmente usa uma técnica chamada <strong>compilação just-in-time</strong> para melhorar o desempenho; o código-fonte JavaScript é compilado em um formato binário mais rápido enquanto o script está sendo usado, para que possa ser executado o mais rápido possível. No entanto, o JavaScript ainda é considerado uma linguagem interpretada, pois a compilação é manipulada em tempo de execução, e não antes.</p> + +<p>Há vantagens em ambos os tipos de linguagem, mas nós não iremos discutir no momento.</p> + +<h3 id="Lado_do_servidor_x_Lado_do_cliente">Lado do servidor x Lado do cliente</h3> + +<p>Você pode também ouvir os termos <strong>lado do servidor (<em>server-side</em>)</strong> e <strong>lado do cliente (<em>client-side</em>)</strong>, especialmente no contexto de desenvolvimento web. Códigos do lado do cliente são executados no computador do usuário — quando uma página web é visualizada, o código do lado do cliente é baixado, executado e exibido pelo navegador. Nesse módulo JavaScript nós estamos explicitamente falando sobre <strong>JavaScript do lado do cliente</strong>.</p> + +<p>Códigos do lado do servidor, por outro lado, são executados no servidor e o resultado da execução é baixado e exibido no navegador. Exemplos de linguagens do lado do servidor populares incluem PHP, Python, Ruby, e ASP.NET. E JavaScript! JavaScript também pode ser usada como uma linguagem <em>server</em><em>-side</em>, por exemplo, no popular ambiente Node.js — você pode encontrar mais sobre JavaScript do lado do servidor no nosso tópico <a href="/en-US/docs/Learn/Server-side">Websites dinâmicos - Programação do lado do servidor</a>.</p> + +<h3 id="Código_dinâmico_x_estático">Código dinâmico x estático</h3> + +<p>A palavra <strong>dinâmico</strong> é usada para descrever tanto o JavaScript <em>client-side </em>como o <em>server-side</em> — essa palavra se refere a habilidade de atualizar a exibição de uma página web/app para mostrar coisas diferentes em circunstâncias diferentes, gerando novo conteúdo como solicitado. Código do lado do servidor dinamicamente gera novo conteúdo no servidor, puxando dados de um banco de dados, enquanto que JavaScript do lado do cliente dinamicamente gera novo conteúdo dentro do navegador do cliente, como criar uma nova tabela HTML com dados recebidos do servidor e mostrar a tabela em uma página web exibida para o usuário. Os significados são ligeiramente diferente nos dois contextos, porém relacionados, e ambos (JavaScript <em>server-side</em> e <em>client-side</em>) geralmente trabalham juntos.</p> + +<p>Uma página web sem atualizações dinâmicas é chamada de <strong>estática</strong> — ela só mostra o mesmo conteúdo o tempo todo.</p> + +<h2 id="Como_você_adiciona_JavaScript_na_sua_página">Como você adiciona JavaScript na sua página?</h2> + +<p>O JavaScript é inserido na sua página de uma maneira similar ao CSS. Enquanto o CSS usa o elemento {{htmlelement("link")}} para aplicar folhas de estilo externas e o elemento {{htmlelement("style")}} para aplicar folhas de estilo internas, o JavaScript só precisa de um amigo no mundo do HTML — o elemento {{htmlelement("script")}}. Vamos aprender como funciona.</p> + +<h3 id="JavaScript_interno">JavaScript interno</h3> + +<ol> + <li>Antes de tudo, faça uma cópia local do nosso arquivo de exemplo <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/aplicando-javascript.html">aplicando-javascript.html</a>. Salve-o em alguma pasta, de uma forma sensata.</li> + <li>Abra o arquivo no seu navegador web e no seu editor de texto. Você verá que o HTML cria uma simples página web contendo um botão clicável.</li> + <li>Agora, vá até o seu editor de texto e adicione o código a seguir antes da tag de fechamento <code></body></code>: + <pre class="brush: html notranslate"><script> + + // O JavaScript fica aqui + +</script></pre> + </li> + <li>Agora nós vamos adicionar um pouco de JavaScript dentro do nosso elemento {{htmlelement("script")}} para que a página faça algo mais interessante — adicione o seguinte código abaixo da linha "// O JavaScript fica aqui": + <pre class="brush: js notranslate">function criarParagrafo() { + let para = document.createElement('p'); + para.textContent = 'Você clicou no botão!'; + document.body.appendChild(para); +} + +const botoes = document.querySelectorAll('button'); + +for(var i = 0; i < botoes.length ; i++) { + botoes[i].addEventListener('click', criarParagrafo); +}</pre> + </li> + <li>Salve seu arquivo e recarregue a página — agora você deveria ver que quando você clique no botão, um novo parágrafo é gerado e colocado logo abaixo.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Se seu exemplo não parece funcionar, leia cada passo novamente e confira que você fez tudo certo. Você salvou sua cópia local do código inicial como um arquivo .html? Você adicionou o elemento {{htmlelement("script")}} imediatamente antes da tag <code></body></code>? Você digitou o código JavaScript exatamente como ele está sendo mostrado? <strong>JavaScript é uma linguagem case sensitive (isso significa que a linguagem vê diferença entre letras maiúsculas e minúsculas) e muito confusa, então você precisa digitar a sintaxe exatamente como foi mostrada, senão não vai funcionar.</strong></p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Você pode ver essa versão no GitHub como <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/aplicando-javascript-interno.html">apicando-javascript-interno.html</a> (<a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/what-is-js/aplicando-javascript-interno.html">veja funcionar também</a>).</p> +</div> + +<h3 id="JavaScript_externo">JavaScript externo</h3> + +<p>Isso funciona muito bem, mas e se nós quiséssemos colocar nosso JavaScript em um arquivo externo? Vamos explorar isso agora.</p> + +<ol> + <li>Primeiro, crie um novo arquivo na mesma pasta que está o arquivo HTML de exemplo. Chame-o de <code>script.js</code> — tenha certeza de que o nome do arquivo tem a extensão <code>.js</code>, pois é assim que ele será reconhecido como JavaScript.</li> + <li>Agora substitua o elemento atual {{htmlelement("script")}} pelo seguinte código: + <pre class="brush: html notranslate"><script src="script.js" defer></script></pre> + </li> + <li>Em <code>script.js</code>, adidione o seguinte script: + <pre class="brush: js notranslate">function createParagraph() { + let para = document.createElement('p'); + para.textContent = 'Você clicou no botão!'; + document.body.appendChild(para); +} + +const buttons = document.querySelectorAll('button'); + +for(let i = 0; i < buttons.length ; i++) { + buttons[i].addEventListener('click', createParagraph); +}</pre> + </li> + <li>Salve e atualize seu navegador, e você deverá ver a mesma coisa! Funciona igualmente, mas agora nós temos o JavaScript em um arquivo externo. Isso é geralmente uma coisa boa em termos de organização de código, e faz com que seja possível reutilizar o código em múltiplos arquivos HTML. Além disso, o HTML fica mais legível sem grandes pedaços de script no meio dele.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Você pode ver essa versão no GitHub como <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/aplicando-javascript-externo.html">aplicando-javascript-externo.html</a> e <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/what-is-js/script.js">script.js</a> (<a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/what-is-js/aplicando-javascript-externo.html">veja funcionar também</a>).</p> +</div> + +<h3 id="Manipuladores_de_JavaScript_inline">Manipuladores de JavaScript inline</h3> + +<p>Note que às vezes você vai encontrar código JavaScript escrito dentro do HTML. Isso deve ser algo como:</p> + +<div id="inline_js_example"> +<pre class="brush: js example-bad notranslate">function criarParagrafo() { + let para = document.createElement('p'); + para.textContent = 'Você clicou o botao!'; + document.body.appendChild(para); +}</pre> + +<div id="inline_js_example"> +<pre class="brush: js example-bad notranslate"><button onclick="criarParagrafo()">Me clique!</button></pre> +</div> + +<p>Você pode tentar essa versão na nossa demonstração abaixo.</p> + +<p><iframe class="live-sample-frame hide-codepen-jsfiddle" frameborder="0" height="150" id="frame_inline_js_example" src="https://mdn.mozillademos.org/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript$samples/inline_js_example?revision=1640817" width="100%"></iframe></p> + +<p>Essa demonstração tem exatamente a mesma funcionalidade que vimos nas primeiras duas seções, exceto que o elemento {{htmlelement("button")}} inclui um manipulador <em>inline</em> <code>onclick</code> para fazer a função ser executada quando o botão é clicado.</p> + +<p><strong>Contudo, por favor, não faça isso.</strong> É uma má prática poluir seu HTML com JavaScript, e isso é ineficiente — você teria que incluir o atributo <code>onclick="criarParagrafo()"</code> em todo botão que você quisesse aplicar JavaScript.</p> + +<p>Usando uma estrutura feita de puro JavaScript permite a você selecionar todos os botões usando uma instrução. O código que nós usamos acima para servir a esse propósito se parece com isso:</p> + +<pre class="brush: js notranslate">const botoes = document.querySelectorAll('button'); + +for(var i = 0; i < botoes.length ; i++) { + botoes[i].addEventListener('click', criarParagrafo); +}</pre> + +<p>Isso talvez parece ser mais do que o atributo <code>onclick</code>, mas isso vai funcionar para todos os botões, não importa quantos tem na página, e quantos forem adicionados ou removidos. O JavaScript não precisará ser mudado.</p> + +<div class="note"> +<p><strong>Nota</strong>: Tente editar a sua versão do arquivo <code>aplicar-javascript.html</code>, adicionando alguns botões a mais. Quando você recarregar, você deverá ver que todos os botões, quando clicados, irão criar parágrafos. Agradável, não?</p> +</div> + +<h3 id="Estratégias_para_o_carregamento_de_scripts">Estratégias para o carregamento de scripts</h3> + +<p>Há um considerável número de problemas envolvendo o carregamento de scripts na ordem correta. Infelizmente, nada é tão simples quanto parece ser! Um problema comum é que todo o HTML de uma página é carregado na ordem em que ele aparece. Se você estiver usando Javascript para manipular alguns elementos da página (sendo mais preciso, manipular o <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents#The_document_object_model">Document Object Model</a>), seu código não irá funcionar caso o JavaScript for carregado e executado antes mesmo dos elementos HTML estarem disponíveis.</p> + +<p>Nos exemplos acima, tanto nos scripts internos ou externos, o JavaScript é carregado e acionado dentro do cabeçalho do documento, antes do corpo da página ser completamente carregado. Isso poderá causar algum erro. Assim, temos algumas soluções para isso.</p> + +<p>No exemplo interno, você pode ver essa estrutura em volta do código:</p> + +<pre class="brush: js notranslate">document.addEventListener("DOMContentLoaded", function() { + ... +});</pre> + +<p>Isso é um <em>event listener</em> (ouvidor de eventos<em>)</em>, que ouve e aguarda o disparo do evento "DOMContentLoaded" vindo do <em>browser</em>, evento este que significa que o corpo do HTML está completamente carregado e pronto. O código JavaScript que estiver dentro desse bloco não será executado até que o evento seja disparado, portanto, o erro será evitado (você irá <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">aprender sobre eventos</a> mais tarde).</p> + +<p>No exemplo externo, nós usamos um recurso moderno do JavaScript para resolver esse problema: Trata-se do atributo <code>defer</code>, que informa ao <em>browser</em> para continuar renderizando o conteúdo HTML uma vez que a tag <code><script></code> foi atingida.</p> + +<pre class="brush: js notranslate"><script src="script.js" defer></script></pre> + +<p>Neste caso, ambos script e HTML irão carregar de forma simultânea e o código irá funcionar.</p> + +<div class="note"> +<p><strong>Nota</strong>: No caso externo, nós não precisamos utilizar o evento <code>DOMContentLoaded</code> porque o atributo <code>defer</code> resolve o nosso problema. Nós não utilizamos <code>defer</code> como solução para os exemplos internos pois <code>defer</code> funciona apenas com scripts externos.</p> +</div> + +<p>Uma solução à moda antiga para esse problema era colocar o elemento script bem no final do body da página (antes da tag <code></body>)</code>. Com isso, os scripts iriam carregar logo após todo o conteúdo HTML. O problema com esse tipo de solução é que o carregamento/renderização do script seria completamente bloqueado até que todo o conteúdo HTML fosse analisado. Em sites de maior escala, com muitos scripts, essa solução causaria um grande problema de performance e deixaria o site lento. </p> + +<h4 id="async_e_defer">async e defer</h4> + +<p>Atualmente, há dois recursos bem modernos que podermos usar para evitar o problema com o bloqueio de scripts — <code>async</code> e <code>defer</code> (que vimos acima). Vamos ver as diferenças entre esses dois?</p> + +<p>Os scripts que são carregados usando o atributo <code>async</code> (veja abaixo) irão baixar o script sem bloquear a renderização da página e irão executar imediatamente após o script terminar de ser disponibilizado. Nesse modo você não tem garantia nenhuma que os scripts carregados irão rodar em uma ordem específica, mas saberá que dessa forma eles não irão impedir o carregamento do restante da página. O melhor uso para o <code>async</code> é quando os scripts de uma página rodam de forma independente entre si e também não dependem de nenhum outro script.</p> + +<p>Por exemplo, se você tiver os seguintes elementos script:</p> + +<pre class="brush: html notranslate"><script async src="js/vendor/jquery.js"></script> + +<script async src="js/script2.js"></script> + +<script async src="js/script3.js"></script></pre> + +<p>Você não pode garantir que o script. <code>jquery.js</code> carregará antes ou depois do <code>script2.js</code> e <code>script3.js</code> . Nesse caso, se alguma função desses scripts dependerem de algo vindo do <code>jquery</code>, ela produzirá um erro pois o <code>jquery</code> ainda não foi definido/carregado quando os scripts executaram essa função.</p> + +<p><code>async</code> deve ser usado quando houver muitos scripts rodando no <em>background</em>, e você precisa que estejam disponíveis o mais rápido possível. Por exemplo, talvez você tenha muitos arquivos de dados de um jogo para carregar que serão necessários assim que o jogo iniciar, mas por enquanto, você só quer entrar e ver a tela de carregamento, a do titulo do jogo e o <em>lobby</em>, sem ser bloqueado pelo carregamento desses scripts.</p> + +<p>Scripts que são carregados utilizando o atributo <code>defer</code> (veja abaixo) irão rodar exatamente na ordem em que aparecem na página e serão executados assim que o script e o conteúdo for baixado.</p> + +<pre class="brush: html notranslate"><script defer src="js/vendor/jquery.js"></script> + +<script defer src="js/script2.js"></script> + +<script defer src="js/script3.js"></script></pre> + +<p>Todos os scripts com o atributo <code>defer</code> irão carregar na ordem que aparecem na página. No segundo exemplo, podemos ter a certeza que o script <code>jquery.js</code> irá carregar antes do <code>script2.js</code> e <code>script3.js</code> e o <code>script2.js</code> irá carregar antes do <code>script3.js</code>. Os scripts não irão rodar sem que antes todo o conteúdo da página seja carregado, que no caso, é muito útil se os seus scripts dependem de um DOM completamente disponibilizado em tela (por exemplo, scripts que modificam um elemento).</p> + +<p>Resumindo:</p> + +<ul> + <li><code>async</code> e <code>defer</code> istruem o <em>browser</em> a baixar os scripts numa <em>thread </em>(processo)<em> </em>á parte, enquanto o resto da página (o DOM, etc.) está sendo baixado e disponibilizado de forma não bloqueante.</li> + <li>Se os seus scripts precisam rodar imediatamente, sem que dependam de outros para serem executados, use <code>async</code>.</li> + <li>Se seus scripts dependem de outros scripts ou do DOM completamente disponível em tela, carregue-os usando <code>defer</code> e coloque os elementos <code><script></code> na ordem exata que deseja que sejam carregados.</li> +</ul> + +<h2 id="Comentários">Comentários</h2> + +<p>Assim como HTML e CSS, é possível escrever comentários dentro do seu código JavaScript que serão ignorados pelo navegador, e existirão simplesmente para prover instruções aos seus colegas desenvolvedores sobre como o código funciona (e pra você, se você tiver que voltar ao seu código depois de 6 meses e não se lembrar do que fez). Comentários são muito úteis, e você deveria usá-los frequentemente, principalmente quando seus códigos forem muito grandes. Há dois tipos:</p> + +<ul> + <li>Um comentário de uma linha é escrito depois de duas barras. Por exemplo:</li> + <li> + <pre class="brush: js notranslate">// Eu sou um comentário</pre> + </li> + <li>Um comentário de múltiplas linhas é escrito entre os caracteres /* e */. Por exemplo: + <pre class="brush: js notranslate">/* + Eu também sou + um comentário +*/</pre> + </li> +</ul> + +<p>Então, por exemplo, você poderia fazer anotações na nossa última demonstração de código JavaScript, da seguinte forma:</p> + +<pre class="brush: js notranslate">// Função: Cria um novo parágrafo e o insere no fim do arquivo HTML. + +function criarParagrafo() { + var para = document.createElement('p'); + para.textContent = 'Você clicou no botão!'; + document.body.appendChild(para); +} + +/* + 1. Captura referências de todos os botões na página e armazena isso em um array. + 2. Vai até todos os botões e adiciona um event listener click a cada um deles. + + Quando cada botão é clicado, a função criarParagrafo() será executada. +*/ + +const botoes = document.querySelectorAll('button'); + +for(var i = 0; i < botoes.length ; i++) { + botoes[i].addEventListener('click', criarParagrafo); +}</pre> + +<div class="note"> +<p><strong>Nota</strong>: Em geral mais comentários são melhores que menos, porém você deve tomar cuidado para não adicionar comentários de mais tentando explicar o que uma variável é (o nome da sua variável deve ser mais intuitivo), ou tentando explicar uma operação simples (talvez seu código seja muito complicado denecessariamente).</p> +</div> + +<h2 id="Sumário">Sumário</h2> + +<p>Então, esse foi o seu primeiro passo no mundo do JavaScript. Nós iniciamos apenas com teoria, então te ensinamos porque usar JavaScript e que tipo de coisa você pode fazer com ele. Pelo caminho você viu alguns códigos de exemplo e aprendeu como JavaScript se encaixa com o resto do código do seu site, entre outras coisas.</p> + +<p>O JavaScript talvez pareça um pouco assustador agora, mas não se preocupe — nesse curso você será guiado passo a passo, e tudo vai começar a fazer sentido. No próximo artigo vamos <a href="/en-US/docs/Learn/JavaScript/Introduction_to_JavaScript_1/A_first_splash">mergulhar direto para a prática</a>, levando você a construir seu próprio código JavaScript.</p> + +<p>{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo:</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">O que é JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/A_first_splash">O primeiro contato com JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Resolvendo problemas com JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables">Armazenando a informação que você precisa - Variáveis</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Matemática básica em JavaScript — números e operadores</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">Trabalhando com texto — strings em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis para strings</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Gerador_de_historias_bobas">Avaliação: Gerador de histórias bobas</a></li> +</ul> +</div> diff --git a/files/pt-br/learn/javascript/first_steps/strings/index.html b/files/pt-br/learn/javascript/first_steps/strings/index.html new file mode 100644 index 0000000000..299c6e33a8 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/strings/index.html @@ -0,0 +1,284 @@ +--- +title: Trabalhando com texto — strings em JavaScript +slug: Learn/JavaScript/First_steps/Strings +translation_of: Learn/JavaScript/First_steps/Strings +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Agora vamos dar atenção às strings - isto é como é chamado em programação qualquer parte de texto. Neste artigo nós veremos tudo que você realmente deve saber sobre strings quando está aprendendo JavaScript. Como criar, fazer citações e como juntar strings.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Computação básica, um entendimento básico de HTML e CSS, e sobre o que é JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ganhar familiaridade com o básico de strings em JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="O_poder_das_palavras">O poder das palavras</h2> + +<p>Palavras são muito importante para humanos - elas são uma grande parte de como nos comunicamos. Desde que a Web é largamente baseada em texto, projetada para permitir humanos a comunicar e compartilhar infomação, isto é útil para nós termos controle sobre como apresentar isso. {{glossary("HTML")}} fornece estrutura e significado para nosso texto, {{glossary("CSS")}} nos permite estilizar precisamente ele, e JavaScript contem um número de funcionalidades para manipular strings, criar mensagens de boas-vindas customizadas, mostrando rótulos quando preciso, sorteando termos de acordo como desejado e muito mais.</p> + +<p>Muitos dos programas que temos visto até agora no curso está envolvido em alguma parte com manipulação de string.</p> + +<h2 id="Strings_—_O_básico">Strings — O básico</h2> + +<p>Em um primeiro relance, strings são tratadas de forma parecida como números, mas quando vamos mais a fundo, você começa a ver algumas diferenças importantes. Vamos começar a entrar em linhas básicas no console para nos familiarizar. Nós vamos fornecer abaixo (você pode também <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">abrir isto no console</a> em uma guia ou janela separada, ou usar o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console do navegador</a> se você preferir).</p> + +<div class="hidden"> +<h6 id="Código_oculto">Código oculto</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class','input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + + if(document.querySelectorAll('div').length > 1) { + inputForm.focus(); + } + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Criando_uma_string">Criando uma string</h3> + +<ol> + <li>Para começar, digite as linhas seguintes: + <pre class="brush: js">var string = 'The revolution will not be televised.'; +string;</pre> + Como fizemos com números, nós declaramos uma variável, inicializando-a com um valor string, e então retornamos o valor. A única diferença aqui é que quando escrevemos uma string, você precisa colocá-la entre aspas.</li> + <li>Se você não fez isso, ou esqueceu uma das aspas, você recebeu um erro. Experimente digitar as linhas seguintes: + <pre class="brush: js example-bad">var badString = This is a test; +var badString = 'This is a test; +var badString = This is a test';</pre> + Estas linhas não funcionam porque todo texto sem aspas são interpretados como um nome de variável, propriedade do nome, palavra reservada ou algo assim. Se o navegador não puder encontrar, então um é erro é apresentado (ex.: "faltando; declaração anterior"). Se o navegador puder ver onde a string começa, mas não conseguir encontrar o fim, como indicado com as segundas aspas, é retornado um erro (com "string não terminada"). Se seu programa retorna tais erros, então volte e verifique todas suas strings para ter certeza que não faltam aspas.</li> + <li>O seguinte funcionará se você definiu previamente a variável <code>string</code> - tente isto agora: + <pre class="brush: js">var badString = string; +badString;</pre> + <code>badString</code> é agora definido para ter o mesmo valor de <code>string</code>.</li> +</ol> + +<h3 id="Aspas_simples_x_aspas_duplas">Aspas simples x aspas duplas</h3> + +<ol> + <li>Em JavaScript, você pode escolher aspas simples ou duplas para envolver suas strings. Ambas linhas abaixo funcionará bem: + <pre class="brush: js">var sgl = 'Single quotes.'; +var dbl = "Double quotes"; +sgl; +dbl;</pre> + </li> + <li>Há poucas diferenças entre as duas, e qual você usar é de preferência pessoal. Você deve escolher uma e permanecer nela, entretanto; diferentes aspas no código pode ser confuso, especialmente se você usa diferentes aspas na mesma string! O seguinte retornará erro: + <pre class="brush: js example-bad">var badQuotes = 'What on earth?";</pre> + </li> + <li>O navegador interpretará como a string não tivesse fechada, porque o outro tipo de aspas pode aparecer dentro da sua string. Por exemplo, ambos exemplos abaixo são okay: + <pre class="brush: js">var sglDbl = 'Would you eat a "fish supper"?'; +var dblSgl = "I'm feeling blue."; +sglDbl; +dblSgl;</pre> + </li> + <li>Entretanto, você não pode incluir o mesmo tipo de aspas dentro da sua string, se você usa para conter seu texto. O seguinte será um erro, como é confuso para o navegador onde a string termina: + <pre class="brush: js example-bad">var bigmouth = 'I've got no right to take my place...';</pre> + Isto nos leva muito bem ao nosso próximo assunto.</li> +</ol> + +<h3 id="Caracteres_de_escape_na_string">Caracteres de escape na string</h3> + +<p>Para corrigir o problema anterior, nós precisamos escapar o problema da aspa. Caracteres de escape significa que nós fazemos algo para ter certeza que eles são reconhecidos como texto, não parte do código. Em JavaScript, nós fazemos isso colocando uma barra invertida logo antes do caracter.Tente isso:</p> + +<pre class="brush: js">var bigmouth = 'I\'ve got no right to take my place...'; +bigmouth;</pre> + +<p>Isto funciona bem. Você pode escapar outros caracteres do mesmo jeito, ex.: <code>\"</code>, e há alguns códigos especiais também. Veja <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Escape_notation">Notação de escape</a> para mais detalhes.</p> + +<h2 id="Concatenando_strings">Concatenando strings</h2> + +<ol> + <li>Concatenar é uma palavra chique da programação que significa "colocar junto". Para colocar strings juntas em JavaScript, usamos o operador (+), o mesmo usamos para adicionar números, mas neste contexto é algo diferente. Vamos tentar este exemplo no console. + <pre class="brush: js">var one = 'Hello, '; +var two = 'how are you?'; +var joined = one + two; +joined;</pre> + O resultado disso é uma variável chamada <code>joined</code>, que contém o valor "Hello, how are you?".</li> + <li>No último exemplo, nós somente juntamos duas strings, mas você pode fazer quantas quiser, contanto que inclua um <code>+</code> entre cada uma.Experimente isso: + <pre class="brush: js">var multiple = one + one + one + one + two; +multiple;</pre> + </li> + <li>Você pore usar um mix de variáveis e strings reais. Tente isso: + <pre class="brush: js">var response = one + 'I am fine — ' + two; +response;</pre> + </li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Quando você coloca uma string atual no seu código dentro de aspas simples ou duplas, é chamada uma <strong>string literal</strong>.</p> +</div> + +<h3 id="Concatenação_em_contexto">Concatenação em contexto</h3> + +<p>Vamos dar uma olhada na concatenação em ação — aqui está um exemplo do curso anterior:</p> + +<pre class="brush: html"><button>Pressione-me</button></pre> + +<pre class="brush: js">var button = document.querySelector('button'); + +button.onclick = function() { + var nome = prompt('Qual é o seu nome?'); + alert('Olá ' + nome + ', prazer em conhecê-lo!'); +}</pre> + +<p>{{ EmbedLiveSample('Concatenation_in_context', '100%', 50, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Aqui estamos usando uma função {{domxref("Window.prompt()", "Window.prompt()")}} na linha 4, a qual pergunta ao usuário para responder uma questão via uma caixa de diálogo, então armazena o texto em uma variável — neste caso <code>nome</code>. Nós então usamos uma função {{domxref("Window.alert()", "Window.alert()")}} na linha 5 para mostrar outra caixa de diálogo contendo nossa string montada de duas strings literais e a variável <code>name</code>,via concatenação.</p> + +<h3 id="Números_x_strings">Números x strings</h3> + +<ol> + <li>Então o que acontece quando tentamos adicionar (ou concatenar) uma string e um número? Vamos tentar isso no console: + <pre class="brush: js">'Front ' + 242; +</pre> + Você pode esperar um erro disto, mas funciona correto. Tentando representar uma string como um número, realmente não faz sentido. Mas representando um número como string, faz. Então o navegador espertamente converte o número em string e concatena as duas.</li> + <li>Você pode fazer isto até com dois números — você pode forçar um número a ser string colocando ele entre aspas. Experimente o seguinte (nós estamos usando o operador <code>typeof</code> para checar o que a variável é, se um número ou string): + <pre class="brush: js">var myDate = '19' + '67'; +typeof myDate;</pre> + </li> + <li>Se você tem uma variável numérica que precisa converter em string, mas não mudar completamente, ou uma string e quer converter em número, você pode usar a construção seguinte: + <ul> + <li>O objeto {{jsxref("Number")}} converterá qualquer coisa passada em um número, se for possível. Tente o seguinte: + <pre class="brush: js">var myString = '123'; +var myNum = Number(myString); +typeof myNum;</pre> + </li> + <li>Por outro lado, todo número tem um método chamado <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString">toString()</a></code> que converterá para a string equivalente. Tente isto: + <pre class="brush: js">var myNum = 123; +var myString = myNum.toString(); +typeof myString;</pre> + </li> + </ul> + Estas construções podem ser bem úteis em algumas situações. Por exemplo, se o usuário colocar um número em um campo de texto, isso será uma string. Entretanto, se você quiser adicionar este número a algo, você precisa que seja um número, então você pode passar isto através do <code>Number()</code> para poder manipular.Nós fizemos exatamente isto no nosso <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game.html#L61">Number Guessing Game, in line 61</a>.</li> +</ol> + +<h2 id="Conclusão">Conclusão</h2> + +<p>Então isto é o basico sobre strings em JavaScript. No próximo artigo nós iremos continuar daqui, vendo alguns métodos de construção de strings disponíveis em JavaScript e como nós podemos usá-los para manipular nossa string da forma como quisermos.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}</p> + + + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">O que é JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Solução de erros em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables">Armazenando a informação que você precisa — Variáveis</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Matemática básica em JavaScript — números e operadores</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">Manipulando texto — strings em JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis de strings</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Silly_story_generator">Avaliação: gerador de história boba</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/teste_suas_habilidades_colon__variaveis/index.html b/files/pt-br/learn/javascript/first_steps/teste_suas_habilidades_colon__variaveis/index.html new file mode 100644 index 0000000000..1a14c86630 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/teste_suas_habilidades_colon__variaveis/index.html @@ -0,0 +1,85 @@ +--- +title: 'Teste suas habilidades: variáveis' +slug: 'Learn/JavaScript/First_steps/Teste_suas_habilidades:_variaveis' +tags: + - Aprender + - Habilidades + - Iniciante + - JavaScript + - Teste suas habilidades + - Variáveis +translation_of: 'Learn/JavaScript/First_steps/Test_your_skills:_variables' +--- +<div>{{learnsidebar}}</div> + +<p>O objetivo deste teste de habilidade é avaliar se você entendeu nosso artigo <a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Vari%C3%A1veis">Armazenando as informações que você precisa — Variáveis</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Você pode experimentar soluções nos editores interativos abaixo. No entanto, pode ser útil fazer o download do código e usar uma ferramenta on-line como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, ou <a href="https://glitch.com/">Glitch</a> para realizar as tarefas.<br> + <br> + Se você travar, peça ajuda — veja a seção {{anch("Assessment or further help")}} na parte inferior desta página.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Nos exemplos abaixo, se houver um erro no seu código, ele será exibido no painel de resultados da página, para ajudá-lo a tentar descobrir a resposta (ou no console JavaScript do navegador, no caso da versão para download).</p> +</div> + +<h2 id="Variáveis_1">Variáveis 1</h2> + +<p>Nesta tarefa, queremos que você:</p> + +<ul> + <li>Declare uma variável chamada <code>meuNome</code>.</li> + <li>Inicialize <code>meuNome</code> com um valor adequado, em uma linha separada (você pode usar seu nome real ou qualquer outra coisa).</li> + <li>Declare uma variável chamada <code>minhaIdade</code> e inicialize-a com um valor, na mesma linha.</li> +</ul> + +<p>Tente atualizar o código ativo abaixo para recriar o exemplo final:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/variables/variables1.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables1-download.html">Faça o download do ponto de partida</a> para esta tarefa funcionar em seu próprio editor ou em um editor online.</p> +</div> + +<h2 id="Variáveis_2">Variáveis 2</h2> + +<p>Nesta tarefa, você precisa adicionar uma nova linha para corrigir o valor armazenado na variável <code>meuNome</code> existente para seu próprio nome.</p> + +<p>Tente atualizar o código ativo abaixo para recriar o exemplo final:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/variables/variables2.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables2-download.html">Faça o download do ponto de partida</a> para esta tarefa funcionar em seu próprio editor ou em um editor online.</p> +</div> + +<h2 id="Variáveis_3">Variáveis 3</h2> + +<p>A tarefa final por enquanto — neste caso, você recebe um código existente, que possui dois erros. O painel de resultados deve exibir o nome <code>Chris</code>, e uma declaração sobre quantos anos Chris terá daqui a 20 anos. Como você pode corrigir o problema e corrigir a saída?</p> + +<p>Tente atualizar o código ativo abaixo para recriar o exemplo final:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/variables/variables3.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables3-download.html">Faça o download do ponto de partida</a> para esta tarefa funcionar em seu próprio editor ou em um editor online.</p> +</div> + +<h2 id="Avaliação_ou_ajuda_adicional">Avaliação ou ajuda adicional</h2> + +<p>Você pode praticar esses exemplos nos editores interativos acima.</p> + +<p>Se você gostaria que seu trabalho fosse avaliado, ou está travado e quer pedir ajuda:</p> + +<ol> + <li>Coloque seu trabalho em um editor compartilhável on-line, como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, ou <a href="https://glitch.com/">Glitch</a>. Você pode escrever o código você mesmo ou usar os arquivos de ponto de partida vinculados nas seções acima.</li> + <li>Escreva um post pedindo avaliação e/ou ajuda na categoria <a href="https://discourse.mozilla.org/c/mdn/learn">MDN Discourse forum Learning</a>. Seu post deve incluir: + <ul> + <li>Um título descritivo como "Avaliação desejada para o teste de habilidade Variáveis 1".</li> + <li>Detalhes do que você já tentou e o que gostaria que fizéssemos. Por exemplo, se você está travado e precisa de ajuda ou deseja uma avaliação.</li> + <li>Um link para o exemplo que você deseja que seja avaliado ou precisa de ajuda, em um editor compartilhável online (conforme mencionado na etapa 1 acima). Esta é uma boa prática para entrar - é muito difícil ajudar alguém com um problema de codificação se você não conseguir ver o código.</li> + <li>Um link para a página real de tarefas ou avaliações, para que possamos encontrar a pergunta com a qual você deseja ajuda.</li> + </ul> + </li> +</ol> diff --git a/files/pt-br/learn/javascript/first_steps/useful_string_methods/index.html b/files/pt-br/learn/javascript/first_steps/useful_string_methods/index.html new file mode 100644 index 0000000000..3304dd800e --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/useful_string_methods/index.html @@ -0,0 +1,484 @@ +--- +title: Métodos úteis de string +slug: Learn/JavaScript/First_steps/Useful_string_methods +translation_of: Learn/JavaScript/First_steps/Useful_string_methods +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Agora que nós vimos o básico de strings, vamos engatar a próxima marcha e começar a pensar sobre as operações úteis que podemos fazer em strings com métodos embutidos, como encontrar o comprimento de um string, unir e dividir sequências de caracteres, substituindo um caracter em uma string por outro, e muito mais.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico de computador, uma compreensão básica de HTML e CSS, uma compreensão do que é o JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Entender que strings são objetos e aprender a usar alguns do métodos básicos disponíveis nesses objetos para manipular strings.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Strings_como_objetos">Strings como objetos</h2> + +<p>Como dissemos antes e diremos novamente — <em>tudo</em> é um objeto em JavaScript. Quando você cria um string, usando por exemplo</p> + +<pre class="brush: js">var string = 'This is my string';</pre> + +<p>sua variável torna-se uma instância do objeto string e, como resultado, tem um grande número de propriedades e métodos diponíveis para ela. Você pode ver isso se você for na página do objeto {{jsxref("String")}} e olhar para baixo na lista do lado da página!</p> + +<p><strong>Agora, antes de seu cérebro começar a derreter, não se preocupe!</strong> Você não precisa saber sobre a maioria deles no início da sua jornada de aprendizado. Mas há alguns que você potencialmente usará com bastante frequência que veremos aqui.</p> + +<p>Vamos digitar alguns exemplos em um console novo. Nós fornecemos um abaixo (você também pode abrir este console em uma guia ou janela separada, ou usar o console do desenvolvedor do navegador, se preferir).</p> + +<p>Nós fornecemos um abaixo (você também pode <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">abrir esse console</a> em uma aba ou janela separada, ou usar o <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console do navegador do desenvolvedor</a> se você preferir).</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class', 'input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300) }}</p> + +<h3 id="Descobrindo_o_comprimento_de_uma_string">Descobrindo o comprimento de uma string</h3> + +<p>Essa é fácil — você simplesmente usa a propriedade {{jsxref("String.prototype.length", "length")}}. Tente digitar as linhas a seguir:</p> + +<pre class="brush: js">var browserType = 'mozilla'; +browserType.length;</pre> + +<p>Isso deve retornar o número 7, porque "mozilla" tem 7 caracteres. Isso é útil por vários motivos; por exemplo, você pode querer encontrar os comprimentos de uma série de nomes para que você possa exibi-los em ordem de comprimento, ou deixar um usuário saber que um nome de usuário que ele informou em um campo de formulário é muito longo se este for maior do que um certo comprimento.</p> + +<h3 id="Recuperando_um_caractere_de_string_específico">Recuperando um caractere de string específico</h3> + +<p>Nota complementar: você pode retornar qualquer caractere dentro de uma string usando a<strong> notação colchete</strong> - isso significa que você inclui colchetes (<code>[]</code>) no final do nome da variável. Dentro dos colchetes, você inclui o número do caractere que deseja retornar, por exemplo, para recuperar a primeira letra, faça o seguinte:</p> + +<pre class="brush: js">browserType[0];</pre> + +<p>Computadores contam a partir de 0, não 1! Para recuperar o último caractere de <em>qualquer</em> string, nós podemos usar a linha a seguir, combinando essa técnica com a propriedade <code>length</code> que vimos anteriormente:</p> + +<pre class="brush: js">browserType[browserType.length-1];</pre> + +<p>O comprimento de "mozilla" é 7, mas porque a contagem começa de 0, a posição do caractere é 6, daí precisamos usar <code>length-1</code>. Você pode usar isso para, por exemplo, encontrar a primeira letra de uma série de strings e ordená-los alfabeticamente.</p> + +<h3 id="Encontrando_uma_substring_dentro_de_uma_string_e_extraindo-a">Encontrando uma substring dentro de uma string e extraindo-a</h3> + +<ol> + <li>Às vezes você quer sabe se uma string menor está presente dentro de uma maior (geralmente dizemos <em>se uma substring está presente dentro de uma string</em>). Isso pode ser feito usando o método {{jsxref ("String.prototype.indexOf ()", "indexOf ()")}}, que leva um único {{glossary ("parameter")}} - a substring que deseja procurar. Experimente isso: + + <pre class="brush: js">browserType.indexOf('zilla');</pre> + Isso nos dá o resultado 2, porque a substring "zilla" se inicia na posição 2 (0, 1, 2 — então, 3 caraceteres) dentro de "mozilla". Esse código poderia ser usado para filtrar cadeias de caracteres. Por exemplo, podemos ter uma lista de endereços da web e apenas queremos imprimir aqueles que contenham "mozilla".</li> + <li>Isso pode ser feito de outro jeito, que é possivelmente mais eficaz. Experimente isso: + <pre class="brush: js">browserType.indexOf('vanilla');</pre> + Isso deve lhe dar um resultado <code>-1</code> — isso é retornado quando a substring, neste caso 'vanilla', não é encontrada na string principal.<br> + <br> + Você pode usar isso para encontrar todas as instâncias de strings que <strong>não contém</strong> a substring 'mozilla', ou <strong>contém</strong>, se você usar o operador de negação, conforme mostrado abaixo. Você poderia fazer algo assim: + + <pre class="brush: js">if(browserType.indexOf('mozilla') !== -1) { + // faz coisas com a string +}</pre> + </li> + <li>Quando você sabe onde uma substring começa dentro de uma string e você sabe em qual caractere você deseja que ela termine, {{jsxref ("String.prototype.slice ()", "slice ()")}} pode ser usado para extrair isto. Tente o seguinte: + <pre class="brush: js">browserType.slice(0,3);</pre> + Isso retorna "moz" — o primeiro parâmetro é a posição do caractere a partir da qual será iniciada a extração, e o segundo parâmetro é a posição seguinte do último caractere a ser extraído. Então, a fatia ocorre da primeira posição, até a última posição, mas não incluindo. Você também pode dizer que o segundo parâmetro é igual ao comprimento da string que está sendo retornada.</li> +</ol> + +<p>Também, se você sabe que você deseja extrair todos os caracteres restantes em uma string após um certo caracter, você não tem que incluir o segundo parametro! Você apenas precisa incluir a posição do caracter a partir de onde você deseja extrar os caracteres restantes em uma string. Tente o seguinte: </p> + +<pre class="brush: js">browserType.slice(2);</pre> + +<p>Isso retornará "zilla" — isso é porque a posição de caracter 2 é a letra z, e porque você não incluiu o segundo parametro, a substring retornou todos os caracteres restantes na string. </p> + +<div class="note"> +<p><strong>Note</strong>: O segundo parametro do <code>slice()</code> é opcional: Se você não incluir ele, o slice finaliza no fim da string original. Existem outras opções também; estude a {{jsxref("String.prototype.slice()", "slice()")}} pagina para ver o que mais você pode descobrir.</p> +</div> + +<h3 id="Mudando_entre_maiúsculas_e_minúsculas">Mudando entre maiúsculas e minúsculas</h3> + +<p>O método string {{jsxref("String.prototype.toLowerCase()", "toLowerCase()")}} e {{jsxref("String.prototype.toUpperCase()", "toUpperCase()")}} toma a string e converte todos os caracteres para minusculo - ou maiusculo, respectivamente. Este pode ser util, por exemplo, se você quer normalizar todas as entradas de dados do usuário antes de armazenar em um banco de dados.</p> + +<p>Vamos testar inserindo as seguintes linhas para ver o que acontece:</p> + +<pre class="brush: js">var radData = 'My NaMe Is MuD'; +radData.toLowerCase(); +radData.toUpperCase();</pre> + +<h3 id="Atualizando_partes_de_uma_string">Atualizando partes de uma string</h3> + +<p>Você pode substituir uma substring dentro de uma string com uma outra substring usando o método {{jsxref("String.prototype.replace()", "replace()")}}. Este funciona muito simples em um nível básico, apesar haver algumas coisas avançadas que você pode fazer com ele, nós não iremos tão longe ainda.</p> + +<p>Ele toma dois parametros — A string que você quer substituir e a string que você quer que substitua o primeiro parametro. Tente este exemplo:</p> + +<pre class="brush: js">browserType.replace('moz','van');</pre> + +<p>Observe que para realmente obter o valor atualizado refletido na variavel <code>browserType</code> em um programa real, você teria que setar o valor da variavel para ser o resultado da operação; não apenas atualizar o valor da substring automaticamente. Assim você teria que realmente escrever isso: <code>browserType = browserType.replace('moz','van');</code></p> + +<h2 id="Exemplos_para_aprendizado_ativo">Exemplos para aprendizado ativo</h2> + +<p>Nesta seção, tentaremos escrever um código de manipulação de string. Em cada exercício abaixo, temos uma matriz de strings e um loop que processa cada valor na matriz e o exibe em uma lista com marcadores. Você não precisa entender matrizes ou loops agora - isso será explicado em artigos futuros. Tudo o que você precisa fazer em cada caso é escrever o código que produzirá as strings no formato em que as queremos.</p> + +<p>Cada exemplo vem com um botão "Reset", que você pode usar para redefinir o código original, isso se cometer um erro e não conseguir faze-lo funcionar novamente, e um botão "Show Solution" que você pode pressionar para ver aresposta em potencial se realmente estiver travado.</p> + +<h3 id="Filtrando_mensagens_de_saudação">Filtrando mensagens de saudação</h3> + +<p>No primeiro exercício, começaremos com simplicidade - temos várias mensagens de cartão, mas queremos classificá-las para listar apenas as mensagens de Natal. Queremos que você preencha um teste condicional dentro da estrutura if (...), para testar cada string e apenas imprimi-la na lista se for uma mensagem de Natal.</p> + +<ol> + <li>Primeiro pense em como você poderia testar se a mensagem em cada caso é uma mensagem de Natal. Qual string está presente em todas essas mensagens e que método você poderia usar para testar se ela está presente?</li> + <li>Em seguida, você precisará escrever um teste condicional do formulario operando2 operador operando1. A coisa à esquerda é igual à coisa à direita? Ou neste caso, o método chama à esquerda retorna o resultado à direita?</li> + <li>Dica: Nesse caso, é provavelmente mais útil testar se a chamada do método não é igual a um determinado resultado.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html"><div class="output" style="min-height: 125px;"> + +<ul> + +</ul> + +</div> + +<textarea id="code" class="playable-code" style="height: 290px;"> +var list = document.querySelector('.output ul'); +list.innerHTML = ''; +var greetings = ['Happy Birthday!', + 'Merry Christmas my love', + 'A happy Christmas to all the family', + 'You\'re all I want for Christmas', + 'Get well soon']; + +for (var i = 0; i < greetings.length; i++) { + var input = greetings[i]; + // Seu teste condicional precisa ir dentro dos parênteses + // na linha abaixo, substituindo o que está lá + if (greetings[i]) { + var result = input; + var listItem = document.createElement('li'); + listItem.textContent = result; + list.appendChild(listItem); + } +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + updateCode(); +}); + +solution.addEventListener('click', function() { + textarea.value = jsSolution; + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar greetings = [\'Happy Birthday!\',\n \'Merry Christmas my love\',\n \'A happy Christmas to all the family\',\n \'You\\\'re all I want for Christmas\',\n \'Get well soon\'];\n\nfor(var i = 0; i < greetings.length; i++) {\n var input = greetings[i];\n if(greetings[i].indexOf(\'Christmas\') !== -1) {\n var result = input;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n }\n}'; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', '100%', 490) }}</p> + +<h3 id="Corrigindo_a_capitalização">Corrigindo a capitalização</h3> + +<p>Neste exercício, temos os nomes das cidades no Reino Unido, mas a capitalização está toda desarrumada. Nós queremos que você as altere para que elas sejam todas minúsculas, exceto pela primeira letra maiúscula. Uma boa maneira de fazer isso é:</p> + +<ol> + <li>Converta toda a cadeia contida na variável de entrada para minúscula e armazene-a em uma nova variável.</li> + <li>Pegue a primeira letra da string nesta nova variável e armazene-a em outra variável.</li> + <li>Usando esta última variável como substring, substitua a primeira letra da string em minúsculas pela primeira letra da string em minúsculas alterada para maiúscula. Armazene o resultado desse procedimento de substituição em outra nova variável.</li> + <li>Altere o valor da variável <code>result</code> para igual ao resultado final, não a <code>input</code>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Uma dica — os parâmetros dos métodos de string não precisam ser literais de string; eles também podem ser variáveis, ou mesmo variáveis com um método sendo invocado nelas.</p> +</div> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html"><div class="output" style="min-height: 125px;"> + +<ul> + +</ul> + +</div> + +<textarea id="code" class="playable-code" style="height: 250px;"> +var list = document.querySelector('.output ul'); +list.innerHTML = ''; +var cities = ['lonDon', 'ManCHESTer', 'BiRmiNGHAM', 'liVERpoOL']; +for(var i = 0; i < cities.length; i++) { + var input = cities[i]; + // write your code just below here + + var result = input; + var listItem = document.createElement('li'); + listItem.textContent = result; + list.appendChild(listItem); +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + updateCode(); +}); + +solution.addEventListener('click', function() { + textarea.value = jsSolution; + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar cities = [\'lonDon\', \'ManCHESTer\', \'BiRmiNGHAM\', \'liVERpoOL\'];\n\nfor(var i = 0; i < cities.length; i++) {\n var input = cities[i];\n var lower = input.toLowerCase();\n var firstLetter = lower.slice(0,1);\n var capitalized = lower.replace(firstLetter,firstLetter.toUpperCase());\n var result = capitalized;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n\n}'; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', '100%', 450) }}</p> + +<h3 id="Fazendo_novas_strings_a_partir_de_partes_antigas">Fazendo novas strings a partir de partes antigas</h3> + +<p>Neste último exercício, o array contém um monte de strings contendo informações sobre estações de trem no norte da Inglaterra. As strings são itens de dados que contêm o código da estação de três letras, seguido por alguns dados legíveis por máquina, seguidos por um ponto-e-vírgula, seguido pelo nome da estação legível por humanos. Por exemplo:</p> + +<pre>MAN675847583748sjt567654;Manchester Piccadilly</pre> + +<p>Queremos extrair o código e o nome da estação e juntá-los em uma string com a seguinte estrutura:</p> + +<pre>MAN: Manchester Piccadilly</pre> + +<p>Nós recomendamos que faça assim:</p> + +<ol> + <li>Extraia o código da estação de três letras e armazene-o em uma nova variável.</li> + <li>Encontre o número de índice do caractere do ponto e vírgula.</li> + <li>Extraia o nome da estação legível usando o número do índice de caracteres de ponto-e-vírgula como ponto de referência e armazene-o em uma nova variável.</li> + <li>Concatene as duas novas variáveis e uma string literal para fazer a string final.</li> + <li>Altere o valor da variável <code>result</code> para igual à string final, não a <code>input</code>.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code_3">Playable code 3</h6> + +<pre class="brush: html"><div class="output" style="min-height: 125px;"> + +<ul> + +</ul> + +</div> + +<textarea id="code" class="playable-code" style="height: 285px;"> +var list = document.querySelector('.output ul'); +list.innerHTML = ''; +var stations = ['MAN675847583748sjt567654;Manchester Piccadilly', + 'GNF576746573fhdg4737dh4;Greenfield', + 'LIV5hg65hd737456236dch46dg4;Liverpool Lime Street', + 'SYB4f65hf75f736463;Stalybridge', + 'HUD5767ghtyfyr4536dh45dg45dg3;Huddersfield']; + +for (var i = 0; i < stations.length; i++) { + var input = stations[i]; + // write your code just below here + + var result = input; + var listItem = document.createElement('li'); + listItem.textContent = result; + list.appendChild(listItem); +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + updateCode(); +}); + +solution.addEventListener('click', function() { + textarea.value = jsSolution; + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar stations = [\'MAN675847583748sjt567654;Manchester Piccadilly\',\n \'GNF576746573fhdg4737dh4;Greenfield\',\n \'LIV5hg65hd737456236dch46dg4;Liverpool Lime Street\',\n \'SYB4f65hf75f736463;Stalybridge\',\n \'HUD5767ghtyfyr4536dh45dg45dg3;Huddersfield\'];\n\nfor(var i = 0; i < stations.length; i++) {\n var input = stations[i];\n var code = input.slice(0,3);\n var semiC = input.indexOf(\';\');\n var name = input.slice(semiC + 1);\n var result = code + \': \' + name;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n}'; + + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_3', '100%', 485) }}</p> + +<h2 id="Conclusão">Conclusão</h2> + +<p>Você não pode escapar do fato de que ser capaz de lidar com palavras e frases em programação é muito importante — particularmente em JavaScript, pois os sites são todos sobre comunicação com pessoas. Este artigo forneceu os fundamentos que você precisa saber sobre a manipulação de strings por enquanto. Isso deve atendê-lo bem ao abordar tópicos mais complexos no futuro. Em seguida, vamos ver o último tipo de dados importante que precisamos focar no curto prazo — arrays.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript">What is JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/A_first_splash">A first splash into JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong">What went wrong? Troubleshooting JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables">Storing the information you need — Variables</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Basic math in JavaScript — numbers and operators</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">Handling text — strings in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Useful string methods</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Silly_story_generator">Assessment: Silly story generator</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/variáveis/index.html b/files/pt-br/learn/javascript/first_steps/variáveis/index.html new file mode 100644 index 0000000000..1afd436622 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/variáveis/index.html @@ -0,0 +1,332 @@ +--- +title: Armazenando as informações que você precisa — Variáveis +slug: Learn/JavaScript/First_steps/Variáveis +translation_of: Learn/JavaScript/First_steps/Variables +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Depois de ler os últimos artigos, você deve saber agora o que é o JavaScript, o que ele pode fazer para você, como você usa isso junto com outras tecnologias da web e as características principais de alto nível. Neste artigo, iremos ao básico, vendo como trabalhar com a maioria dos blocos de construção básicos de JavaScript - Variáveis.</p> + +<table class="learn-box"> + <tbody> + <tr> + <th scope="row">Pré-requisitos:</th> + <td>Conhecimento básico em informática, uma compreensão básica de HTML e CSS, uma compreensão do que é o JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizar-se com o básico de variáveis em JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Ferramentas_que_você_precisa">Ferramentas que você precisa</h2> + +<p>Ao longo deste artigo, pediremos que você digite linhas de código para testar seu entendimento do conteúdo. Se você estiver utilizando um navegador em um computador, o melhor lugar para digitar seus código de exemplos é o console JavaScript do seu navegador (veja o artigo <a href="/pt-BR/docs/Learn/Common_questions/ferramentas_de_desenvolvimento_do_navegador">O que são as ferramentas de desenvolvimento do navegador</a> para mais informações sobre como acessar essa ferramenta).</p> + +<p>No entanto, nós também providenciamos um simples console JavaScript incorporado à página logo abaixo para que você inserir o código, caso não esteja usando um navegador com um console JavaScript facilmente disponível, ou se achar o console incorporado mais confortável.</p> + +<h2 id="O_que_é_uma_variável">O que é uma variável?</h2> + +<p>Uma variável é um container para um valor, como um número que podemos usar em uma operação de adição, ou uma sequência de texto que possamos usar como parte de uma oração. Mas uma coisa especial a respeito das variáveis é que seu conteúdo pode mudar. Vamos ver um exemplo simples:</p> + +<pre class="brush: html notranslate"><button>Aperte-me</button></pre> + +<pre class="brush: js notranslate">var button = document.querySelector('button'); + +button.onclick = function() { + var nome = prompt('Qual é o seu nome?'); + alert('Olá ' + nome + ', é um prazer te ver!'); +}</pre> + +<p>{{ EmbedLiveSample('O_que_é_uma_variável', '100%', 50, "", "", "hide-codepen-jsfiddle" ) }}</p> + +<p>Nesse exemplo, apertar o botão executa algumas linhas de código. A primeira linha exibe uma caixa pop-up na tela que pede ao leitor para inserir o seu nome, e então armazena o valor na variável. A segunda linha exibe uma mensagem de boas vindas que inclui seu nome, obtido do valor da variável.</p> + +<p>Para entender porque isso é útil, vamos pensar sobre como nós escreveríamos esse exemplo sem usar uma variável. Iria acabar se parecendo com algo do tipo:</p> + +<pre class="example-bad notranslate">var nome = prompt('Qual é o seu nome?'); + +if (nome === 'Adão') { + alert('Olá Adão, é um prazer te ver!'); +} else if (nome === 'Alan') { + alert('Olá Alan, é um prazer te ver!'); +} else if (nome === 'Bella') { + alert('Olá Bella, é um prazer te ver!'); +} else if (nome === 'Bianca') { + alert('Olá Bianca, é um prazer te ver!'); +} else if (nome === 'Chris') { + alert('Olá Chris, é um prazer te ver !'); +} + +// ... e assim por diante ...</pre> + +<p>Você talvez não entenda totalmente a sintaxe que estamos usando (ainda!), mas deve ter pegado a ideia — se nós não tivermos variáveis disponíveis teríamos que implementar um bloco de código gigantesco para conferir qual era o nome inserido, e então exibir a mensagem apropriada para aquele nome. Isso é obviamente muito ineficiente (o código é muito maior, mesmo para apenas quatro opções de nome), e simplesmente não funcionaria — você não poderia armazenar todas as possíveis opções de nome.</p> + +<p>Variáveis simplesmente fazem sentido, e a medida que você for aprendendo mais sobre JavaScript elas começarão a se tornar uma coisa natural.</p> + +<p>Outra coisa especial sobra as variáveis é que elas podem conter praticamente qualquer coisa — não apenas cadeias de texto e números. Variáveis também podem conter dados complexos e até mesmo funções completas para fazer coisas incríveis. Você irá aprender mais sobre isso a medida que continuarmos.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Perceba que dissemos que as variáveis contém valores. Essa é uma distinção importante a se fazer. Elas não são os valores; e sim os containers para eles. Você pode pensar nelas sendo pequenas caixas de papelão nas quais você pode guardar coisas..</p> +</div> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13506/boxes.png" style="display: block; height: 436px; margin: 0px auto; width: 1052px;"></p> + +<h2 id="Declarando_uma_variável">Declarando uma variável</h2> + +<p>Para usar uma variável primeiro tem que criá-la — mais precisamente, chamamos isso de declarar a variável. Para fazê-lo digitamos a palavra chave <code>var</code> seguido do nome que desejamos dar à variável:</p> + +<pre class="brush: js notranslate">var meuNome; +var minhaIdade;</pre> + +<p>Aqui, estamos criando duas variáveis chamadas <code>meuNome</code> e <code>minhaIdade</code>. Tente agora digitar essas linhas no console do seu navegador. Depois disso, tente criar uma variável (ou duas) com suas próprias escolhas de nomes.</p> + +<div class="note"> +<p><strong>Nota</strong>: No JavaScript, todas as intruções em código deve terminar com um ponto e vírgula (<code>;</code>) — seu código pode até funcionar sem o ponto e vírgula em linhas únicas, mas provavelmente não irá funcionar quando estiver escrevendo várias linhas de código juntas. Tente pegar o hábito de sempre incluir o ponto e vírgula.</p> +</div> + +<p>Você pode testar se os valores agora existem no ambiente de execução digitando apenas os nomes das variáveis, ex.:</p> + +<pre class="brush: js notranslate">meuNome; +minhaidade;</pre> + +<p>Elas atualmente não possuem valor; são containers vazios. Quando você insere o nome de uma variável, você deve obter em retorno ou um valor <code>undefined</code> (indefinido), ou se a variável não existir, você recebe uma mensagem de erro — tente digitar:</p> + +<pre class="brush: js notranslate">scoobyDoo;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Não confunda uma variável que existe mas não tenho valor definido com uma variável que não existe — são coisas bem diferentes.</p> +</div> + +<h2 id="Inicializando_uma_variável">Inicializando uma variável</h2> + +<p>Uma vez que você declarou uma variável, você pode inicializá-la com um valor. Você faz isso digitando o nome da variável, seguido do sinal de igual (<code>=</code>) e o valor que deseja atribuir a ela. Por exemplo:</p> + +<pre class="brush: js notranslate">meuNome = 'Chris'; +minhaIdade = 37;</pre> + +<p>Tente voltar ao console agora e digitar essas linhas acima. Você deve ver o valor que atribuiu à variável retornado no console confirmando-o, em cada caso. De novo, você pode retornar os valores de suas variáveis simplesmente digitando seus nomes no console — tente isso novamente:</p> + +<pre class="brush: js notranslate">meuNome; +minhaIdade;</pre> + +<p>Você pode declarar e inicializar uma variável ao mesmo tempo, assim:</p> + +<pre class="brush: js notranslate">var meuNome = 'Chris';</pre> + +<p>Isso provavelmente é como irá fazer na maioria das vezes, já que é mais rápido do que fazer as duas ações em duas linhas separadas.</p> + +<h2 id="A_diferença_entre_var_e_let">A diferença entre var e let</h2> + +<p>Agora você pode estar pensando "por que precisamos de duas palavras-chave para definir variáveis? Por que <code>var</code> <em>e</em> <code>let</code>?".</p> + +<p>As razões são um tanto históricas. Quando o JavaScript foi criado, havia apenas <code>var</code>. Isso funciona basicamente bem na maioria dos casos, mas tem alguns problemas na maneira como funciona — seu design pode ser confuso ou totalmente irritante. Portanto, <code>let</code> foi criada nas versões modernas de JavaScript, uma nova palavra-chave para criar variáveis que funcionam de maneira um pouco diferente para <code>var</code>, corrigindo seus problemas no processo.</p> + +<p>Algumas diferenças simples são explicadas abaixo. Não abordaremos todas as diferenças agora, mas você começará a descobri-las à medida que aprender mais sobre JavaScript (se realmente quiser ler sobre elas agora, fique à vontade para conferir nossa <a href="/pt-BR/docs/Web/JavaScript/Reference/Statements/let">página de referência let</a>).</p> + +<p>Para começar, se você escrever um programa JavaScript de várias linhas que declare e inicialize uma variável, poderá realmente declarar uma variável com <code>var</code> depois de inicializá-la e ainda funcionará. Por exemplo:</p> + +<pre class="brush: js notranslate">meuNome = 'Chris'; + +function logNome() { + console.log(meuNome); +} + +logNome(); + +var meuNome;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Isso não funcionará ao digitar linhas individuais em um console JavaScript, apenas ao executar várias linhas de JavaScript em um documento da web.</p> +</div> + +<p>Isso funciona por causa do <strong>hoisting</strong> — leia <a href="/pt-BR/docs/Web/JavaScript/Reference/Statements/var#var_hoisting">var hoisting</a> pra mais detalhes.</p> + +<p>Hoisting não funciona mais com <code>let</code>. Se mudássemos de <code>var</code> para <code>let</code> no exemplo acima, teríamos um erro. Isso é bom — declarar uma variável depois que você a inicializa resulta em código confuso e difícil de entender.</p> + +<p>E depois, ao usar <code>var</code>, você pode declarar a mesma variável quantas vezes quiser, mas com <code>let</code> você não consegue. Isso pode funcionar:</p> + +<pre class="brush: js notranslate">var meuNome = 'Chris'; +var meuNome = 'Bob';</pre> + +<p>Mas isso geraria um erro na segunda linha:</p> + +<pre class="brush: js notranslate">let meuNome = 'Chris'; +let meuNome = 'Bob';</pre> + +<p>Você precisaria fazer assim:</p> + +<pre class="brush: js notranslate">let meuNome = 'Chris'; +meuNome = 'Bob';</pre> + +<p>Novamente, essa é uma decisão sensata da linguagem. Não há razão para redeclarar variáveis — isso apenas torna as coisas mais confusas.</p> + +<p>Por esses motivos e mais, recomendamos que você use <code>let</code> o máximo possível em seu código, em vez de <code>var</code>. Não há motivo para usar <code>var</code>, a menos que você precise oferecer suporte para versões antigas do Internet Explorer com seu código (ele não suporta <code>let</code> até a versão 11; o navegador mais moderno do Windows, o Edge, suporta <code>let</code>).</p> + +<h2 id="Atualizando_uma_variável">Atualizando uma variável</h2> + +<p>Uma vez que uma tenha um valor atribuido, você pode atualizar esse valor simplesmente dando a ela um valor diferente. Tente inserir as seguintes linhas no seu console:</p> + +<pre class="brush: js notranslate">meuNome = 'Bob'; +minhaIdade = 40;</pre> + +<h3 id="Um_adendo_sobre_regras_de_nomeação_de_variáveis">Um adendo sobre regras de nomeação de variáveis</h3> + +<p>Você pode chamar uma variável praticamente qualquer nome que queira, mas há limitações. Geralmente você deve se limitar a utilizar somente caracteres latinos (0-9, a-z, A-Z) e o caractere underline ( _ ).</p> + +<ul> + <li>Você não deve usar outros caracteres porque eles podem causar erros ou ser difíceis de entender por uma audiência internacional.</li> + <li>Não use underline no início do nome de variáveis — isso é utilizado em certos construtores JavaScript para significar coisas específicas, então pode deixar as coisas confusas.</li> + <li>Não use número no início do nome de variáveis. Isso não é permitido e irá causar um erro.</li> + <li>Uma conveção segura e se ater é a chamada <a href="https://pt.wikipedia.org/wiki/CamelCase">"lower camel case"</a>, onde você junta várias palavras, usando minúscula para a primeira palavra inteira e, em seguita, maiusculiza a primeira letra das palavras subsequentes. Temos utilizado esse procedimento para os nomes das nossas variáveis nesse artigo até aqui.</li> + <li>Faça nomes de variáveis intuitivos, para que descrevam o dado que ela contém. Não use letras ou números únicos, ou frases muito longas.</li> + <li>As variáveis diferenciam letras maiúsculas e minúsculas — então <code>minhaidade</code> é uma variável diferente de <code>minhaIdade</code>.</li> + <li>Um último ponto — você também precisa evitar utilizar palavras reservadas pelo JavaScript como nome para suas variáveis — com isso, queremos dizer as palavras que fazem parte da sintaxe do JavaScript! Então você não pode usar palavras como <code>var</code>, <code>function</code>, <code>let</code> e <code>for</code> como nome de variáveis. Os navegadores vão reconhecê-las como itens de código diferentes e, portanto, você terá erros.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Você pode encontrar uma lista bem completa de palavras reservadas para evitar em <a href="/pt-BR/docs/Web/JavaScript/Reference/Lexical_grammar#Palavras-chave">Gramática léxica — Palavras-chave</a>.</p> +</div> + +<p>Exemplos de bons nomes:</p> + +<pre class="example-good notranslate">idade +minhaIdade +inicio +corInicial +valorFinalDeSaida +audio1 +audio2</pre> + +<p>Exemplos ruins de nomes:</p> + +<pre class="example-bad notranslate">1 +a +_12 +minhaidade +MINHAIDADE +var +Document +skjfndskjfnbdskjfb +esseeumnomedevariavelbemlongoeestupido +</pre> + +<p>Tente criar mais algumas variáveis agora, com a orientação acima em mente.</p> + +<h2 id="Tipos_de_variáveis">Tipos de variáveis</h2> + +<p>Existem alguns diferentes tipos de dados que podemos armazenar em variáveis. Nessa seção iremos descrevê-los brevemente, e então em artigos futuros você aprenderá sobre eles em mais detalhes.</p> + +<p>Até agora nós vimos os dois primeiros, mas há outros.</p> + +<h3 id="Números">Números</h3> + +<p>Você pode armazenar números em variáveis, tanto números inteiros, como por exemplo 30 (também chamados de <em>integers</em>) como números decimais, por exemplo 2.456 (também chamados de <em>floats</em> ou <em>floating point numbers</em>). Você não precisa declarar tipos de variáveis no JavaScript, diferentemente de outras linguagens de programação. Quando você atribui a uma variável o valor em número, você não inclui as aspas:</p> + +<pre class="brush: js notranslate">var minhaIdade = 17;</pre> + +<h3 id="Strings_cadeias_de_texto"><em>Strings</em> (cadeias de texto)</h3> + +<p><em>Strings</em> são sequências de texto. Quando você dá a uma variável um valor em texto (<em>string</em>), você precisa envolver o texto em aspas simples ou duplas; caso contrário, o JavaScript vai tentar interpretá-lo como sendo outro nome de variável.</p> + +<pre class="brush: js notranslate">var despedidaGolfinho = 'Até logo e obrigado por todos os peixes!';</pre> + +<h3 id="Booleans_boleanos"><em>Booleans</em> (boleanos)</h3> + +<p><em>Booleans</em> são valores verdadeiro/falso (<em>true/false</em>) — eles podem ter dois valores, <code>true</code> (verdadeiro) ou <code>false</code> (falso). São geralmente usados para verificar uma condição, que em seguida o código é executado apopriadamente. Por exemplo, um caso simples seria:</p> + +<pre class="brush: js notranslate">var estouVivo = true;</pre> + +<p>Enquanto na realidade seria utlizado mais da seguinte forma:</p> + +<pre class="brush: js notranslate">var teste = 6 < 3;</pre> + +<p>Esse exemplo está usando o operador "menor que" (<code><</code>) para testar se 6 é menor que 3. Como você pode esperar, irá retornar <code>false</code> (falso), porque 6 não é menor que 3! Você aprenderá mais sobre tais operadores mais tarde no curso.</p> + +<h3 id="Arrays"><em>Arrays</em></h3> + +<p>Um array é um único objeto que contém valores múltiplos inseridos entre colchetes e separados por vírgulas. Tente inserir as seguintes linhas de código no seu console:</p> + +<pre class="brush: js notranslate">var meuNomeArray = ['Chris', 'Bob', 'Jim']; +var meuNumeroArray = [10,15,40];</pre> + +<p>Uma vez que esses arrays estejam definidos, você pode acessar cada um de seus valores através de sua localização dentro do array. Tente essas linhas:</p> + +<pre class="brush: js notranslate">meuNomeArray[0]; // deve retornar 'Chris' +meuNumeroArray[2]; // deve retornar 40</pre> + +<p>Os colchetes especificam um valor do índice correspondente à posição do valor que você deseja retornado. Você talvez tenha notado que os arrays em JavaScript são indexados a partir do zero: o primeiro elemento está na posíção 0 do índice.</p> + +<p>Você aprenderá mais sobre arrays em um artigo futuro.</p> + +<h3 id="Objetos">Objetos</h3> + +<p>Em programação, um objeto é uma estrutura de código que representa um objeto da vida real. Você pode ter um simples objeto que representa um estacionamento de carro contendo informações sobre sobre sua largura e comprimento, ou você poderia ter um objeto que representa uma pessoa, e contém dados sobre seu nome, altura, peso, que idioma ela fala, como dizer olá a ela, e mais.</p> + +<p>Tente inserir a seguinte linha em seu console:</p> + +<pre class="brush: js notranslate">var cachorro = { nome : 'Totó', raca : 'Dálmata' };</pre> + +<p>Para obeter a informação armazenada no objeto, você pode usar a seguinte sintaxe:</p> + +<pre class="brush: js notranslate">cachorro.nome</pre> + +<p>Nós não iremos ver mais sobre objetos por agora — você pode aprender mais sobre eles em um artigo futuro.</p> + +<h2 id="Digitação_permissiva">Digitação permissiva</h2> + +<p>JavaScript é uma "dynamically typed language", o que significa que, diferente de outras linguagens, você não precisa especificar que tipo de dados uma variável irá conter (ex.: números, cadeias de texto, arrays, etc).</p> + +<p>Por exemplo, se você declarar uma variável e dar a ela um valor encapsulado em aspas, o navegador irá tratar a variável como sendo uma <em>string</em> (cadeia de texto):</p> + +<pre class="brush: js notranslate">var minhaString = 'Olá';</pre> + +<p>Irá continuar sendo uma <em>string</em>, mesmo que dentro das apas contenha um número, então seja cuidadoso:</p> + +<pre class="brush: js notranslate">var meuNumero = '500'; // opa, isso continua sendo uma string +typeof(meuNumero); +meuNumero = 500; // bem melhor — agora isso é um número +typeof(meuNumero);</pre> + +<p>Tente inserir as quatro linhas acima em seu console uma por uma, e veja quais são os resultados. Você notará que estamos usando uma função especial chamada <code>typeof()</code> — ela irá retornar o tipo de dado da variável que você passar. Da primeira vez que for executada, deve retornar <code>string</code>, como naquele ponto a variável <code>meuNumero</code> contém uma <em>string</em>, <code>'500'</code>. Dê uma olhada e veja o que é retornado da segunda vez que você a utilizar.</p> + +<h2 id="Constants_em_JavaScript">Constants em JavaScript</h2> + +<p>Muitas linguagens de programação têm o conceito de <em>constant</em> — um valor que uma vez declarado não pode ser alterado. Há muitas razões pelas quais você deseja fazer isso, desde segurança (se um script de terceiros alterou esses valores, poderia causar problemas) até a depuração e a compreensão do código (é mais difícil alterar acidentalmente valores que não devem ser alterados e bagunçar as coisas).</p> + +<p>Nos primeiros dias do JavaScript, não existiam <em>constants</em>. No JavaScript moderno, temos a palavra-chave <code>const</code>, que nos permite armazenar valores que nunca podem ser alterados:</p> + +<pre class="brush: js notranslate">const diasNaSemana = 7<span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number">; +const horasNoDia = 24;</span></span></span></span></pre> + +<p><span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number"><code>const</code> funciona exatamente da mesma maneira que <code>let</code>, exceto que você não pode atribuir um novo valor a <code>const</code>. No exemplo a seguir, a segunda linha geraria um erro:</span></span></span></span></p> + +<pre class="brush: js notranslate">const diasNaSemana = 7<span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number">; +</span></span></span></span>diasNaSemana<span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number"> = 8;</span></span></span></span></pre> + +<h2 id="Teste_suas_habilidades!">Teste suas habilidades!</h2> + +<p>Você chegou ao final deste artigo, mas consegue se lembrar das informações mais importantes? Você pode encontrar alguns testes adicionais para verificar se você reteve essas informações antes de prosseguir — veja <a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Teste_suas_habilidades:_variaveis">Teste suas habilidades: variáveis</a>.</p> + +<h2 id="Sumário">Sumário</h2> + +<p>Por agora você deve saber razoavelmente sobre variáveis JavaScript e como criá-las. No próximo artigo Vamos focar nos números em mais detalhes, vendo como fazer matemática básica no JavaScript.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Maths", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="Neste_módulo">Neste módulo</h2> + +<ul> + <li><a href="https://wiki.developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/O_que_e_JavaScript">O que é JavaScript?</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/A_first_splash">Um primeiro mergulho no JavaScript</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/What_went_wrong">O que deu errado? Resolvendo problemas no JavaScript</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Vari%C3%A1veis">Armazenando as informações que você precisa — Variáveis</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Matematica">Matemática básica no JavaScript — números e operadores</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Strings">Trabalhando com textos — strings em JavaScript</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos úteis de string</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Arrays">Arrays</a></li> + <li><a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/First_steps/Gerador_de_historias_bobas">Avaliação: Gerador de histórias bobas</a></li> +</ul> diff --git a/files/pt-br/learn/javascript/first_steps/what_went_wrong/index.html b/files/pt-br/learn/javascript/first_steps/what_went_wrong/index.html new file mode 100644 index 0000000000..ee121e8773 --- /dev/null +++ b/files/pt-br/learn/javascript/first_steps/what_went_wrong/index.html @@ -0,0 +1,245 @@ +--- +title: O que deu errado? Resolvendo problemas no JavaScript +slug: Learn/JavaScript/First_steps/What_went_wrong +translation_of: Learn/JavaScript/First_steps/What_went_wrong +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Quando você construiu o jogo "Adivinhe o número" no artigo anterior, você talvez tenha descoberto que ele não funcionou. Não tema — este artigo tem como objetivo impedir que você arranque os cabelos por causa desses problemas, fornecendo-lhe algumas dicas simples de como encontrar e corrigir erros nos programas JavaScript.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pré-requesitos:</th> + <td> + <p>Conhecimentos básicos de informática, uma compreensão básica de HTML e CSS, uma compreensão do que é JavaScript.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ganhar habilidade e confiança para começar a resolver problemas simples em seu próprio código.</td> + </tr> + </tbody> +</table> + +<h2 id="Tipos_de_erros">Tipos de erros</h2> + +<p>De um modo geral, quando você faz algo errado no código, existem dois tipos principais de erros que você encontrará:</p> + +<ul> + <li><strong>Erros de sintaxe:</strong> são erros de ortografia em seu código que realmente fazem com que o programa não seja executado, ou pare de trabalhar parcialmente - você geralmente receberá algumas mensagens de erro também. Estes geralmente são adequados para consertar, desde que você esteja familiarizado com as ferramentas certas e saiba o que as mensagens de erro significam!</li> + <li><strong>Erros lógicos: </strong>são erros onde a sintaxe está realmente correta, mas o código não é o que você pretendia, o que significa que o programa é executado com sucesso, mas dá resultados incorretos. Muitas vezes, eles são mais difíceis de consertar do que erros de sintaxe, pois geralmente não há uma mensagem de erro resultante para direcioná-lo para a origem do erro.</li> +</ul> + +<p>Ok, então não é assim tão simples - há alguns outros diferenciadores à medida que você aprofunda. Mas as classificações acima serão bem úteis nesta fase inicial da sua carreira. Examinaremos esses dois tipos a seguir.</p> + +<h2 id="Um_exemplo_errôneo">Um exemplo errôneo</h2> + +<p>Para começar, voltemos ao nosso jogo de adivinhação - porém desta vez estaremos explorando uma versão que tem alguns erros inseridos propositalmente. Vá até o Github e faça uma cópia local de <a href="https://github.com/mdn/learning-area-pt-br/blob/master/javascript/introduction-to-js-1/troubleshooting/jogo-numero-erros.html">jogo-numero-erros.html</a> (<a href="https://mdn.github.io/learning-area-pt-br/javascript/introduction-to-js-1/troubleshooting/jogo-numero-erros.html">veja-o em execução aqui</a>).</p> + +<ol> + <li>Para começar, abra a cópia local dentro do seu editor de texto favorito, e em seu navegador.</li> + <li>Tente jogar o jogo - você notará que, quando você pressiona o botão "Enviar palpite", ele não funciona!</li> +</ol> + +<div class="note"> +<p><strong>Nota: </strong>Talvez você tenha sua própria versão de exemplo do jogo que não funciona, e pode querer consertá-la! Nós ainda gostaríamos que você trabalhasse no artigo com a nossa versão, para que possa aprender as técnicas que estamos ensinando aqui. Daí então você pode voltar e tentar consertar seu exemplo.</p> +</div> + +<p>Neste ponto, vamos consultar o console do desenvolvedor para ver se identificamos qualquer erro de sintaxe, e então tentar consertá-lo. Você irá aprender como, logo abaixo.</p> + +<h2 id="Consertando_erros_de_sintaxe">Consertando erros de sintaxe</h2> + +<p>Anteriormente no curso, nós fizemos você digitar alguns comandos simples de JavaScript no <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">console JavaScript</a> (se você não se lembra como, abra o link anterior). O que é ainda mais útil é o fato do console lhe mostrar mensagens de erro sempre que existir algo errado na sintaxe dentro do JavaScript enviado ao motor de JavaScript do navegador. Agora vamos à caça.</p> + +<ol> + <li>Vá até a aba onde você tem aberto o arquivo <code>jogo-numero-erros.html</code> e abra o console JavaScript. Você deverá ver uma mensagem de erro sendo exibida:<br> + <img alt="" src="https://mdn.mozillademos.org/files/15590/nao-e-uma-funcao.png"></li> + <li>Esse é um erro bem fácil de identifcar, e o navegador lhe fornece várias informações úteis para lhe ajudar (a captura de tela acima foi feita no Firefox, mas os outros navegadores oferecem informações similares). Da esquerda para a direita, nós temos: + <ul> + <li>Um "x" laranja para indicar que esse é um erro.</li> + <li>Uma mensagem de erro para indicar o que está errado: "TypeError: envioPalpite.addeventListener is not a function"</li> + <li>Um link "Learn More" que encaminha à uma página no MDN docs explicando o que esse erro significa em uma quantidade enorme de detalhes.</li> + <li>O nome do arquivo JavaScript, que direciona à aba Debugger das ferramentas de desenvolvimento. Se você clicar nesse link, verá a linha exata onde o erro está destatacada.</li> + <li>O número da linha onde o erro se encontra, e o número do caractere na linha onde o erro é encontrado primeiro. Neste caso nós temos, linha 86, caractere número 3.</li> + </ul> + </li> + <li>Se olharmos para a linha 86 em nosso nosso código de código, vamos encontrar a seguinte linha: + <pre class="brush: js">envioPalpite.addeventListener('click', conferir Palpite);</pre> + </li> + <li>O erro diz o seguinte "envioPalpite.addeventListener is not a function", que significa envioPalpite.addeventListener não é uma funçao. Então provavelmente digitamos algo errado. Se você não estiver certo da digitação correta de parte da sintaxe, é uma boa ideia procurar a funcionalidade no MDN docs. A melhor forma de fazer isso atualmente é pesquisar por "mdn <em>nome-da-funcionalidade</em>" em seu mecanismo de buscas favorito. Aqui está um atalho para te salvar algum tempo nesse caso: <code><a href="/pt-BR/docs/Web/API/Element/addEventListener">addEventListener()</a></code>.</li> + <li>Então, olhando nessa essa página, o erro parece ser termos digitado o nome da função errado! Lembre-se de que o JavaScript diferencia letras maiúsculas de minúsculas, então qualquer diferença na digitação ou no uso de letras maiúsculas irá causar um erro. Alterar <code>addeventListener</code> para <code>addEventListener</code> deverá corrigir esse erro. Faça essa alteração no código do seu arquivo.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossa página de referência <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Not_a_function">TypeError: "x" is not a function</a> para mais detalhes sobre esse erro.</p> +</div> + +<h3 id="Erros_de_sintaxe_-_segundo_round">Erros de sintaxe - segundo round</h3> + +<ol> + <li>Salve o arquivo e atualize a aba do navegador, e você poderá ver que o erro foi corrigido.</li> + <li>Agora se você tentar enviar um palpite e pressionar o botão !Enviar palpite" você verá... outro erro!<br> + <img alt="" src="https://mdn.mozillademos.org/files/15591/variavel-e-nula.png"></li> + <li>Dessa vez o erro informado é "TypeError: baixoOuAlto is null", na linha 78. + <div class="note"><strong>Nota</strong>: <code><a href="/en-US/docs/Glossary/Null">Null</a></code> é um valor especial que significa "nada", ou "sem valor". Então <code>baixoOuAlto</code> foi declarado e inicializado, mas não com algum valor significativo — não possui nenhum caractere ou valor.</div> + + <div class="note"><strong>Nota</strong>: Esse erro não apareceu assim que a página foi carregada porque esse erro ocorreu dentro de uma função (dentro do bloco <code>conferirPalpite() { ... }</code> ). Como você irá aprender com mais detalhes no nosso artigo de funções mais tarde, o código localizado dentro de funções roda em um escopo separado do código presente fora das funções. Nesse caso, o código não estava rodando e o erro não estava aparecendo até a função <code>conferirPalpite()</code> ser executada na linha 86.</div> + </li> + <li>Dê uma olhada na linha 78, e você verá o seguinte código: + <pre class="brush: js">baixoOuAlto.textContent = 'Seu palpite foi muito alto!';</pre> + </li> + <li>Essa linha está tentando definir a propriedade <code>textContent</code> (conteúdo de texto) da variável <code>baixoOuAlto</code> como uma sequência de texto, mas isso não está funcionando porque <code>baixoOuAlto</code> não contém o que deveria conter. Vamos ver o porquê — tente localizar outras instâncias de <code>baixoOuAlto</code> no código. A instância que aparece primeiro no código JavaScript é na linha 48: + <pre class="brush: js">var baixoOuAlto = document.querySelector('baixoOuAlto');</pre> + </li> + <li>Nesse ponto estamos tentando fazer com que a variável contenha uma referência a um elemento no documento HTML. Vamos conferir se o valor é <code>null</code> (nulo) depois que essa linha é executada. Adicione o seguinte código na linha 49: + <pre class="brush: js">console.log(baixoOuAlto);</pre> + + <div class="note"> + <p><strong>Nota</strong>: <code><a href="/en-US/docs/Web/API/Console/log">console.log()</a></code> é uma função de debugging (correção de erros) realmente útil que exibe um valor na tela do console. Então ela irá imprimir o valor da variável <code>baixoOuAlto</code> na tela do console assim que tentarmos defini-la na linha 48.</p> + </div> + </li> + <li>Salve o arquivo e o atualize no navegador, e você deverá ver agora o resultado do <code>console.log()</code> na tela do seu console.<br> + <img alt="" src="https://mdn.mozillademos.org/files/15592/console-log-saida.png"><br> + Pois bem, nesse ponto o valor de <code>baixoOuAlto</code> e <code>null</code>, então definitivamente há um problema com a linha 48.</li> + <li>Vamos pensar em qual poderia ser o problema. A linha 48 está usando um método <code><a href="/en-US/docs/Web/API/Document/querySelector">document.querySelector()</a></code> para pegar a referência do elemento selecionado com um seletor CSS selector (<em>CSS selector</em>). Olhando mais acima no nosso código, podemos encontrar o parágrafo em questão: + <pre class="brush: js"><p class="baixoOuAlto"></p></pre> + </li> + <li>Então nós precisamos de um seletor de classe aqui, que começa com um ponto (.), mas o seletor passado pelo método <code>querySelector()</code> na linha 48 não tem o ponto. Esse pode ser o problema! Tente mudar <code>baixoOuAlto</code> para <code>.baixoOuAlto</code> na linha 48.</li> + <li>Tente salvar o arquivo e atualizá-lo no navegador de novo, e a sua declaração <code>console.log()</code> deverá retornar o elemento <code><p></code> que queremos. Ufa! Outro erro resolvido! Você pode deletar a linha do seu <code>console.log()</code> agora, ou mantê-la para referência posterior — a escolha é sua.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossa página de referência <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Unexpected_type">TypeError: "x" is (not) "y"</a> para mais detalhes sobre esse erro.</p> +</div> + +<h3 id="Erros_de_sintaxe_-_terceiro_round">Erros de sintaxe - terceiro round</h3> + +<ol> + <li>Agora se você tentar jogar novamente, você deve ter mais sucesso — o jogo deve continuar normalmente, até você terminar, ou adivinhando o número, ou ficando sem mais chances.</li> + <li>Nesse ponto, o jogo falha mais uma vez, e o mesmo erro do início é exibido — "TypeError: botaoReinicio.addeventListener is not a function"! No entanto, dessa vez é listado vindo da linha 94.</li> + <li>Olhando a linha 94, é fácil de ver que nós cometemos o mesmo erro novamente. Só precisamos alterar mais uma vez <code>addeventListener</code> para <code>addEventListener</code>. Faça isso.</li> +</ol> + +<h2 id="Um_erro_de_lógica">Um erro de lógica</h2> + +<p>Nesse ponto, o jogo deve rodar normalmente, porém depois de jogá-lo algumas vezes você irá notar que o número "aleatório" que você tem que adivinhar é sempre igual a 1. Definitivamente não é como queremos que o jogo funcione!</p> + +<p>Há sem dúvida um problema na lógica do jogo em algum lugar — o jogo não está retornando nenhum erro;simplesmente não está funcionando corretamente.</p> + +<ol> + <li>Procure pela variável <code>numeroAleatorio</code>, e as linhas onde o número aleatório é definido primeiro. A instância que armazena o número aleatório que queremos adivinhar no começo do jogo deve estar na linha 44 ou próximo a ela: + + <pre class="brush: js">var numeroAleatorio = Math.floor(Math.random()) + 1;</pre> + </li> + <li>E a linha que gera o número aleatório antes de cada jogo subsequente está na linha 113, ou próximo a ela: + <pre class="brush: js">numeroAleatorio = Math.floor(Math.random()) + 1;</pre> + </li> + <li>Para checar se essas linhas são mesmo o problema, vamos recorrer ao nosso amigo <code>console.log()</code> de novo — insira a seguinte linha diretamente abaixo de cada uma das duas linhas: + <pre class="brush: js">console.log(numeroAleatorio);</pre> + </li> + <li>Salve o arquivo e atualize o navegador, então jogue algumas vezes — você verá que o <code>numeroAleatorio</code> é igual a 1 cada vez em que é exibido no console.</li> +</ol> + +<h3 id="Trabalhando_através_da_lógica">Trabalhando através da lógica</h3> + +<p>Para consertar isso, vamos considerar como essa linha está trabalhando. Primeiro, nós invocamos <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a></code>, que gera um número decimal aleatório entre 0 e 1, ex. 0.5675493843.</p> + +<pre class="brush: js">Math.random()</pre> + +<p>Em seguida, passamos o resultado invocando <code>Math.random()</code> através de <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor">Math.floor()</a></code>, que arredonda o número passado para o menor número inteiro mais próximo. E então adicionamos 1 ao resultado:</p> + +<pre>Math.floor(Math.random()) + 1</pre> + +<p>Arredondando um número decimal aleatório entre 0 e 1 para baixo irá sempre retornar 0, então adicionando 1 a ele sempre retornará 1. Precisamos multiplicar o número aleatório por 100 antes de o arredondarmos para baixo. O código seguinte nos daria um número aleatório entre 0 and 99:</p> + +<pre class="brush: js">Math.floor(Math.random()*100);</pre> + +<p>Por isso, queremos adicionar 1, para nos dar um número aleatório entre 1 e 100:</p> + +<pre class="brush: js">Math.floor(Math.random()*100) + 1;</pre> + +<p>Tente atualizar as duas linhas dessa forma, então salve e atualize o navegador — o jogo deve agora funcionar como nós queremos que funcione!</p> + +<h2 id="Outros_erros_comuns">Outros erros comuns</h2> + +<p>Existem outros erros comuns com os quais você irá esbarrar em seu código. Essa seção destaca a maioria deles.</p> + +<h3 id="SyntaxError_missing_before_statement"><em>SyntaxError: missing ; before statement</em></h3> + +<p>Erro de sintaxe: faltando ";" antes da declaração. Esse erro geralmente significa que você deixou de inserir um ponto e vírgula ao final de uma de suas linhas de código, mas algumas vezes pode ser mais crítico. Por exemplo, se mudarmos essa linha (número 58) dentro da função <code>conferirPalpite()</code>:</p> + +<pre class="brush: js">var palpiteUsuario = Number(campoPalpite.value);</pre> + +<p>para</p> + +<pre class="brush: js">var palpiteUsuario === Number(campoPalpite.value);</pre> + +<p>Exibe esse erro porque pensa que você está fazendo algo diferente. Você deve se certificar de não misturar o operador de atribuição (<code>=</code>) — que configura uma variável para ser igual a determinado valor — com o operador de igualdade restrita (<code>===</code>), que testa se um valor é exatamente igual a outro, e retorna um resultado <code>true</code>/<code>false</code> (verdadeiro ou falso).</p> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossa página de referência <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Missing_semicolon_before_statement">SyntaxError: missing ; before statement</a> para mais detalhes sobre esse erro.</p> +</div> + +<h3 id="O_programa_sempre_diz_que_você_ganhou_independentemente_do_palpite_que_insira">O programa sempre diz que você ganhou, independentemente do palpite que insira</h3> + +<p>Isso pode ser outro sintoma de confusão entre o operador de atribuição e o operador de igualdade restrita. Por exemplo, se nós quiséssemos essa linha dentro de <code>conferirPalpite()</code>:</p> + +<pre class="brush: js">if (palpiteUsuario === numeroAleatorio) {</pre> + +<p>para</p> + +<pre class="brush: js">if (palpiteUsuario = numeroAleatorio) {</pre> + +<p>o teste retornaria sempre <code>true</code> (verdadeiro), causando o programa a reportar que o jogo foi vencido. Tome cuidado!</p> + +<h3 id="SyntaxError_missing_after_argument_list"><em>SyntaxError: missing ) after argument list</em></h3> + +<p>Erro de sintaxe: faltando ")" depois de listar uma declaração. Esse é bem simples — geralmente significa que deixamos de fechar o parênteses no final ao invocar uma função/método.</p> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossa página de referência <a href="/en-US/docs/Web/JavaScript/Reference/Errors/Missing_parenthesis_after_argument_list">SyntaxError: missing ) after argument list</a> para mais detalhes sobre o erro.</p> +</div> + +<h3 id="SyntaxError_missing_after_property_id"><em>SyntaxError: missing : after property id</em></h3> + +<p>Erro de sintaxe: faltando ":" depois da propriedade id. Esse erro geralmente se relaciona à formação incorreta de um objeto de JavaScript, mas nesse caso o obtivemos alterando:</p> + +<pre class="brush: js">function conferirPalpite() {</pre> + +<p>para</p> + +<pre class="brush: js">function conferirPalpite( {</pre> + +<p>Isso levou o navegador a pensar que estávamos tentando passar todo o conteúdo da função como se fosse um argumento dessa função. Seja cuidadoso com esses parênteses!</p> + +<h3 id="SyntaxError_missing_after_function_body"><em>SyntaxError: missing } after function body</em></h3> + +<p>Erro de sintaxe: faltando "}" depois do corpo da função. Isso é fácil — geralmente significa que você deixou de colocar uma das chaves de uma função ou de uma estrutura condicional. Nós obtemos esse erro deletando uma das chaves de fechamento próximas ao final da função <code>conferirPalpite()</code>.</p> + +<h3 id="SyntaxError_expected_expression_got_string_ou_SyntaxError_unterminated_string_literal"><em>SyntaxError: expected expression, got 'string' </em>ou <em>SyntaxError: unterminated string literal</em></h3> + +<p>Erro de sintaxe: esperado uma expressão, obtido uma 'string' e Erro de sintaxe: string literal não terminada. Esses erros geralmente significam que você deixou de colocar aspas no início ou no final da declaração de uma cadeia de texto. No primeiro erro acima, '<em>string'</em> seria substituído pelo(s) caractere(s) encontrado(s) pelo navegador ao invés da aspa no início de uma cadeia de texto. O segundo erro quer dizer que a cadeia de texto não foi finalizada com o caractere de aspa.</p> + +<p>Para todos esses erros, pense em como nós abordamos os exemplos em que olhamos no passo a passo. Quando um erro surge, olha o número da linha que é informado, vá até essa linha e veja se consegue localizar o que há de errado. Mantenha em mente que o erro não estará necessariamente nessa linha, e também que o erro pode não ter sido causado exatamente pelo mesmo problema que citamos acima!</p> + +<div class="note"> +<p><strong>Nota</strong>: Veja nossas páginas de referência <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Unexpected_token">SyntaxError: Unexpected token</a> e <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors/Unterminated_string_literal">SyntaxError: unterminated string literal</a> para mais detalhes sobre esses erros.</p> +</div> + +<h2 id="Sumário">Sumário</h2> + +<p>Então aqui temos, o básico de como resolver erros em programas simples de JavaScript. Não será sempre tão fácil de solucionar o que está errado em seu código, mas pelo menos isso irá te poupar algumas horas de sono e lhe permitir progredir um pouco mais rápido quando as coisas não saírem certas no início da sua jornada de aprendizado.</p> + +<h2 id="Veja_também">Veja também</h2> + +<div> +<ul> + <li>Há muitos outros tipos de erros que não listamos aqui; estamos compilando uma referência que explica o que eles significam em detalhes — veja a <a href="/pt-BR/docs/Web/JavaScript/Reference/Errors">referência de erros do JavaScript</a>.</li> + <li>Se você se deparar com qualquer erro em seu código que não tenha certeza de como resolver mesmo depois de ler este artigo, você pode pedir ajuda! Pergunte na <a class="external external-icon" href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">Área de Discussão e Aprendizagem</a>, ou no canal IRC <a href="irc://irc.mozilla.org/mdn">#mdn</a> em <a class="external external-icon" href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Nos diga quel é o seu erro, e nós iremos tentar te ajudar. Uma amostra do seu código também seria útil.</li> +</ul> +</div> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}</p> |