Estrutura do Programa
E meu coração brilha vermelho vivo sob minha pele fina e translúcida e eles precisam administrar 10cc de JavaScript para me fazer voltar. (Eu respondo bem a toxinas no sangue.) Cara, essa coisa vai tirar os pêssegos direto das suas guelras!

Neste capítulo, começaremos a fazer coisas que realmente podem ser chamadas de programação. Vamos expandir nosso domínio da linguagem JavaScript além dos substantivos e fragmentos de frases que vimos até agora, até o ponto em que possamos expressar uma prosa significativa.
Expressões e instruções
No Capítulo 1, criamos valores e aplicamos operadores a eles para obter novos valores. Criar valores assim é a substância principal de qualquer programa JavaScript. Mas essa substância precisa ser enquadrada em uma estrutura maior para ser útil. É isso que cobriremos neste capítulo.
Um fragmento de código que produz um valor é chamado de expressão. Todo valor que é escrito literalmente (como 22 ou "psychoanalysis") é uma expressão. Uma expressão entre parênteses também é uma expressão, assim como um operador binário aplicado a duas expressões ou um operador unário aplicado a uma.
Isso mostra parte da beleza de uma interface baseada em linguagem. Expressões podem conter outras expressões de uma forma semelhante a como subfrases em línguas humanas são aninhadas — uma subfrase pode conter suas próprias subfrases, e assim por diante. Isso nos permite construir expressões que descrevem cálculos arbitrariamente complexos.
Se uma expressão corresponde a um fragmento de frase, uma instrução JavaScript corresponde a uma frase completa. Um programa é uma lista de instruções.
O tipo mais simples de instrução é uma expressão com um ponto e vírgula depois. Este é um programa:
1;
!false;
No entanto, é um programa inútil. Uma expressão pode se contentar em apenas produzir um valor, que pode então ser usado pelo código que a envolve. Porém, uma instrução existe por si só, então se ela não afeta o mundo, é inútil. Pode exibir algo na tela, como com console.log, ou alterar o estado da máquina de uma forma que influencie as instruções que vierem depois. Essas mudanças são chamadas de efeitos colaterais. As instruções no exemplo anterior apenas produzem os valores 1 e true e então os descartam imediatamente. Isso não deixa nenhuma impressão no mundo. Quando você executa esse programa, nada observável acontece.
Em alguns casos, o JavaScript permite que você omita o ponto e vírgula no final de uma instrução. Em outros casos, ele precisa estar lá, ou a próxima linha será tratada como parte da mesma instrução. As regras para quando pode ser omitido com segurança são um pouco complexas e propensas a erros. Então, neste livro, toda instrução que precisar de ponto e vírgula sempre terá um. Recomendo que você faça o mesmo, pelo menos até aprender mais sobre as sutilezas dos pontos e vírgulas ausentes.
Ligações
Como um programa mantém um estado interno? Como ele lembra das coisas? Vimos como produzir novos valores a partir de valores antigos, mas isso não altera os valores antigos, e o novo valor precisa ser usado imediatamente ou ele se dissipará novamente. Para capturar e manter valores, o JavaScript fornece uma coisa chamada ligação, ou variável.
let caught = 5 * 5;
Isso nos dá um segundo tipo de instrução. A palavra especial (keyword) let indica que esta instrução vai definir uma ligação. Ela é seguida pelo nome da ligação e, se quisermos dar imediatamente um valor, por um operador = e uma expressão.
O exemplo cria uma ligação chamada caught e a usa para segurar o número que é produzido ao multiplicar 5 por 5.
Depois que uma ligação é definida, seu nome pode ser usado como uma expressão. O valor de tal expressão é o valor que a ligação atualmente mantém. Aqui está um exemplo:
let ten = 10; console.log(ten * ten); // → 100
Quando uma ligação aponta para um valor, isso não significa que está presa a esse valor para sempre. O operador = pode ser usado a qualquer momento em ligações existentes para desconectá-las do seu valor atual e fazê-las apontar para um novo:
let mood = "light"; console.log(mood); // → light mood = "dark"; console.log(mood); // → dark
Você deve imaginar ligações mais como tentáculos do que caixas. Eles não contêm valores; eles os agarram — duas ligações podem se referir ao mesmo valor. Um programa pode acessar apenas os valores para os quais ainda tem uma referência. Quando você precisa lembrar de algo, você ou cresce um tentáculo para segurá-lo ou reconecta um dos seus tentáculos existentes a ele.
Vamos ver outro exemplo. Para lembrar o número de dólares que Luigi ainda te deve, você cria uma ligação. Quando ele paga $35 de volta, você dá a essa ligação um novo valor.
let luigisDebt = 140; luigisDebt = luigisDebt - 35; console.log(luigisDebt); // → 105
Quando você define uma ligação sem dar a ela um valor, o tentáculo não tem nada para agarrar, então termina no vazio. Se você pedir o valor de uma ligação vazia, receberá o valor undefined.
Uma única instrução let pode definir várias ligações. As definições devem ser separadas por vírgulas:
let one = 1, two = 2; console.log(one + two); // → 3
As palavras var e const também podem ser usadas para criar ligações, de forma semelhante ao let.
var name = "Ayda"; const greeting = "Hello "; console.log(greeting + name); // → Hello Ayda
A primeira delas, var (abreviação de “variable”), é a forma como as ligações eram declaradas no JavaScript pré-2015, quando let ainda não existia. Voltarei à forma precisa como ela difere do let no próximo capítulo. Por enquanto, lembre-se de que ela faz basicamente a mesma coisa, mas raramente a usaremos neste livro porque seu comportamento é estranho em algumas situações.
A palavra const significa constante. Ela define uma ligação constante, que aponta para o mesmo valor enquanto existir. Isso é útil para ligações que apenas dão um nome a um valor para que você possa se referir a ele facilmente depois.
Nomes de ligações
Nomes de ligações podem ser qualquer sequência de uma ou mais letras. Dígitos podem fazer parte dos nomes de ligações — catch22 é um nome válido, por exemplo — mas o nome não pode começar com um dígito. Um nome de ligações pode incluir cifrões ($) ou underscores (_), mas nenhum outro sinal de pontuação ou caractere especial.
Palavras com um significado especial, como let, são keywords, e não podem ser usadas como nomes de ligação. Existem também várias palavras que são “reservadas para uso” em versões futuras do JavaScript, que também não podem ser utilizadas como nomes de ligação. A lista completa de palavras-chave e reservadas é bastante longa:
break case catch class const continue debugger default delete do else enum export extends false finally for function if implements import interface in instanceof let new package private protected public return static super switch this throw true try typeof var void while with yield
Não se preocupe em decorar essa lista. Quando criar uma ligação gerar um erro de sintaxe inesperado, confira se você está tentando definir uma palavra reservada.
O ambiente
A coleção de ligações e seus valores que existem em um dado momento é chamada de ambiente. Quando um programa é iniciado, esse ambiente não está vazio. Ele sempre contém ligações que fazem parte do padrão da linguagem, e na maioria das vezes, também possui ligações que fornecem maneiras de interagir com o sistema ao redor. Por exemplo, em um browser, existem funções para interagir com o site carregado atualmente e para ler entradas do mouse e do teclado.
Functions
Muitos dos valores fornecidos no ambiente padrão têm o tipo function. Uma função é uma parte do programa encapsulada em um valor. Esses valores podem ser aplicados para executar o programa encapsulado. Por exemplo, em um ambiente de navegador, a ligação prompt contém uma função que exibe uma pequena caixa de diálogo pedindo uma entrada do usuário. É usado assim:
prompt("Enter passcode");
Executar uma função é chamado de invocar, chamar ou aplicar a função. Você pode chamar uma função colocando parênteses após uma expressão que produz um valor de função. Normalmente, você usará diretamente o nome da ligação que contém a função. Os valores entre os parênteses são passados para o programa dentro da função. No exemplo, a função prompt usa a string que damos a ela como o texto para mostrar na caixa de diálogo. Os valores passados para funções são chamados de argumentos. Funções diferentes podem necessitar de um número diferente ou tipos diferentes de argumentos.
A função prompt não é muito usada na programação web moderna, principalmente porque você não tem controle sobre a forma como a caixa de diálogo resultante aparece, mas pode ser útil em programas simples e experimentos.
A função console.log
Nos exemplos, usei console.log para exibir valores. A maioria dos sistemas JavaScript (incluindo todos os navegadores modernos e o Node.js) fornece uma função console.log que escreve seus argumentos em algum dispositivo de saída de texto. Nos navegadores, a saída vai para o console JavaScript. Essa parte da interface do navegador fica oculta por padrão, mas a maioria dos navegadores a abre quando você pressiona F12 ou, em um Mac, command-option-I. Se isso não funcionar, procure nos menus um item chamado Developer Tools ou similar.
Ao executar os exemplos (ou seu próprio código) nas páginas deste livro, a saída do console.log será mostrada após o exemplo, em vez de no console JavaScript do navegador.
let x = 30; console.log("the value of x is", x); // → the value of x is 30
Embora nomes de ligação não possam conter pontos, console.log possui um. Isso porque console.log não é uma ligação simples, mas uma expressão que obtém a propriedade log do valor guardado pela ligação console. Descobriremos exatamente o que isso significa no Capítulo 4.
Valores de retorno
Exibir uma caixa de diálogo ou escrever texto na tela é um efeito colateral. Muitas funções são úteis por causa dos efeitos colaterais que produzem. Funções também podem produzir valores, caso em que não precisam ter efeito colateral para serem úteis. Por exemplo, a função Math.max recebe qualquer quantidade de argumentos numéricos e retorna o maior.
console.log(Math.max(2, 4)); // → 4
Quando uma função produz um valor, dizemos que ela retorna esse valor. Tudo que produz um valor é uma expressão em JavaScript, o que significa que chamadas de função podem ser usadas dentro de expressões maiores. No código a seguir, uma chamada a Math.min, que é o oposto de Math.max, é usada como parte de uma expressão de soma:
console.log(Math.min(2, 4) + 100); // → 102
Capítulo 3 explicará como escrever suas próprias funções.
Fluxo de controle
Quando seu programa contém mais de uma instrução, as instruções são executadas como se fossem uma história, de cima para baixo. Por exemplo, o seguinte programa tem duas instruções. A primeira pede ao usuário um número, e a segunda, que é executada depois da primeira, mostra o quadrado desse número:
let theNumber = Number(prompt("Pick a number")); console.log("Your number is the square root of " + theNumber * theNumber);
A função Number converte um valor para um número. Precisamos dessa conversão porque o resultado de prompt é um valor string, e queremos um número. Existem funções similares chamadas String e Boolean que convertem valores para esses tipos.
Aqui está uma representação esquemática bastante trivial do fluxo de controle linear:
Execução condicional
Nem todos os programas são estradas retas. Podemos, por exemplo, querer criar um caminho ramificado onde o programa escolhe a ramificação correta com base na situação atual. Isso é chamado de execução condicional.
A execução condicional é criada com a palavra-chave if em JavaScript. No caso simples, queremos que algum código seja executado se, e somente se, uma certa condição for verdadeira. Podemos, por exemplo, querer mostrar o quadrado do valor digitado apenas se o valor digitado for realmente um número:
let theNumber = Number(prompt("Pick a number")); if (!Number.isNaN(theNumber)) { console.log("Your number is the square root of " + theNumber * theNumber); }
Com essa modificação, se você inserir “parrot”, nenhuma saída será mostrada.
A palavra-chave if executa ou pula uma instrução dependendo do valor de uma expressão Boolean. A expressão decisória é escrita após a palavra-chave, entre parênteses, seguida pela instrução a ser executada.
A função Number.isNaN é uma função padrão do JavaScript que retorna true apenas se o argumento que recebe for NaN. A função Number eventualmente retorna NaN quando você passa para ela uma string que não representa um número válido. Assim, a condição traduz-se para “a menos que theNumber seja not-a-number, faça isto”.
A instrução após o if está envolvida por chaves ({ e }) neste exemplo. As chaves podem ser usadas para agrupar qualquer número de instruções em uma única instrução, chamada um bloco. Você também poderia tê-las omitido neste caso, já que há apenas uma instrução, mas para evitar ter que pensar se elas são necessárias, a maioria dos programadores JavaScript as usa em toda instrução agrupada como esta. Seguiremos essa convenção na maior parte deste livro, exceto em casos ocasionais de uma linha só.
if (1 + 1 == 2) console.log("It's true"); // → It's true
Frequentemente você não terá só código que é executado quando uma condição é verdadeira, mas também código que lida com o outro caso. Esse caminho alternativo é representado pela segunda seta no diagrama. Você pode usar a palavra-chave else, junto com if, para criar dois caminhos de execução separados e alternativos:
let theNumber = Number(prompt("Pick a number")); if (!Number.isNaN(theNumber)) { console.log("Your number is the square root of " + theNumber * theNumber); } else { console.log("Hey. Why didn't you give me a number?"); }
Se você tiver mais de dois caminhos para escolher, pode “encadear” múltiplos pares if/else. Aqui está um exemplo:
let num = Number(prompt("Pick a number")); if (num < 10) { console.log("Small"); } else if (num < 100) { console.log("Medium"); } else { console.log("Large"); }
O programa primeiro verificará se num é menor que 10. Se for, ele escolhe essa ramificação, exibe "Small" e termina. Se não for, segue pela ramificação else, que por sua vez contém um segundo if. Se a segunda condição (< 100) for verdadeira, isso significa que o número é pelo menos 10, mas menor que 100, e "Medium" será exibido. Se não for, a segunda e última ramificação else será escolhida. O esquema para este programa fica algo assim:
while e do loops
Considere um programa que exibe todos os número pares de 0 a 12. Uma forma de escrever isso é a seguinte:
console.log(0); console.log(2); console.log(4); console.log(6); console.log(8); console.log(10); console.log(12);
Isso funciona, mas a ideia de escrever um programa é fazer algo com menos trabalho, não mais. Se precisássemos de todos os números pares menores que 1.000, essa abordagem seria inviável. O que precisamos é de uma forma de executar um pedaço de código múltiplas vezes. Essa forma de fluxo de controle é chamada de loop.
O fluxo de controle em loop nos permite voltar a algum ponto do programa onde já estivemos antes e repeti-lo com o estado atual do programa. Se combinarmos isso com uma ligação que conte, podemos fazer algo como isto:
let number = 0; while (number <= 12) { console.log(number); number = number + 2; } // → 0 // → 2 // … e assim por diante
{{index “while loop”, Boolean, [parênteses, statement]}}
Uma instrução que começa com a palavra-chave while cria um loop. A palavra while é seguida de uma expressão entre parênteses e depois uma instrução, bem parecido com if. O loop continua executando essa instrução enquanto a expressão produzir um valor que avalie para true quando convertido para Boolean.
A ligação number demonstra a maneira como uma ligação pode monitorar o progresso de um programa. Cada vez que o loop se repete, number recebe um valor 2 maior que o valor anterior. No início de cada repetição, ele é comparado com o número 12 para decidir se o trabalho do programa terminou.
Como um exemplo que realmente faz algo útil, agora podemos escrever um programa que calcula e mostra o valor de 210 (2 elevado à 10ª potência). Usamos duas ligações: uma para acompanhar nosso resultado e outra para contar quantas vezes multiplicamos esse resultado por 2. O loop verifica se a segunda ligação já chegou a 10 e, se não, atualiza ambas as ligações.
let result = 1; let counter = 0; while (counter < 10) { result = result * 2; counter = counter + 1; } console.log(result); // → 1024
O contador também poderia ter começado em 1 e checado por <= 10, mas por motivos que ficarão claros no Capítulo 4, é uma boa ideia se acostumar a contar a partir de 0.
Note que JavaScript também possui um operador para exponenciação (2 ** 10), que você usaria para calcular isso em código real—mas isso teria estragado o exemplo.
Um loop do é uma estrutura de controle semelhante ao loop while. Ele difere em apenas um ponto: um do loop sempre executa seu corpo ao menos uma vez, e só começa a testar se deve parar após essa primeira execução. Para refletir isso, o teste aparece depois do corpo do loop:
let seuNome; do { seuNome = prompt("Quem é você?"); } while (!seuNome); console.log("Olá " + seuNome);
Este programa vai forçar você a digitar um nome. Ele vai perguntar de novo e de novo até obter algo que não seja uma string vazia. Aplicar o operador ! converte um valor para o tipo Boolean antes de negá-lo, e todas as strings exceto "" se convertem para true. Isso significa que o loop continua rodando até que você forneça um nome não vazio.
Indentando Código
Nos exemplos, tenho adicionado espaços na frente das instruções que fazem parte de alguma instrução maior. Esses espaços não são obrigatórios — o computador aceita o programa muito bem sem eles. De fato, até as quebras de linha em programas são opcionais. Você poderia escrever um programa numa única linha longa se quisesse.
O papel dessa indentação dentro de blocos é fazer com que a estrutura do código se destaque para os leitores humanos. Em código onde novos blocos são abertos dentro de outros blocos, pode ficar difícil ver onde termina um bloco e começa outro. Com uma indentação adequada, o formato visual de um programa corresponde à forma dos blocos dentro dele. Eu gosto de usar dois espaços para cada bloco aberto, mas gostos diferem — algumas pessoas usam quatro espaços, e algumas usam caractere tab. O importante é que cada novo bloco adicione a mesma quantidade de espaço.
if (false != true) { console.log("Isso faz sentido."); if (1 < 2) { console.log("Sem surpresa aí."); } }
A maioria dos programas editor de código (inclusive o deste livro) ajuda ao identar automaticamente as novas linhas com a quantidade adequada.
for loops
Muitos loops seguem o padrão mostrado nos exemplos de while. Primeiro, uma vinculação “contador” é criada para acompanhar o progresso do loop. Depois vem um loop while, geralmente com uma expressão de teste que verifica se o contador alcançou seu valor final. No final do corpo do loop, o contador é atualizado para acompanhar o progresso.
Por causa deste padrão ser tão comum, JavaScript e linguagens similares fornecem uma forma um pouco mais curta e abrangente, o loop for:
for (let numero = 0; numero <= 12; numero = numero + 2) { console.log(numero); } // → 0 // → 2 // … etcetera
Este programa é exatamente equivalente ao exemplo anterior que imprime números pares. A única mudança é que todas as instruçõess relacionadas ao “estado” do loop são agrupadas após o for.
Os parênteses após a palavra-chave for devem conter dois ponto e vírgulas. A parte antes do primeiro ponto e vírgula inicializa o loop, normalmente definindo uma vinculação. A segunda parte é a expressão que verifica se o loop deve continuar. A parte final atualiza o estado do loop após cada iteração. Na maioria dos casos, isso é mais curto e claro do que uma construção while.
Este é o código que calcula 210 usando for ao invés de while:
let resultado = 1; for (let contador = 0; contador < 10; contador = contador + 1) { resultado = resultado * 2; } console.log(resultado); // → 1024
Saindo de um Loop
Fazer a condição do loop resultar em false não é a única forma de um loop terminar. A instrução break tem o efeito de pular imediatamente para fora do loop que o envolve. Seu uso é demonstrado no programa seguinte, que encontra o primeiro número que seja maior ou igual a 20 e divisível por 7:
for (let current = 20; ; current = current + 1) { if (current % 7 == 0) { console.log(current); break; } } // → 21
Usar o operador de resto (%) é uma maneira fácil de testar se um número é divisível por outro número. Se for, o resto da divisão entre eles é zero.
A construção for no exemplo não tem uma parte que verifica o fim do loop. Isso significa que o loop nunca vai parar a menos que a instrução break dentro dele seja executada.
Se você remover essa instrução break ou acidentalmente escrever uma condição de fim que sempre resulta em true, seu programa ficará preso num loop infinito. Um programa preso em um loop infinito nunca terminará de rodar, o que geralmente é ruim.
Se você criar um loop infinito em um dos exemplos nestas páginas, normalmente será perguntado se quer parar o script depois de alguns segundos. Se isso falhar, você terá que fechar a aba onde está trabalhando para recuperar.
A palavra-chave continue é semelhante ao break porque também influencia o andamento de um loop. Quando continue é encontrado no corpo do loop, o controle sai do corpo e continua com a próxima iteração do loop.
Atualizando ligações de forma sucinta
Especialmente ao fazer loop, um programa frequentemente precisa “atualizar” uma ligação para conter um valor baseado no valor anterior dessa ligação.
counter = counter + 1;
JavaScript oferece um atalho para isso:
counter += 1;
Atalhos similares funcionam para muitos outros operadores, como result *= 2 para dobrar result ou counter -= 1 para contar para baixo.
Isso nos permite encurtar ainda mais nosso exemplo de contagem:
for (let number = 0; number <= 12; number += 2) { console.log(number); }
Para counter += 1 e counter -= 1, existem equivalentes ainda mais curtos: counter++ e counter--.
Despachando com switch baseado em um valor
Não é incomum o código parecer assim:
if (x == "value1") action1(); else if (x == "value2") action2(); else if (x == "value3") action3(); else defaultAction();
Existe uma construção chamada switch que pretende expressar esse tipo de “despacho” de forma mais direta. Infelizmente, a sintaxe que o JavaScript usa para isso (que herdou da linha de linguagens de programação C/Java) é meio estranha — uma cadeia de instruções if pode parecer melhor. Aqui está um exemplo:
switch (prompt("What is the weather like?")) { case "rainy": console.log("Remember to bring an umbrella."); break; case "sunny": console.log("Dress lightly."); case "cloudy": console.log("Go outside."); break; default: console.log("Unknown weather type!"); break; }
Você pode colocar qualquer número de rótulos case dentro do bloco aberto pelo switch. O programa começará a executar no rótulo que corresponde ao valor dado ao switch, ou no default se nenhum valor correspondente for encontrado. Ele continuará executando, mesmo passando por outros rótulos, até encontrar uma instrução break. Em alguns casos, como o caso "sunny" no exemplo, isso pode ser usado para compartilhar algum código entre casos (recomenda ir para fora tanto no tempo ensolarado quanto no nublado). Tenha cuidado, contudo — é fácil esquecer um break como esse, o que fará o programa executar código que você não quer que seja executado.
Capitalização
Nomes de ligação não podem conter espaços, mas muitas vezes é útil usar múltiplas palavras para descrever claramente o que a ligação representa. Estas são basicamente suas opções para escrever um nome de ligação com várias palavras:
fuzzylittleturtle fuzzy_little_turtle FuzzyLittleTurtle fuzzyLittleTurtle
O primeiro estilo pode ser difícil de ler. Eu gosto mais da aparência dos underscores, embora esse estilo seja um pouco doloroso de digitar. As funções standard do JavaScript, e a maioria dos programadores JavaScript, seguem o último estilo—eles capitalizam todas as palavras exceto a primeira. Não é difícil se acostumar com pequenos detalhes assim, e código com estilos mistos de nomes pode ser desconfortável para ler, então seguimos essa convenção.
Em alguns casos, como a função Number, a primeira letra da ligação também é capitalizada. Isso foi feito para marcar essa função como um construtor. Ficará claro o que é um construtor em Capítulo 6. Por enquanto, o importante é não se incomodar com essa aparente falta de consistência.
Comentários
Frequentemente, o código bruto não transmite toda a informação que você quer que um programa transmita aos leitores humanos, ou transmite de uma forma tão críptica que as pessoas podem não entender. Outras vezes, você pode querer apenas incluir alguns pensamentos relacionados como parte do seu programa. É para isso que servem os comentários.
Um comentário é um pedaço de texto que faz parte do programa, mas é completamente ignorado pelo computador. JavaScript tem duas formas de escrever comentários. Para escrever um comentário de linha única, você pode usar dois caracteres de barra (//) e depois o texto do comentário:
let accountBalance = calculateBalance(account); // É uma verde cavidade onde um rio canta accountBalance.adjust(); // Loucamente pegando flocos brancos na grama. let report = new Report(); // Onde o sol no orgulhoso monte ressoa: addToReport(accountBalance, report); // É um pequeno vale, espumando como luz em um copo.
Um comentário // vai somente até o fim da linha. Um trecho de texto entre /* e */ será ignorado completamente, independentemente de conter quebras de linha. Isso é útil para adicionar blocos de informação sobre um arquivo ou um trecho do programa:
/* Eu encontrei este número escrito no verso de um velho caderno. Desde então, ele tem aparecido várias vezes, em números de telefone e nos números de série de produtos que comprei. Obviamente ele gosta de mim, então decidi mantê-lo. */ const myNumber = 11213;
Resumo
Agora você sabe que um programa é construído com instruções, que às vezes contêm outras instruções. Instruções tendem a conter expressões, que por sua vez podem ser construídas a partir de expressões menores.
Colocar instruções uma após a outra resulta em um programa que é executado de cima para baixo. Você pode inserir desvios no fluxo de controle usando instruções condicionais (if, else e switch) e de repetição (while, do e for).
Ligações podem ser usadas para arquivar pedaços de dados sob um nome, e eles são úteis para acompanhar o estado no seu programa. O ambiente é o conjunto de ligações que estão definidas. Sistemas JavaScript sempre colocam várias ligações padrões úteis em seu ambiente.
Funções são valores especiais que encapsulam um pedaço de programa. Você pode invocá-las escrevendo functionName(argument1, argument2). Essa chamada de função é uma expressão e pode produzir um valor.
Exercícios
Se você não tem certeza de como testar suas soluções para os exercícios, consulte a introdução.
Cada exercício começa com uma descrição do problema. Leia essa descrição e tente resolver o exercício. Se você encontrar dificuldades, considere ler as dicas depois do exercício. Você pode encontrar soluções completas para os exercícios online em https://eloquentjavascript.net/code. Se quiser aprender algo com os exercícios, recomendo olhar as soluções somente depois de resolver o exercício, ou pelo menos depois de ter se esforçado bastante a ponto de ficar com uma leve dor de cabeça.
Fazendo um triângulo com loop
Escreva um loop que faça sete chamadas para console.log para imprimir o seguinte triângulo:
# ## ### #### ##### ###### #######
Pode ser útil saber que você pode encontrar o comprimento de uma string escrevendo .length após ela.
let abc = "abc"; console.log(abc.length); // → 3
A maioria dos exercícios contém um pedaço de código que você pode modificar para resolver o exercício. Lembre-se de que você pode clicar nos blocos de código para editá-los.
// Seu código aqui.
Mostrar dicas...
Você pode começar com um programa que imprime os números de 1 a 7, o que você pode derivar fazendo algumas modificações no exemplo de impressão de números pares dado anteriormente no capítulo, onde o for loop foi introduzido.
Agora considere a equivalência entre números e strings de caracteres hash. Você pode ir de 1 para 2 adicionando 1 (+= 1). Você pode ir de "#" para "##" adicionando um caractere (+= "#") . Assim, sua solução pode seguir de perto o programa de impressão de números.
FizzBuzz
Escreva um programa que use console.log para imprimir todos os números de 1 a 100, com duas exceções. Para números divisíveis por 3, imprima "Fizz" em vez do número, e para números divisíveis por 5 (e não por 3), imprima "Buzz".
Quando isso funcionar, modifique seu programa para imprimir "FizzBuzz" para números divisíveis por 3 e 5 (e ainda imprimir "Fizz" ou "Buzz" para números divisíveis por apenas um deles).
(Este é na verdade um entrevista que foi alegadamente usado para eliminar uma porcentagem significativa de candidatos a programador. Então, se você o resolveu, seu valor no mercado de trabalho acabou de subir.)
// Seu código aqui.
Mostrar dicas...
Analisar os números é claramente um trabalho de looping, e selecionar o que imprimir é uma questão de execução condicional. Lembre-se do truque de usar o operador resto (%) para verificar se um número é divisível por outro número (tem resto zero).
Na primeira versão, há três resultados possíveis para cada número, então você terá que criar uma cadeia if/else if/else.
A segunda versão do programa tem uma solução direta e uma inteligente. A solução simples é adicionar outro “ramo” condicional para testar precisamente a condição dada. Para a solução inteligente, construa uma string contendo a palavra ou palavras a serem exibidas e imprima esta palavra ou o número caso não haja palavra, potencialmente fazendo bom uso do operador ||.
Tabuleiro de xadrez
Escreva um programa que crie uma string que represente uma grade 8×8, usando caracteres de nova linha para separar as linhas. Em cada posição da grade há um espaço ou um caractere "#". Os caracteres devem formar um tabuleiro de xadrez.
Passar essa string para console.log deve mostrar algo como isto:
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Quando você tiver um programa que gera esse padrão, defina uma ligação size = 8 e altere o programa para que ele funcione para qualquer size, exibindo uma grade da largura e altura dadas.
// Seu código aqui.
Mostrar dicas...
Você pode construir a string começando com uma vazia ("") e adicionando caracteres repetidamente. Um caractere de nova linha é escrito "\n".
Para trabalhar com duas dimensões, você precisará de um loop dentro de outro loop. Coloque chaves ao redor dos corpos de ambos os loops para facilitar ver onde começam e terminam. Tente indentar adequadamente esses corpos. A ordem dos loops deve seguir a ordem na qual construímos a string (linha por linha, da esquerda para a direita, de cima para baixo). Então o loop externo trata das linhas, e o loop interno trata dos caracteres em uma linha.
Você precisará de duas ligações para acompanhar seu progresso. Para saber se deve colocar um espaço ou uma cerquilha numa posição dada, você pode testar se a soma dos dois contadores é par (% 2).
Terminar uma linha adicionando um caractere de nova linha deve acontecer após a linha ter sido construída, então faça isso depois do loop interno mas dentro do loop externo.