Comentários são linhas de código que JavaScript vai ignorar intencionalmente. Os comentários são uma ótima maneira de deixar anotações para você mesmo e para outras pessoas que mais tarde precisarão descobrir o que esse código faz.
Existem duas maneiras de escrever comentários em JavaScript:
Usar //
dirá ao JavaScript para ignorar o resto do texto na linha atual. Isso é um comentário de uma linha:
// This is an in-line comment.
Você pode fazer um comentário de mais de uma linha, começando com /*
e terminando com */
. Este é um comentário em várias linhas:
/* This is amulti-line comment */
Na ciência da computação, dado é qualquer coisa que tenha significado para o computador. JavaScript fornece oito tipos de dados diferentes que são undefined
, null
, boolean
, string
, symbol
, bigint
, number
e object
.
Por exemplo, os computadores distinguem números, como o número12
, e strings
, como o "12"
, "dog"
, ou"123 cats"
, as quais são coleções de caracteres. Computadores podem realizar operações matemáticas em um número, mas não em uma string.
Variáveis permitem aos computadores armazenar e manipular dados de forma dinâmica. Elas fazem isso usando uma “etiqueta” para apontar para o dado ao invés de usar o próprio dado. Qualquer um dos 8 tipos de dados pode ser armazenado em uma variável.
Variáveis são similares às variáveis x e y utilizadas na matemática, o que significa que elas são simples nomes para representar os dados aos quais se referem. Variáveis de computador diferem das variáveis matemáticas porque elas podem armazenar diferentes valores em momentos diferentes.
Dizemos ao JavaScript para criar ou declarar uma variável colocando a palavra-chave var
na frente dela, dessa forma:
var ourName;
cria uma variável chamada ourName
. Em JavaScript, terminamos uma instrução com ponto e vírgula. Nomes de variáveis podem ser formados por números, letras e $
ou _
, mas não podem conter espaços ou começar com um número.
Em JavaScript, você pode armazenar um valor em uma variável com o operador de atribuição (=
).
myVariable = 5;
Isso atribui um valor do tipo Number
de 5
para myVariable
.
Se há qualquer cálculo à direita do operador =
, esses cálculos são executados antes do valor ser atribuído à variável na esquerda do operador.
var myVar;
myVar = 5;
Primeiro, esse código cria uma variável chamada myVar
. Em seguida, o código atribui 5
para myVar
. Agora, se myVar
aparece novamente no código, o programa vai tratá-la como se fosse 5
.
Após um valor ser atribuído para uma variável usando o operador de atribuição, você pode atribuir o valor daquela variável para outra variável usando o operador de atribuição.
var myVar;
myVar = 5;
var myNum;
myNum = myVar;
O código acima declara uma variável myVar
sem valor, e então atribui a ela o valor 5
. Em seguida, uma variável chamada myNum
é declarada sem valor. Depois, o conteúdo de myVar
(o qual é 5
) é atribuído para a variável myNum
. Agora, myNum
também possui o valor de 5
.
É comum inicializar a variável com um valor inicial na mesma linha em que é declarada.
var myVar = 0;
Cria uma nova variável chamada myVar
e atribua o seu valor inicial como 0
.
Anteriormente, você usou o seguinte código para declarar uma variável:
var myName;
Mas você também pode declarar uma variável string assim:
var myName = "your name";
"your name"
é chamado de string literal. Uma string literal, ou string, é uma série de 0 ou mais caracteres entre aspas simples ou duplas.
Quando as variáveis de JavaScript são declaradas, elas têm um valor inicial de undefined
. Se você fizer uma operação matemática em uma variável undefined
, seu resultado será NaN
, o que significa que ”Não é um número”. Se você concatenar uma string com uma variável undefined
, você receberá uma string com o valor undefined
.
Em JavaScript todas os nomes de variáveis e funções são sensíveis a caracteres maiúsculos e minúsculos. Isso significa que a capitalização importa.
MYVAR
não é o mesmo que MyVar
nem myvar
. É possível ter diversas variáveis distintas com o mesmo nome mas com capitalização diferente. É extremamente recomendado pelo bem da clareza, que você não use esse recurso da linguagem.
Melhores práticas
Escreva nomes de variáveis em JavaScript em camelCase. Em camelCase, nomes de variáveis com mais de uma palavra possuem a primeira palavra toda em minúscula e a primeira letra de cada palavra subsequente capitalizada.
Um dos maiores problemas ao declarar variáveis com a palavra-chave var
é que você pode sobrescrever facilmente declarações de variável:
var camper = "James";
var camper = "David";
console.log(camper);
No código acima, a variável camper
é originalmente declarada com o valor James
e então substituída pelo valor David
. O console, então, vai exibir a string David
.
Em uma aplicação pequena, você pode não encontrar esse tipo de problema. Mas à medida que sua base de código se tornar maior, você pode sobrescrever acidentalmente uma variável que você não pretendia. Como esse comportamento não lança um erro, a busca e correção de bugs tornam-se mais difíceis.
Uma palavra-chave chamada let
foi introduzida na ES6, uma grande atualização para o JavaScript, para resolver este possível problema com a palavra-chave var
. Você vai aprender sobre outros recursos da ES6 em desafios posteriores.
Se você substituir var
por let
no código acima, ele resultará em um erro:
let camper = "James";
let camper = "David";
O erro pode ser visto no console do seu navegador.
Então, diferente de var
, ao usar let
, uma variável com o mesmo nome só pode ser declarada uma única vez.
A palavra-chave let
não é a única nova forma de declarar variáveis. Na versão ES6, você também pode declarar variáveis usando a palavra-chave const
.
const
possui todos os recursos maravilhosos que let
tem, com o bônus adicional que variáveis declaradas usando const
são somente de leitura. Elas têm um valor constante, o que significa que a variável atribuída com const
não pode ser atribuída novamente:
const FAV_PET = "Cats";
FAV_PET = "Dogs";
O console vai exibir um erro devido à reatribuição do valor de FAV_PET
.
Você sempre deve nomear variáveis que você não quer reatribuir, usando a palavra-chave const
. Isso ajuda quando você acidentalmente tenta reatribuir uma variável que deveria ser constante.
Observação: é comum que os desenvolvedores usem nomes de variáveis maiúsculas para valores imutáveis e minúsculas ou camelCase para valores mutáveis (objetos e arrays). Você aprenderá mais sobre objetos, arrays e valores imutáveis e mutáveis em desafios futuros. Em desafios posteriores, você também verá exemplos de identificadores de variáveis maiúsculas, minúsculas ou em camelCase.
Number
é um tipo de dado em JavaScript que representa um dado numérico.
Agora, vamos tentar adicionar dois números usando JavaScript.
JavaScript utiliza o símbolo +
como um operador de adição quando colocado entre dois números.
Exemplo:
const myVar = 5 + 10;
myVar
agora tem o valor de 15
.
Nós também podemos subtrair um número de outro.
JavaScript usa o símbolo -
para subtração.
Exemplo
const myVar = 12 - 6;
myVar
teria o valor 6
.
Nós também podemos multiplicar um número por outro.
JavaScript usa o símbolo *
para multiplicação de dois números.
Exemplo
const myVar = 13 * 13;
myVar
teria o valor 169
.
Nós também podemos dividir um número por outro.
JavaScript usa o símbolo /
para divisão.
Exemplo
const myVar = 16 / 2;
myVar
agora possui o valor 8
.
Você pode facilmente incrementar ou adicionar 1 à variável com o operador ++
.
i++;
é o equivalente a
i = i + 1;
Observação: a linha inteira torna-se i++;
, eliminando a necessidade para o sinal de igual (atribuição).
Você pode facilmente decrementar ou diminuir uma variável por um com o operador --
.
i--;
é o equivalente a
i = i - 1;
Observação: a linha inteira torna-se i--;
, eliminando a necessidade para o sinal de igual (atribuição).
Nós também podemos armazenar números decimais em variáveis. Números decimais são às vezes referidos como números de ponto flutuante ou floats.
Em JavaScript, você também pode realizar cálculos com números decimais, assim como com números inteiros.
O operador de resto %
retorna o resto da divisão de dois números.
Exemplo
5 % 2 = 1 porque
Math.floor(5 / 2) = 2 (Quociente)
2 * 2 = 4
5 - 4 = 1 (Resto)
Uso
Na matemática, um número pode ser verificado como par ou ímpar por meio do resto da divisão do número por 2
.
17 % 2 = 1 (17 é Ímpar)
48 % 2 = 0 (48 é Par)
Observação: o operador de resto às vezes é referido incorretamente como o operador de módulo. É muito semelhante ao módulo, mas não funciona adequadamente com números negativos.
Na programação, é comum usar atribuições para modificar o conteúdo de uma variável. Lembre-se de que tudo à direita do sinal de igual é avaliado primeiro, para que possamos dizer:
myVar = myVar + 5;
para adicionar 5
a myVar
. Como este é um padrão tão comum, existem operadores que realizam uma operação matemática e atribuição em um passo.
Um desses operadores é o operador +=
.
let myVar = 1;
myVar += 5;
console.log(myVar);
6
seria exibido no console.
Como o operador +=
, -=
subtrai um número de uma variável.
myVar = myVar - 5;
vai subtrair 5
de myVar
. Essa expressão pode ser reescrita assim:
myVar -= 5;
O operador *=
multiplica uma variável por um número.
myVar = myVar * 5;
multiplicará myVar
por 5
. Essa expressão pode ser reescrita assim:
myVar *= 5;
O operador /=
divide uma variável por outro número.
myVar = myVar / 5;
dividirá myVar
por 5
. Essa expressão pode ser reescrita assim:
myVar /= 5;
Quando você estiver definindo uma sequência de caracteres você deve iniciar e terminar com uma aspa simples ou dupla. O que acontece quando você precisa de uma aspa literal: "
ou '
dentro de sua string?
Em JavaScript, você pode escapar uma aspa para que não seja considerada como o fim de uma string ao colocar a barra invertida (\
) na frente da aspa.
const sampleStr = "Alan said, \"Peter is learning JavaScript\".";
Isso sinaliza ao JavaScript que a aspa seguinte não é o fim de uma string, mas que deve aparecer dentro da string. Então, se você fosse imprimir isso no console, você obteria:
Alan said, "Peter is learning JavaScript".
Valores de string em JavaScript podem ser escritas com aspas simples ou duplas, desde que você comece e termine com o mesmo tipo de aspas. Diferente de outras linguagens de programação, aspas simples e duplas funcionam da mesma forma em JavaScript.
const doubleQuoteStr = "This is a string";
const singleQuoteStr = 'This is also a string';
O motivo pelo qual você pode querer usar um tipo de aspas no lugar da outra é se você vir a querer usar ambas em uma string. Isso pode acontecer se você quiser salvar uma conversa em uma string e ter a conversa entre aspas. Outro uso para isso seria salvar uma tag <a>
com vários atributos em aspas, tudo dentro de uma string.
const conversation = 'Finn exclaims to Jake, "Algebraic!"';
Porém, isso se torna um problema se você precisar usar as aspas mais extremas dentro dela. Lembre-se, uma string tem o mesmo tipo de aspas no início e no final. Mas se você tem aquela mesma aspa em algum lugar no meio, a string vai terminar mais cedo e lançará um erro.
const goodStr = 'Jake asks Finn, "Hey, let\'s go on an adventure?"';
const badStr = 'Finn responds, "Let's go!"';
Aqui badStr
lançará um erro.
Na string goodStr acima, você pode usar ambas as aspas com segurança ao usar a barra invertida \
como um caractere de escapamento.
Observação: a barra invertida \
não deve ser confundida com a barra comum /
. Elas não fazem a mesma coisa.
Aspas não são os únicos caracteres que podem ser escapados dentro de uma string. Há dois motivos para usar caracteres de escapamento:
Aprendemos isso no desafio anterior.
Código | Saída |
---|---|
\' |
aspas simples |
\" |
aspas duplas |
\\ |
barra invertida |
\n |
nova linha |
\r |
retorno de carro |
\t |
tab |
\b |
limite de palavra |
\f |
quebra de página |
Note que a própria barra invertida deve ser escapada para ser exibida como uma barra invertida.
Em JavaScript, quando o operador +
é usado com um valor de String
, ele é chamado de operador de concatenação. Você pode criar uma nova string a partir de outras strings ao concatenar elas juntos.
Exemplo
'My name is Alan,' + ' I concatenate.'
Observação: cuidado com os espaços. A concatenação não adiciona espaços entre strings concatenadas, então você mesmo precisará adicioná-las.
Exemplo:
const ourStr = "I come first. " + "I come second.";
A string I come first. I come second.
seria exibida no console.
Também podemos usar o operador +=
para concatenar uma string no final de uma variável string existente. Isso pode ser muito útil para quebrar uma longa string em várias linhas.
Observação: cuidado com os espaços. A concatenação não adiciona espaços entre strings concatenadas, então você mesmo precisará adicioná-los.
Exemplo:
let ourStr = "I come first. ";
ourStr += "I come second.";
ourStr
agora deve ter como valor a string I come first. I come second.
.
Às vezes, você precisará criar uma string. Usando o operador de concatenação (+
), você pode inserir uma ou mais variáveis em uma string que você está criando.
Exemplo:
const ourName = "freeCodeCamp";
const ourStr = "Hello, our name is " + ourName + ", how are you?";
ourStr
teria o valor da string Hello, our name is freeCodeCamp, how are you?
.
Assim como podemos construir uma string em várias linhas através das strings literais, nós também podemos adicionar as variáveis para a string usando o operador mais igual (+=
).
Exemplo:
const anAdjective = "awesome!";
let ourStr = "freeCodeCamp is ";
ourStr += anAdjective;
ourStr
teria o valor freeCodeCamp is awesome!
.
Você pode encontrar o tamanho de um valor de String
ao escrever .length
após a variável de string ou literal de string.
console.log("Alan Peter".length);
O valor 10
seria exibido no console. Observe que o caractere de espaço entre “Alan” e “Peter” também é contado.
Por exemplo, se nós criássemos uma variável const firstName = "Ada"
, poderíamos descobrir qual o tamanho da string Ada
usando a propriedade firstName.length
.
Notação de colchetes é uma forma de pegar um caractere no índice especificado dentro de uma string.
A maioria das linguagens de programação modernas, como JavaScript, não começa contando do 1 como humanos fazem. Elas começam no 0. Isso é referido como indexação baseada em zero.
Por exemplo, o caractere no índice 0 da palavra Charles
é C
. Então, se const firstName = "Charles"
, você pode pegar o valor da primeira letra da string usando firstName[0]
.
Exemplo:
const firstName = "Charles";
const firstLetter = firstName[0];
firstLetter
teria o valor da string C
.
Em JavaScript, valores String
são imutáveis, o que significa que elas não podem ser alteradas após serem criadas.
Por exemplo, o código a seguir produzirá um erro porque a letra B
na cadeia de caracteres Bob
não pode ser alterada para a letra J
:
let myStr = "Bob";
myStr[0] = "J";
Observe que isso não significa que myStr
não possa ser reatribuída. A única forma de alterar myStr
seria atribuindo a ela um novo valor, deste modo:
let myStr = "Bob";
myStr = "Job";
ocê também pode usar notação de colchetes para pegar caracteres em outras posições em uma string.
Lembre-se de que computadores começam contando do 0
. Então, o primeiro caractere é na verdade o caractere na posição 0.
Exemplo:
const firstName = "Ada";
const secondLetterOfFirstName = firstName[1];
secondLetterOfFirstName
teria o valor da string d
.
Para pegar a última letra de uma string, você pode subtrair um do tamanho da string.
Por exemplo, se const firstName = "Ada"
, você pode pegar o valor da última letra da string ao usar firstName[firstName.length - 1]
.
Exemplo:
const firstName = "Ada";
const lastLetter = firstName[firstName.length - 1];
lastLetter
teria o valor da string a
.
Você pode usar o mesmo princípio que nós acabamos de usar para recuperar o último caractere em uma string, para recuperar o enésimo caractere antes do último caractere.
Por exemplo, você pode pegar o valor da antepenúltima letra da string const firstName = "Augusta"
usando firstName[firstName.length - 3]
Exemplo:
const firstName = "Augusta";
const thirdToLastLetter = firstName[firstName.length - 3];
thirdToLastLetter
teria o valor da string s
.
Você recebe frases com algumas palavras faltando, como substantivos, verbos, adjetivos e advérbios. Você então preencherá os pedaços faltantes com palavras de sua escolha de modo que a frase completa faça sentido.
Considere a frase - Era realmente ____ e nós ____ nós mesmos ____. Essa frase possui três pedaços faltando - um adjetivo, um verbo e um advérbio, e nós podemos adicionar palavras de nossa escolha para completar. Em seguida, podemos atribuir a frase completa para uma variável como se segue:
const sentence = "It was really " + "hot" + ", and we " + "laughed" + " ourselves " + "silly" + ".";
Com as variáveis de array
em JavaScript, podemos armazenar diversos dados em um único lugar.
Você começa uma declaração de um array com a abertura de um colchetes, terminando com o fechamento do colchetes e colocando vírgulas entre cada entrada, dessa forma:
const sandwich = ["peanut butter", "jelly", "bread"];
Você também pode aninhar arrays dentro de outros arrays, como abaixo:
const teams = [["Bulls", 23], ["White Sox", 45]];
Isso é chamado um array multidimensional.
Podemos acessar os dados dentro de arrays usando indexes.
Os índices de um array são escritos na mesma notação com colchetes que as strings usam. Porém, em vez de especificar um caractere, eles estão especificando um item do array. Assim como ocorre com as strings, os arrays usam indexação de base zero, de forma que o primeiro elemento de um array possui índice 0
.
Exemplo
const array = [50, 60, 70];
console.log(array[0]);
const data = array[1];
O console.log(array[0])
exibirá 50
e data
terá o valor de 60
.
Ao contrário das strings, as entradas de arrays são mutáveis e podem ser alteradas livremente, mesmo se o array foi declarado com const
.
Exemplo
const ourArray = [50, 40, 30];
ourArray[0] = 15;
ourArray
agora tem o valor [15, 40, 30]
.
Observação: não deve haver espaços entre o nome do array e os colchetes, como array [0]
. Embora JavaScript seja capaz de processar isso corretamente, isso pode confundir outros programadores lendo seu código.
Uma maneira de pensar em um array multidimensional é como um array de arrays. Quando você usa colchetes para acessar seu array, o primeiro conjunto de colchetes se refere às entradas no array mais exterior (o primeiro nível), e cada par adicional de colchetes refere-se ao próximo nível de entradas interno.
Exemplo
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[[10, 11, 12], 13, 14]
];
const subarray = arr[3];
const nestedSubarray = arr[3][0];
const element = arr[3][0][1];
Neste exemplo, subarray
tem o valor de [[10, 11, 12], 13, 14]
, nestedSubarray
tem o valor de [10, 11, 12]
e element
tem o valor de 11
.
Observação: não deve haver nenhum espaço entre o nome do array e os colchetes como array [0][0]
e até mesmo array [0] [0]
não é permitido. Embora JavaScript seja capaz de processar isso corretamente, isso pode confundir outros programadores lendo seu código.
Uma forma fácil de adicionar dados no final de um array é através da função push()
.
.push()
recebe um ou mais parâmetros e “empurra” eles no final do array.
Exemplos:
const arr1 = [1, 2, 3];
arr1.push(4);
const arr2 = ["Stimpson", "J", "cat"];
arr2.push(["happy", "joy"]);
arr1
agora tem o valor de [1, 2, 3, 4]
e arr2
tem o valor de ["Stimpson", "J", "cat", ["happy", "joy"]]
.
Outra forma de alterar os dados em um array é com a função .pop()
.
.pop()
é usado para remover um valor do final do array. Nós podemos armazenar esse valor removido atribuindo-o a uma variável. Em outras palavras, .pop()
remove o último elemento de um array e retorna aquele elemento.
Qualquer tipo de entrada pode ser removida de um array - numbers, strings e até mesmo arrays aninhados.
const threeArr = [1, 4, 6];
const oneDown = threeArr.pop();
console.log(oneDown);
console.log(threeArr);
O primeiro console.log
exibirá o valor 6
e o segundo exibirá o valor [1, 4]
.
pop()
sempre remove o último elemento de um array. E se você quiser remover o primeiro?
É aí que o .shift()
vem a ser útil. Ele funciona da mesma forma que .pop()
, exceto que ele remove o primeiro elemento ao invés do último.
Exemplo:
const ourArray = ["Stimpson", "J", ["cat"]];
const removedFromOurArray = ourArray.shift();
removedFromOurArray
teria o valor da string Stimpson
e ourArray
teria o valor de ["J", ["cat"]]
.
Você pode não apenas usar shift
para remover elementos do início de um array, como também pode usar unshift
para adicionar elementos ao início de um array, ou seja, adicionar elementos na posição inicial do array.
.unshift()
funciona exatamente como .push()
, mas, ao invés de adicionar o elemento ao final do array, unshift()
adiciona o elemento no início do array.
Exemplo:
const ourArray = ["Stimpson", "J", "cat"];
ourArray.shift();
ourArray.unshift("Happy");
Após o shift
, ourArray
teria o valor ["J","cat"]
. Após o unshift
, ourArray
teria o valor ["Happy","J","cat"]
.
Em JavaScript, nós podemos dividir nosso código em partes reutilizáveis chamadas de funções.
Aqui está um exemplo de uma função:
function functionName() {
console.log("Hello World");
}
Você pode chamar ou invocar essa função ao usar seu nome seguido de parênteses, da seguinte forma: functionName();
Cada vez que a função é chamada, imprimirá no console a mensagem Hello World
. Todo o código entre as chaves será executado toda vez que uma função for chamada.
Parâmetros são variáveis que atuam como espaços reservados para os valores que são passados para uma função, quando ela é chamada. Quando uma função é definida, normalmente ela é definida junto com um ou mais parâmetros. Os valores reais que são entradas de (ou ”passadas” para) uma função quando ela é chamada são conhecidos como argumentos.
Aqui está uma função com dois parâmetros, param1
e param2
:
function testFun(param1, param2) {
console.log(param1, param2);
}
Então podemos chamar o testFun
dessa forma: testFun("Hello", "World");
. Passamos dois argumentos do tipo string, Hello
e World
. Dentro da função, param1
será igual à string Hello
e param2
será igual à string World
. Note que você poderia chamar o testFun
novamente com diferentes argumentos e os parâmetros assumiriam o valor dos novos argumentos.
Nós podemos passar valores para uma função com argumentos. Você pode usar uma instrução return
para enviar um valor para fora de uma função.
Exemplo
function plusThree(num) {
return num + 3;
}
const answer = plusThree(5);
answer
tem o valor de 8
.
plusThree
recebe um argumento para num
e retorna um valor igual a num + 3
.
Em JavaScript, escopo refere-se à visibilidade de variáveis. Variáveis que são definidas fora de um bloco de função tem o escopo Global. Isso significa que elas podem ser vistas em qualquer lugar no seu código JavaScript.
Variáveis que são declaradas sem a palavra-chave let
ou const
são automaticamente criadas no escopo global
. Isso pode criar consequências indesejadas em outro lugar no seu código ou quando executar uma função novamente. Você sempre deve declarar suas variáveis com let
ou const
.
Variáveis que são declaradas dentro de uma função, assim como parâmetros das funções, possuem escopo local. Isso significa que elas são visíveis apenas dentro da função.
Aqui está uma função myTest
com uma variável local chamada loc
.
function myTest() {
const loc = "foo";
console.log(loc);
}
myTest();
console.log(loc);
A chamada da função myTest()
vai exibir a string foo
no console. A linha console.log(loc)
(fora da função myTest
) vai lançar um erro, já que loc
não foi definido fora da função.
É possível ter as variáveis local e global com o mesmo nome. Quando você faz isso, a variável local tem precedência sobre a variável global.
Neste exemplo:
const someVar = "Hat";
function myFun() {
const someVar = "Head";
return someVar;
}
A função myFun
retornará a string Head
porque a versão local da variável está presente.
Uma função pode incluir a instrução return
mas ela não precisa fazer isso. No caso de a função não ter uma instrução return
, quando você a chamar, a função processa o código interno, mas o valor retornado é undefined
.
Exemplo
let sum = 0;
function addSum(num) {
sum = sum + num;
}
addSum(3);
addSum
é uma função sem uma instrução return
. A função vai alterar a variável global sum
, mas o valor retornado da função é undefined
.
Se você se lembrar de nossa discussão sobre como armazenar valores com o operador de atribuição, tudo à direita do sinal de igual é resolvido antes de o valor ser atribuído. Isso significa que podemos pegar o valor de retorno de uma função e atribuí-lo a uma variável.
Assuma que temos uma função predefinida chamada sum
, que soma dois números. Então:
ourSum = sum(5, 12);
chamará a função sum
, a qual retorna o valor 17
e então atribui este valor à variável ourSum
.
Na Ciência da Computação, uma fila é uma estrutura de dados abstrata onde itens são mantidos em ordem. Novos itens podem ser adicionados no final da fila e itens mais antigos são removidos do início da fila.
Outro tipo de dado é o booleano. Booleanos podem ser apenas dois valores: true
ou false
. Eles basicamente são interruptores pequenos, onde true
é ligado e false
é desligado. Esses dois estados são mutuamente exclusivos.
Observação: valores booleanos nunca são escritos com aspas. As strings "true"
e "false"
não são booleanos e não tem nenhum significado especial em JavaScript.
instruções if
são usadas para tomar decisões no código. A palavra-chave if
diz ao JavaScript para executar o código nas chaves sob certas condições, definidas nos parênteses. Essas condições são conhecidas como condições Boolean
e elas só podem ser true
ou false
.
Quando a condição for true
, o programa executará as instruções dentro das chaves. Quando a condição booleana for false
, as instruções dentro das chaves não serão executadas.
Pseudocódigo
if (condição é verdadeira) {
instrução é executada
}
Exemplo
function test (myCondition) {
if (myCondition) {
return "It was true";
}
return "It was false";
}
test(true);
test(false);
test(true)
retorna a string It was true
e test(false)
retorna a string It was false
.
Quando test
é chamado com o valor true
, a instrução if
avalia myCondition
para verificar se é true
ou não. Já que é true
, a função retorna It was true
. Quando chamamos test
com um valor de false
, myCondition
não é true
, a instrução nas chaves não é executada e a função retorna It was false
.
Há muitos operadores de comparação em JavaScript. Todos esses operadores retornam um valor booleano true
ou false
.
O operador mais básico é o operador de igualdade ==
. O operador de igualdade compara dois valores e retorna true
se eles são equivalentes ou false
se não são. Observe que o operador de igualdade é diferente do operador de atribuição (=
), que atribui o valor à direita do operador para uma variável à esquerda.
function equalityTest(myVal) {
if (myVal == 10) {
return "Equal";
}
return "Not Equal";
}
Se myVal
é igual a 10
, o operador de igualdade retorna true
, assim o código nas chaves será executado e a função retornará Equal
. Caso contrário, a função retornará Not Equal
. Para que o JavaScript possa comparar dois tipos de dados diferentes (por exemplo, numbers
e strings
), deve converter um tipo para outro. Isto é conhecido como coerção de tipo (casting ou type coercion). No entanto, uma vez que a faça, você pode comparar os termos da seguinte forma:
1 == 1 // true
1 == 2 // false
1 == '1' // true
"3" == 3 // true
Igualdade estrita (===
) é a contrapartida do operador de igualdade (==
). No entanto, ao contrário do operador de igualdade, que tenta converter ambos os valores em comparação a um tipo comum, o operador estrito de igualdade não realiza uma conversão de tipo.
Se os valores que são comparados tiverem valores diferentes, são considerados desiguais, e o operador de igualdade estrito retornará falso.
Exemplos
3 === 3 // true
3 === '3' // false
No segundo exemplo, 3
é um tipo de Number
e '3'
é um tipo String
.
Nos últimos dois desafios, aprendemos sobre o operador de igualdade (==
) e o operador de igualdade estrita (===
). Vamos fazer uma breve revisão e praticar usando esses operadores mais uma vez.
Se os valores sendo comparados não são do mesmo tipo, o operador de igualdade fará a conversão de tipo e, então, avaliará os valores. No entanto, o operador de igualdade estrita vai comparar ambos os tipos de dados e os valores, sem converter de um tipo para outro.
Exemplos
3 == '3'
retorna true
porque JavaScript faz a conversão de tipo de string para número. 3 === '3'
retorna false
porque os tipos são diferentes e não é feita a conversão de tipo.
Observação: em JavaScript, você pode determinar o tipo de uma variável ou de um valor, com o operador typeof
, como vemos a seguir:
typeof 3
typeof '3'
typeof 3
retorna a string number
e typeof '3'
retorna a string string
.
O operador de desigualdade (!=
) é o oposto do operador de igualdade. Significa que não é igual e retorna false
onde a igualdade retornaria true
e vice-versa. Tal como o operador de igualdade, o operador de desigualdade converterá os tipos de dados de valores enquanto compara.
Exemplos
1 != 2 // true
1 != "1" // false
1 != '1' // false
1 != true // false
0 != false // false
O operador de desigualdade estrito (!==
) é o oposto lógico do operador de igualdade estrito. Significa que “não é estritamente igual” e retorna false
onde a igualdade estrita retornaria true
e vice-versa. O operador de desigualdade estrita não converterá tipos de dados.
Exemplos
3 !== 3 // false
3 !== '3' // true
4 !== 3 // true
O operador maior que (>
) compara os valores de dois números. Se o número à esquerda for maior que o número à direita, ele retorna true
. Caso contrário, ele retorna false
.
Tal como o operador de igualdade, o operador maior que converterá os tipos de dados de valores enquanto compara.
Exemplos
5 > 3 // true
7 > '3' // true
2 > 3 // false
'1' > 9 // false
O operador maior ou igual que (>=
) compara os valores de dois números. Se o número à esquerda é maior ou igual ao número à direita, ele retorna true
. Caso contrário, ele retornará false
.
Tal como o operador de igualdade, o operador maior que converterá os tipos de dados de valores enquanto compara.
Exemplos
6 >= 6 // true
7 >= '3' // true
2 >= 3 // false
'7' >= 9 // false
O operador menor que (<
) compara os valores de dois números. Se o número à esquerda for menos que o número à direita, retornará true
. Caso contrário, retorna false
. Assim como o operador de igualdade, o operador menor que converte os tipos de dados enquanto compara.
Exemplos
2 < 5 // true
'3' < 7 // true
5 < 5 // false
3 < 2 // false
'8' < 4 // false
O operador menor ou igual (<=
) compara os valores de dois números. Se o número à esquerda for menor ou igual ao número à direita, retornará true
. Se o número à esquerda for maior que o número a direita, retornará false
. Assim como o operador de igualdade, o operador de menor ou igual que converte os tipos de dados.
Exemplos
4 <= 5 // true
'7' <= 7 // true
5 <= 5 // true
3 <= 2 // false
'8' <= 4 // false
Às vezes, você precisará testar mais de uma coisa de cada vez. O operador lógico AND (&&
) retornará true
apenas se os operadores à esquerda e à direita forem verdadeiros.
O mesmo efeito pode ser alcançado aninhando uma instrução if dentro de outro if:
if (num > 5) {
if (num < 10) {
return "Yes";
}
}
return "No";
só retornará Yes
se num
for maior que 5
e menor que 10
. A mesma lógica pode ser escrita assim:
if (num > 5 && num < 10) {
return "Yes";
}
return "No";
O operador lógico OR (||
) retorna true
se qualquer um dos operandos for true
. Caso contrário, retorna false
.
O operador lógico ou é composto por dois símbolos de pipe: (||
). Normalmente, ele pode ser encontrado entre as teclas Backspace e Enter.
O padrão abaixo deve parecer familiar aos pontos das passagens anteriores:
if (num > 10) {
return "No";
}
if (num < 5) {
return "No";
}
return "Yes";
retornará Yes
apenas se num
for entre 5
e 10
(5 e 10 incluídos). A mesma lógica pode ser escrita assim:
if (num > 10 || num < 5) {
return "No";
}
return "Yes";
Quando uma condição para uma instrução if
for verdadeira, o bloco de código seguinte será executado. E quando a condição for falsa? Normalmente, nada aconteceria. Com uma instrução else
, um bloco de código alternativo pode ser executado.
if (num > 10) {
return "Bigger than 10";
} else {
return "10 or Less";
}
Se você tem múltiplas condições que precisam ser resolvidas, você pode encadear as instruções if
junto com instruções else if
.
if (num > 15) {
return "Bigger than 15";
} else if (num < 5) {
return "Smaller than 5";
} else {
return "Between 5 and 15";
}
A ordem é importante em instruções if
e else if
.
A função é executada de cima para baixo, então você deve ser cuidadoso com qual instrução vem primeiro.
Tomemos como exemplo estas duas funções.
Aqui está a primeira:
function foo(x) {
if (x < 1) {
return "Less than one";
} else if (x < 2) {
return "Less than two";
} else {
return "Greater than or equal to two";
}
}
A segunda apenas altera a ordem das instruções if e else if:
function bar(x) {
if (x < 2) {
return "Less than two";
} else if (x < 1) {
return "Less than one";
} else {
return "Greater than or equal to two";
}
}
Embora as duas funções pareçam praticamente idênticas, se passarmos um número para ambas, teremos saídas diferentes.
foo(0)
bar(0)
foo(0)
retornará a string Less than one
e bar(0)
retornará a string Less than two
.
Instruções if/else
podem ser encadeadas por uma lógica complexa. Aqui está o pseudocódigo de várias instruções encadeadas if
/else if
:
if (condition1) {
statement1
} else if (condition2) {
statement2
} else if (condition3) {
statement3
. . .
} else {
statementN
}
Se você possui muitas opções pra escolher, use uma instrução switch. Uma instrução switch
testa um valor e pode ter muitas instruções case as quais definem os diversos valores possíveis. As instruções são executadas desde o primeiro case
correspondente até que seja encontrado um break
.
Aqui está um exemplo de uma instrução switch
:
switch (lowercaseLetter) {
case "a":
console.log("A");
break;
case "b":
console.log("B");
break;
}
Valores case
são testados com o operador de igualdade estrita (===
). O break
diz ao JavaScript parar interromper a execução das instruções. Se o break
for omitido, a próxima instrução case será executada.
Na instrução switch
, você não deve ser capaz de especificar todos os possíveis valores como instruções case
. Ao invés disso, você pode adicionar a instrução default
, que será executada se nenhuma instrução case
correspondente for encontrada. Pense nisso como a instrução final else
em uma cadeia de if/else
.
A instrução default
deve ser o último caso.
switch (num) {
case value1:
statement1;
break;
case value2:
statement2;
break;
...
default:
defaultStatement;
break;
}
Se a instrução break
for omitida de uma instrução case
de um switch
, as instruções case
seguintes serão executadas até que seja encontrado um break
. Se você tem várias entradas com a mesma saída, você pode representá-las em uma instrução switch
da seguinte forma:
let result = "";
switch (val) {
case 1:
case 2:
case 3:
result = "1, 2, or 3";
break;
case 4:
result = "4 alone";
}
Todos os casos para 1, 2 e 3 vão produzir o mesmo resultado.
Se você tiver muitas opções para escolher, uma instrução switch
pode ser mais fácil de escrever do que muitas instruções if
/else if
encadeadas. O seguinte:
if (val === 1) {
answer = "a";
} else if (val === 2) {
answer = "b";
} else {
answer = "c";
}
pode ser substituído por:
switch (val) {
case 1:
answer = "a";
break;
case 2:
answer = "b";
break;
default:
answer = "c";
}
Você pode se lembrar de Comparação com o operador de igualdade, em que todos os operadores de comparação retornam um valor booleano true
ou false
.
Às vezes, as pessoas usam uma instrução if/else
para fazer uma comparação, dessa forma:
function isEqual(a, b) {
if (a === b) {
return true;
} else {
return false;
}
}
Mas há uma forma melhor de fazer isso. Já que ===
retorna true
ou false
, podemos retornar o resultado da comparação:
function isEqual(a, b) {
return a === b;
}
Quando uma instrução return
é alcançada, a execução da função atual para e retorna o código para o local da chamada da função.
Exemplo
function myFun() {
console.log("Hello");
return "World";
console.log("byebye")
}
myFun();
O código acima exibirá no console a string Hello
, e retorna a string World
. A string byebye
nunca vai ser exibida no console, porque a função termina na instrução return
.
Você talvez tenha ouvido o termo objeto
antes.
Objetos são similares a arrays
, exceto que, ao invés de usar índices para acessar e modificar seus dados, você acessa os dados em objetos através do que se chama propriedades
.
Objetos são úteis para armazenar dados de forma estruturada e podem representar objetos do mundo real, como um gato.
Aqui está um exemplo de objeto gato:
const cat = {
"name": "Whiskers",
"legs": 4,
"tails": 1,
"enemies": ["Water", "Dogs"]
};
Neste exemplo, todas as propriedades são armazenadas como strings, como name
, legs
e tails
. Porém, você também pode usar números como propriedades. Você pode até omitir as aspas para propriedades de string com uma única palavra, da seguinte forma:
const anotherObject = {
make: "Ford",
5: "five",
"model": "focus"
};
No entanto, se seu objeto tem quaisquer propriedades que não sejam strings, o JavaScript automaticamente definirá seus tipos como strings.
Existem duas formas para acessar as propriedades de um objeto: notação de ponto (.
) e notação de colchetes ([]
), de forma similar a um array.
Notação de ponto é o que você utiliza quando você sabe o nome da propriedade que você está tentando acessar antecipadamente.
Aqui está um exemplo usando notação de ponto (.
) para ler uma propriedade do objeto:
const myObj = {
prop1: "val1",
prop2: "val2"
};
const prop1val = myObj.prop1;
const prop2val = myObj.prop2;
prop1val
teria o valor val1
e prop2val
teria o valor val2
.
A segunda forma para acessar as propriedades de um objeto é a notação de colchetes ([]
). Se a propriedade do objeto que você está tentando acessar possui um espaço no seu nome, você precisará usar a notação de colchetes.
No entanto, você ainda pode usar a notação de colchetes nas propriedades dos objetos sem espaços.
Aqui está um exemplo usando a notação de colchetes para ler uma propriedade de um objeto:
const myObj = {
"Space Name": "Kirk",
"More Space": "Spock",
"NoSpace": "USS Enterprise"
};
myObj["Space Name"];
myObj['More Space'];
myObj["NoSpace"];
myObj["Space Name"]
seria a string Kirk
, myObj['More Space']
seria a string Spock
e myObj["NoSpace"]
seria a string USS Enterprise
.
Note que os nomes das propriedades com espaços neles precisam estar entre aspas (simples ou duplas).
Outro uso de notação de colchetes em objetos é para acessar a propriedade a qual está armazenada como o valor de uma variável. Isso pode ser muito útil para iterar através das propriedades de um objeto ou quando acessando uma tabela de pesquisa.
Aqui está um exemplo de usar uma variável para acessar uma propriedade:
const dogs = {
Fido: "Mutt",
Hunter: "Doberman",
Snoopie: "Beagle"
};
const myDog = "Hunter";
const myBreed = dogs[myDog];
console.log(myBreed);
A string Doberman
seria exibida no console.
Observe que não usamos aspas em torno do nome da variável ao usá-la para acessar a propriedade, porque estamos usando o valor da variável, e não o nome.
Depois de criar um objeto JavaScript, você pode atualizar suas propriedades a qualquer momento, como você atualizaria qualquer outra variável. Você pode usar notação de ponto ou colchete para atualizar.
Por exemplo, vamos dar uma olhada em ourDog
:
const ourDog = {
"name": "Camper",
"legs": 4,
"tails": 1,
"friends": ["everything!"]
};
Como ele é um cachorro particularmente feliz, vamos mudar seu nome para o texto Happy Camper
. Veja como atualizamos a propriedade name do objeto: ourDog.name = "Happy Camper";
ou ourDog["name"] = "Happy Camper";
Agora, quando avaliamos ourDog.name
, em vez de obter Camper
, teremos seu novo nome, Happy Camper
.
Você pode adicionar novas propriedades para um objeto JavaScript existente da mesma forma pela qual você os modificaria.
Aqui está como adicionaríamos uma propriedade bark
para ourDog
:
ourDog.bark = "bow-wow";
ou
ourDog["bark"] = "bow-wow";
Agora, quando acessamos ourDog.bark
, nós teremos o seu latido, bow-wow
.
Exemplo:
const ourDog = {
"name": "Camper",
"legs": 4,
"tails": 1,
"friends": ["everything!"]
};
ourDog.bark = "bow-wow";
Podemos também excluir propriedades de objetos dessa forma:
delete ourDog.bark;
Exemplo:
const ourDog = {
"name": "Camper",
"legs": 4,
"tails": 1,
"friends": ["everything!"],
"bark": "bow-wow"
};
delete ourDog.bark;
Após a última linha mostrada acima, ourDog
se parece com:
{
"name": "Camper",
"legs": 4,
"tails": 1,
"friends": ["everything!"]
}
Objetos podem ser pensados como armazenamento de chave/valor, como um dicionário. Se você tem um dado tabular, você pode usar um objeto para pesquisar valores ao invés de uma instrução switch
ou uma cadeia de if/else
. Isso é mais útil quando você sabe que o seu dado de entrada é limitado para um certo intervalo.
Aqui está um exemplo de uma simples pesquisa reversa no alfabeto:
const alpha = {
1:"Z",
2:"Y",
3:"X",
4:"W",
...
24:"C",
25:"B",
26:"A"
};
const thirdLetter = alpha[2];
const lastLetter = alpha[24];
const value = 2;
const valueLookup = alpha[value];
thirdLetter
é a string Y
, lastLetter
é a string C
e valueLookup
é a string Y
.
Às vezes, é útil verificar se a propriedade de um determinado objeto existe ou não. Podemos usar o método de objetos .hasOwnProperty(propname)
para determinar se aquele objeto possui o nome de propriedade fornecido. .hasOwnProperty()
retorna true
ou false
se a propriedade for encontrada ou não.
Exemplo
const myObj = {
top: "hat",
bottom: "pants"
};
myObj.hasOwnProperty("top");
myObj.hasOwnProperty("middle");
O primeiro hasOwnProperty
retorna true
, enquanto o segundo retorna false
.
Às vezes, você pode querer armazenar dados em uma Estrutura de Dados flexível. Um objeto JavaScript é uma forma de lidar com dados flexíveis. Eles permitem combinações arbitrárias de strings, numbers, booleans, arrays, functions e objects.
Aqui está um exemplo de estrutura de dados complexas:
const ourMusic = [
{
"artist": "Daft Punk",
"title": "Homework",
"release_year": 1997,
"formats": [
"CD",
"Cassette",
"LP"
],
"gold": true
}
];
Este é um array que contém um objeto dentro dele. O objeto possui vários pedaços de metadados sobre um álbum. Também possui um array aninhado formats
. Se você quiser adicionar mais álbuns, você pode fazer isso adicionando os discos ao array de alto nível. Objetos armazenam dados em uma propriedade, a qual possui um formato de chave-valor. No exemplo acima, "artist": "Daft Punk"
é uma propriedade que tem uma chave artist
e um valor de Daft Punk
.
Observação: você precisará colocar uma vírgula após cada objeto no array, a não ser que ele seja o último objeto no array.
As subpropriedades de objetos podem ser acessadas ao encadear a notação de ponto e de colchetes.
Aqui está um objeto aninhado:
const ourStorage = {
"desk": {
"drawer": "stapler"
},
"cabinet": {
"top drawer": {
"folder1": "a file",
"folder2": "secrets"
},
"bottom drawer": "soda"
}
};
ourStorage.cabinet["top drawer"].folder2;
ourStorage.desk.drawer;
ourStorage.cabinet["top drawer"].folder2
seria a string secrets
e ourStorage.desk.drawer
seria a string stapler
.
Como vimos em exemplos anteriores, objetos podem conter tanto objetos aninhados quanto arrays aninhados. Semelhante ao acesso de objetos aninhados, a notação de colchetes pode ser encadeada para se acessar arrays aninhados.
Aqui está um exemplo de como se acessar um array aninhado:
const ourPets = [
{
animalType: "cat",
names: [
"Meowzer",
"Fluffy",
"Kit-Cat"
]
},
{
animalType: "dog",
names: [
"Spot",
"Bowser",
"Frankie"
]
}
];
ourPets[0].names[1];
ourPets[1].names[0];
ourPets[0].names[1]
seria a string Fluffy
e ourPets[1].names[0]
seria a string Spot
.
Você pode rodar o mesmo código várias vezes usando um laço.
O primeiro tipo de laço que aprenderemos é chamado de laço while
porque ele rodará enquanto uma condição específica for verdadeira e vai parar uma vez que a condição não for mais verdadeira.
const ourArray = [];
let i = 0;
while (i < 5) {
ourArray.push(i);
i++;
}
No código de exemplo acima, o laço while
executará por 5 vezes e adicionará os números de 0 até 4 a ourArray
.
Vamos tentar fazer um laço while funcionar empurrando valores para um array.
Você pode rodar o mesmo código várias vezes usando um laço.
O tipo mais comum de laço JavaScript é chamado de laço for
, porque ele é executado por um número especificado de vezes.
Laços for são declarados com três expressões opcionais separadas por ponto e vírgula:
for (a; b; c)
, onde a
é a declaração de inicialização, b
é a declaração de condição, e c
é a expressão final.
A declaração de inicialização é executada apenas uma vez antes de o laço iniciar. Normalmente, é usada para definir e configurar sua variável de laço.
A declaração de condição é verificada no início de cada iteração do laço e vai continuar enquanto seu valor for true
. Quando a condição for false
no início da iteração, o laço vai parar de executar. Isso significa que se a condição de início for falsa, seu laço nunca será executado.
A expressão final é executada no final de cada iteração do laço, antes da verificação da próxima condição e normalmente é usada para incrementar ou decrementar o contador do laço.
No exemplo a seguir, inicializamos com i = 0
e iteramos enquanto nossa condição i < 5
for verdadeira. Nós incrementaremos i
em 1
em cada iteração do laço com i++
como nossa expressão final.
const ourArray = [];
for (let i = 0; i < 5; i++) {
ourArray.push(i);
}
ourArray
agora terá o valor de [0, 1, 2, 3, 4]
.
Laços for não tem de iterar um de cada vez. Ao alterar nossa final-expression
, nós podemos contar os números pares.
Começaremos em i = 0
e um laço while i < 10
. Incrementaremos i
em 2 a cada iteração com i += 2
.
const ourArray = [];
for (let i = 0; i < 10; i += 2) {
ourArray.push(i);
}
ourArray
agora conterá [0, 2, 4, 6, 8]
. Vamos mudar nossa initialization
para que possamos contar por números ímpares.
Um laço for também pode contar pra trás, contanto que possamos definir as condições certas.
Para decrementar em dois cada iteração, nós precisamos alterar nossa inicialização, condição e expressão final.
Nós começaremos em i = 10
e vamos iterar enquanto i > 0
. Nós decrementamos i
por dois em cada iteração com i -= 2
.
const ourArray = [];
for (let i = 10; i > 0; i -= 2) {
ourArray.push(i);
}
ourArray
agora vai conter [10, 8, 6, 4, 2]
. Vamos mudar nossa inicialização e expressão final para que possamos contar para trás em dois para criar um array de números ímpares decrescentes.
Uma tarefa comum em JavaScript é para iterar através do conteúdo de um array. Uma forma de fazer isso é com um laço for
. Esse código vai exibir cada elemento do array arr
no console:
const arr = [10, 9, 8, 7, 6];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
Lembre-se de que arrays têm indexação baseada em zero, o que significa que o último índice do array é de length - 1
. Nossa condição para esse laço é i < arr.length
, que interrompe o laço quando i
é igual a length
. Nesse caso a última iteração é i === 4
, ou seja, quando i
se tornar igual a arr.length - 1
e exibir 6
no console. Em seguida, i
aumenta para 5
, e o laço é interrompido porque i < arr.length
é false
.
Se você possui um array multidimensional, você pode usar a mesma lógica no ponto de passagem anterior para iterar através de arrays e de qualquer sub-array. Exemplo:
const arr = [
[1, 2], [3, 4], [5, 6]
];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
console.log(arr[i][j]);
}
}
Isso exibe no console cada subelemento dentro de arr
, um de cada vez. Note que para o laço interno, nós estamos verificando a propriedade .length
de arr[i]
, desde que arr[i]
também seja um array.
O próximo tipo de laço que você aprenderá é chamado de laço do...while
. O laço do...while
é chamado assim porque primeiro fará algo (do
) ou executará algo uma vez dentro do bloco de código, não importando o que acontecer. Em seguida, continuará a executar o laço enquanto (while
) a condição for true
.
const ourArray = [];
let i = 0;
do {
ourArray.push(i);
i++;
} while (i < 5);
O exemplo acima se comporta de forma similar a outros tipos de laços, e o array resultante se parecerá com [0, 1, 2, 3, 4]
. No entanto, o que torna o laço do...while
diferente de outros laços é como ele se comporta quando uma condição falha na primeira verificação. Vamos ver isso na prática. Aqui está um laço comum while
que rodará o código no laço enquanto i < 5
:
const ourArray = [];
let i = 5;
while (i < 5) {
ourArray.push(i);
i++;
}
Nesse exemplo, inicializamos o valor de ourArray
como um array vazio e o valor de i
sendo 5. Quando executamos o laço while
, a condição é igual a false
porque i
não é menor que 5, portanto nós não executamos o código dentro do laço. O resultado é que ourArray
terminará sem valores adicionados a ele, e ainda se parecerá com []
quando todas as linhas do código no exemplo acima forem completamente executadas. Agora, dê uma olhada no laço do...while
:
const ourArray = [];
let i = 5;
do {
ourArray.push(i);
i++;
} while (i < 5);
Nesse caso, nós inicializamos o valor de i
para 5, assim como fizemos com o laço while
. Quando chegamos na próxima linha, não há condição a ser analisada, então nós vamos ao código dentro das chaves e o executamos. Nós adicionaremos um único elemento ao array e então incrementamos i
antes de chegarmos à verificação da condição. Quando nós finalmente temos o resultado da condição i < 5
na última linha, nós notamos que i
agora é 6, o que não cumpre a verificação da condição, então nós saímos do laço e terminamos. Ao final do exemplo acima, o valor de ourArray
é [5]
. Essencialmente, um laço do...while
garante que o código dentro do laço será executado pelo menos uma vez. Vamos tentar fazer um laço do...while
funcionar inserindo valores em um array.
Recursão é o conceito de que uma função pode ser chamada por ela mesma. Para ajudar a entender isso, comece a pensar sobre a seguinte tarefa: multiplique os primeiros n
elementos de um array para criar o produto desses elementos. Usando um laço for
, você poderia fazer isso:
function multiply(arr, n) {
let product = 1;
for (let i = 0; i < n; i++) {
product *= arr[i];
}
return product;
}
No entanto, note que multiply(arr, n) == multiply(arr, n - 1) * arr[n - 1]
. Isso significa que você pode reescrever multiply
dentro da própria função e nunca precisar usar um laço.
function multiply(arr, n) {
if (n <= 0) {
return 1;
} else {
return multiply(arr, n - 1) * arr[n - 1];
}
}
A versão recursiva de multiply
fica dessa forma. No caso de base, onde n <= 0
, ele retorna 1. Para valores maiores de n
, a função chama a si mesma, mas com n - 1
. Essa chamada da função é avaliada da mesma forma, chamando multiply
novamente até que n <= 0
. Nesse ponto, todas as funções podem retornar e a função multiply
original retorna a resposta.
Observação: funções recursivas precisam ter um caso de base quando elas retornam sem chamar a função novamente (nesse exemplo, quando n <= 0
), caso contrário, elas nunca vão parar de executar.
Números aleatórios são úteis para criar comportamento aleatório.
JavaScript tem a função Math.random()
que gera um número decimal aleatório entre 0
(incluso) e 1
(excluso). Assim, Math.random()
pode retornar um 0
mas nunca retornará 1
.
Observação: como ao armazenar valores com operador de atribuição, todas as chamadas de funções serão resolvidas antes de executar o return
, para que possamos dar ao return
o valor da função Math.random()
.
É ótimo podermos gerar números decimais aleatórios, mas é ainda mais útil se usarmos isso para gerar números inteiros aleatórios.
Math.random()
para gerar um decimal aleatório.20
.Math.floor()
para arredondar o número para baixo para o número inteiro mais próximo.Lembre-se de que Math.random()
pode nunca retornar um 1
e, por estarmos arredondando, é impossível também receber 20
. Essa técnica nos dará um número inteiro entre 0
e 19
.
Juntando tudo, é assim que nosso código se parece:
Math.floor(Math.random() * 20);
Nós estamos chamando Math.random()
, multiplicando o resultado por 20, e em seguida passando o valor para a função Math.floor()
para arredondar o valor para o número inteiro mais próximo abaixo.
Ao invés de gerar um número inteiro aleatório entre 0 e um número especificado, como fizemos anteriormente, nós podemos gerar um número inteiro aleatório que fica em um intervalo entre dois números especificados.
Para isso, definiremos um número mínimo min
e um número máximomax
.
Aqui está a fórmula que usaremos. Leve um momento para ler e entender o que esse código está fazendo:
Math.floor(Math.random() * (max - min + 1)) + min
A função parseInt()
analisa uma string e retorna um inteiro. Exemplo:
const a = parseInt("007");
A função acima converte a string 007
para o inteiro 7
. Se o primeiro caractere na string não pode ser convertido em um número, então ele retorna NaN
.
A função parseInt()
analisa uma string e retorna um inteiro. É preciso um segundo argumento para o radix, que especifica a base do número na string. O radix pode ser um inteiro entre 2 e 36.
A chamada da função se parece com:
parseInt(string, radix);
Exemplo:
const a = parseInt("11", 2);
A variável radix diz que 11
está no sistema binário, ou base 2. Esse exemplo converte a string 11
para um inteiro 3
.
O operador condicional, também chamado de operador ternário, pode ser usado como uma expressão if-else de uma linha.
A sintaxe é a ? b : c
, onde a
é a condição, b
é o código executado quando a condição retorna true
e c
é o código executado quando a condição retorna false
.
A função a seguir usa a instrução if/else
para verificar uma condição:
function findGreater(a, b) {
if(a > b) {
return "a is greater";
}
else {
return "b is greater or equal";
}
}
Isto pode ser reescrito usando o operador condicional:
function findGreater(a, b) {
return a > b ? "a is greater" : "b is greater or equal";
}
No desafio anterior, você usou um único operador condicional. Você também pode encadear eles juntos para verificar por múltiplas condições.
A seguinte função usa as instruções if
, else if
e else
para verificar múltiplas condições:
function findGreaterOrEqual(a, b) {
if (a === b) {
return "a and b are equal";
}
else if (a > b) {
return "a is greater";
}
else {
return "b is greater";
}
}
A função acima pode ser rescrita usando operadores de múltiplas condições (operador ternário):
function findGreaterOrEqual(a, b) {
return (a === b) ? "a and b are equal"
: (a > b) ? "a is greater"
: "b is greater";
}
É considerada a melhor prática para formatar operadores de múltiplas condições, já que cada condição está em uma linha separada, como mostrado acima. Usar operadores de múltiplas condições sem a indentação adequada pode dificultar a leitura do seu código. Por exemplo:
function findGreaterOrEqual(a, b) {
return (a === b) ? "a and b are equal" : (a > b) ? "a is greater" : "b is greater";
}