O termo "Vanilla", traduzido como "baunilha", nada mais é do que um sarcasmo para o JavaScript puro. Ou seja, muitos podem achar que se trata de uma biblioteca, pacote, módulo ou framework, mas não...é o bom e velho JavaScript. E como estamos envolvendo o JavaScript puro, por que não utilizar esse branch pra se tratar do paradigma imperativo/ procedural da linguagem? Embora, ela ainda seja orientada a objetos e tudo dentro dela é considerado um objeto.
Como qualquer outra tarefa, a programação requer ferramentas e espaço de trabalho adequados. O desenvolvimento de software, na maioria dos casos, requer um editor de código e um compilador ou intérprete de uma determinada linguagem. Este é um conjunto mínimo, que podemos estender conforme necessário com várias outras ferramentas. No caso, estarei utilizando o Visual Studio Code, que possui muitas funcionalidade e extensões que facilitam o desenvolvimento em JavaScript.
Além do editor e interpretador de código JavaScript, podemos também utilizar o depurador, que é uma ferramenta que nos permite, entre outras coisas, pausar o programa no local indicado e analisar o seu estado atual (por exemplo, os valores das variáveis indicadas). É claro que as ferramentas em questão deverão ser executadas no computador. Nesta fase, o seu desempenho não é particularmente importante, e qualquer unidade que possa lidar com tarefas normais de escritório será suficiente, por isso é altamente recomendável trabalhar a partir de um computador desktop ou laptop. Não há como negar que o tamanho do monitor afetará o conforto do seu trabalho. Quanto maior o monitor, mais fácil será colocar o editor de código, o intérprete e outros conteúdos (por exemplo, este curso) próximos uns dos outros. Em circunstâncias normais de trabalho, os programadores costumam usar vários monitores.
O sistema operacional não importa, pois a ferramenta apropriada pode ser encontrada para Windows, macOS e Linux.
Neste momento, existem duas opções. Você pode instalar todas as ferramentas necessárias em sua máquina e trabalhar no ambiente local. Esta é a abordagem preferida, pois é assim que acontece em projetos comerciais reais na maioria das vezes. Você também pode personalizar tudo para atender às suas necessidades. Outra abordagem é usar ferramentas online. Eles podem ser convenientes, pois você não precisa instalar ou configurar nada – eles simplesmente funcionam. A maioria deles permite armazenar seu trabalho em uma nuvem para que você possa acessá-lo de diferentes dispositivos, mas por outro lado, carecem de opções de personalização e você precisa ter uma conexão constante com a Internet.
Todo o código que você verá neste curso foi testado em ambientes locais e online, portanto ambas as opções são válidas. Finalmente, podemos passar para a escolha das ferramentas.
Trabalhar com JavaScript é simples, não será necessário nenhuma ferramenta mirabolante ou difícil de conseguir. Basicamente iremos precisar de um editor de texto e de um navegador. Apesar de poder rodar JavaScript em outros locais, até mesmo no console, optaremos por utilizar o VSCode, por ser um ambiente onde a maioria dos desenvolvedores já está familiarizado, seja por utilizar outras linguagens ou simplesmente por abrir um localhost no navegar na web (preview), e também por ser ter muitas ferramento para o desenvolvimento JavaScript.
Dica: Caso já tenha familiaridade com editores de texto ou IDE’s mais robustas, sinta-se à vontade para utilizá-los, pois o JavaScript é independente do editor. Somente certifique-se de que o navegador utilizado lhe dará o devido suporte.
Primeiramente, crie um documento HTML, nomeie-o como “index.html”.
<html>
<head>
<meta charset="UTF-8">
<title>JavaScript</title>
</head>
<body>
</body>
</html>
Agora, existem duas maneiras de criar um documento JS:
No <body>
(corpo):
<body>
<script>
alert("Hello, World!");
</script>
</body>
No <head>
(cabeça):
<html>
<head>
<meta charset="UTF-8">
<script>
alert("Ola, Mundo!");
</script>
<title>JavaScript</title>
<script>
alert("Hello, World!");
</script>
</head>
O código JavaScript a ser executado pelo navegador na página deve ser anexado ao HTML usando a tag <script>
, e há duas maneiras de fazer isso. O código pode ser incorporado diretamente nas tags <script>
e </script>
, mas isso só é recomendado quando o código for curto. Outra abordagem é usar o atributo “src”
para apontar para um arquivo separado que contém o código JavaScript. Isto é especialmente verdade quando o mesmo código vai ser usado em várias páginas, porque repetir exatamente o mesmo código muitas vezes é uma má prática, pois qualquer alteração precisa ser aplicada a todos os arquivos; e além disso, aumenta artificialmente o tamanho da página. A extensão do arquivo JavaScript é .js.
O HTML é lido pelo navegador linha por linha, e as tags de script são executadas no momento em que o navegador analisa a tag <script>
(a análise de linguagens de programação significa uma análise formal do código por uma máquina para entender sua estrutura) . Normalmente as tags <script>
são inseridas no cabeçalho da página entre as tags <head>
e </head>
, e podemos inserir muitas delas em um arquivo, por exemplo, para incluir código JavaScript de diferentes arquivos. Este comportamento pode ser alterado para scripts externos apontados pelo atributo "src"
utilizando os atributos "defer"
ou "async"
.
-
defer
– significa que o script deve ser executado após o carregamento de toda a página; -
async
– significa que o script será executado imediatamente, mas paralelamente à análise do resto da página.
No arquivo:
Outra maneira válida é criar um documento com a extensão .js
, é separando ele e linkar-lo no documento HTML. A fonte do link pode ser chamada tanto no <head>
como no <body>
:
No arquivo: Estrutura do diretório | ||
├── public | └── scripts | └── js | └── main.js └── src └── pages └── index.html |
<html>
<head>
<meta charset="UTF-8">
<script src="./public/scripts/js/main.js"></script>
<title>Hello, World! - JS</title>
</head>
<body>
<script src="./public/scripts/js/main.js"></script>
</body>
</html> |
alert("Hello, World!"); |
o comando alert();
exibe uma janela pop-up no navegador que revela o conteúdo inserido dentro do parêntese, pode ser uma variável ou um texto (entre aspas).
Dessa forma, é possível diminuir a quantidade de linhas de código no seu arquivo HTML, porém deixa o seu website mais pesado com a quantidade de scripts.
Próximo passo, execute o documento index.html
. Resultado:
O script funcionou perfeitamente!
Para acessar o console, pressione a tecla F12 do seu teclado, você será redirecionado as ferramentas de desenvolvedor do seu navegador, vá até console, lá você poderá fazer alterações ou até programar.
Nesse caso, para exibir resultados ou mensagens no console do navegador utilize o comando console.log()
, ele possui uma função semelhante ao alert
, porém somente exibe no console, enquanto o alert
exibe ao usuário.
Outros comandos para serem executados em janela:
window.alert()
janela ok;window.confirm()
janela ok e cancel;window.prompt()
janela com textbox e ok.
// Comentário de uma linha
/*
Comentário de
duas ou mais linhas
*/
Tudo o que existe no mundo dos computadores são dados. Os dados podem ser criados, modificados e apagados. Os dados (e seus diversos tipos) são os blocos básicos da programação. Eles representam uma unidade ou um elemento de informação que pode ser acessado através de um identificador - por exemplo, uma variável, veremos mais adiante sobre as variáveis no JavaScript.
A maior parte das linguagens de programação trabalha com variações baseadas nos quatro tipos primitivos abaixo:
INT
ou número inteiro: valores numéricos inteiros (positivos ou negativos);FLOAT
ou o chamado “ponto flutuante”: valores numéricos com casas após a vírgula (positivos ou negativos);BOOLEAN
ou booleanos: representado apenas por dois valores, “verdadeiro” e “falso”. Também chamados de operadores lógicos;TEXT
: sequências ou cadeias de caracteres, utilizados para manipular textos e/ou outros tipos de dados não numéricos ou booleanos, como hashes de criptografia.
O JavaScript, por exemplo, tem como tipos primitivos embutidos na estrutura básica da linguagem: number
, string
, boolean
e symbol
(de “nome simbólico”, usado entre outras coisas para criar propriedades únicas em objetos).
Já o C# (C-Sharp) trabalha com uma quantidade maior de tipos primitivos, de acordo com o espaço de memória que será ocupado pela variável: Boolean
, Byte
, SByte
, Int16
, UInt16
, Int32
, UInt32
, Int64
, UInt64
, IntPtr
, UIntPtr
, Char
, Double
e Single
.
O C, por sua vez, não tem um tipo próprio de dado booleano; false
é representado pelo número 0
e qualquer outro algarismo representa true
. Outras linguagens podem trabalhar com outras variações.
Os dados são armazenados no que conhecemos como bits. Cada bit pode ter um valor 0
ou 1
, que podemos imaginar como um interruptor que pode estar ligado ou desligado. Por ter 2
possíveis valores, chamamos isso de sistema binário. Essa sequência de zeros e uns fazem o computador conseguir armazenar e interpretar valores. Esses valores serão usados para algum cálculo. Sim, computadores são grandes e caras calculadoras. Tudo o que fazem são cálculos. Quando você está assistindo um vídeo ou escutando uma música, tudo está armazenado em vários zeros e uns, e para reproduzir isso em forma de imagens e sons, cálculos são feitos.
Mas se tudo é feito por 0
e 1
, como outros valores são formados?
Bom, abaixo temos um exemplo simples:
Veja a linha de baixo, a qual tem valores 128
, 64
, 32
, etc. Tudo é lido da direita para a esquerda. Lembra que Bits podem ter valor 1
ou 0
? Então temos dois valores possíveis, o que nos faz ter um número de base 2
.
Na computação, todas as contagens começam no 0
, e não no 1
.
- 2 elevado a 0 é igual a 1;
- 2 elevado a 1 é igual a 2;
- 2 elevado a 2 é igual a 4;
- etc...
E com isso nós vamos obtendo os valores da linha de baixo, de 1
a 128
.
Lembra que esses bits podem ter o valor 1
e 0
como se fosse um interruptor de liga e desliga? Repare então na linha de cima, onde temos apenas 0
e 1
. Os 0
são o "desligado", e o 1
, "ligado".
Então temos os valores 1
, 4
e 8
ligados, certo? 1+4+8 = 13
.
Isso significa que a sequência 00001101
equivale ao valor 13
em binário. É dessa maneira que dados são armazenados e interpretados pelas máquinas.
Mas isso é só uma curiosidade. Com JavaScript e outras linguagens modernas você não precisará se preocupar com o sistema binário. As linguagens hoje em dia nos fornecem várias funcionalidades que, com um simples comando, fazem operações mais complexas.
Curiosidade:
128+64+32+16+8+4+2+1 = 255
. E se tivermos todos os campos "desligados", teremos o valor0
, o que nos dá um total de 256 possíveis valores. Você já deve ter visto esse número por aí no mundo da informática, não é mesmo? Como os antigos pendrives de 256MB, 512MB e 1024MB que é igual a 1GB.
Dica: Veja que nessa cadeia há 8 números. 1 Byte é igual a 8 bits. Então temos aí 8 bits, que resultam em 1 Byte.
Todas as entradas e saída dos algoritmos são utilizados o STDIN e STDOUT de cada linguagem, abaixo tem algumas dicas de como utilizar cada STDIN e STDOUT de cada linguagem. Basicamente, estamos lidando com a leitura e escrita dos dados.
Em JavaScript as funções de STDIN e STDOUT respectivamente são gets()
e console.log
, a função gets
é implementada internamente para auxiliar a entrada dos dados.
Exemplo:
let line = gets(); // Retorna a próxima linha de entrada
console.log(line); // Imprime o dado
Em Java existe várias formas de implementar o STDIN e STDOUT recomendamos utilizar BufferedReader
para o STDIN e o System.out.println
para o STDOUT.
Exemplo:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine()); // Lê a linha de entrada
int a = Integer.parseInt(st.nextToken());
System.out.println(a); // Imprime o dado
Em Python existe várias formas de implementar o STDIN e STDOUT recomendamos utilizar sys.stdin.readline
para o STDIN e o print
para o STDOUT.
Exemplo:
import sys
a = int(sys.stdin.readline()) // Lê a linha de entrada
print(a); // Imprime o dado
![](https://private-user-images.githubusercontent.com/61624336/344795813-4b63bc9b-6986-4186-9c7d-449678082766.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjYxNTk4MzYsIm5iZiI6MTcyNjE1OTUzNiwicGF0aCI6Ii82MTYyNDMzNi8zNDQ3OTU4MTMtNGI2M2JjOWItNjk4Ni00MTg2LTljN2QtNDQ5Njc4MDgyNzY2LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MTIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTEyVDE2NDUzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWY1OTM4MzMxMGJhNmU1YTg2OTk0MDk4YmQxM2M5ZTg5YjA2NDU4MzE3YmRlOWI3ZGMwZTZkMDRmNWFiNjQ2MmMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.I2ydX-Y6kgOwyiP_P2e67U4cEKd7f8q9_Of8meUM5kA)
Como vimos anteriormente, os computadores armazenam e entendem dados na forma binária (0
e 1
).
As linguagens de programação possuem vários tipos de dados diferente do binário, os quais facilitam com que a gente trabalhe com diferentes tipos de dados. Um exemplo bem simples são números e textos. São tipos de dados diferentes.
Com números podemos fazer cálculos, e com textos podemos guardar um texto e fazer uma pesquisa por uma palavra do seu interesse. Os tipos mais simples que uma linguagem possui são chamados de Tipos Primitivos.
O JavaScript possui 6 tipos primitivos no momento, os quais veremos com mais detalhes depois. São eles:
Boolean
- possuem apenas dois valores: verdadeiro ou falso;Undefined
- indica que não foi definido um valor;Null
- indica que um valor é nulo;Number
- armazena valores numéricos;String
- armazena textos;Symbol
- armazena símbolos.
Boolean
(também chamado em português como tipo Booleano ou a sigla "bool") é o tipo mais básico existente nas linguagens de programação. Assim como os bits, eles também só armazenam 2 possíveis valores: true
ou false
(verdadeiro ou falso). Esse tipo é muito importante, pois ele tem um valor lógico para que a gente faça o computador tomar decisões.
Outros valores no JavaScript possuem valores equivalentes ao true
e false
. Um exemplo é o número 0
, ele representa tanto o número zero quanto o valor false
. Isso significa que fazer uma comparação com ele seria o equivalente a fazer uma comparação com false
.
Os seguintes valores são considerados falsos no JavaScript:
0
-0
null
false
NaN
undefined
""
(string vazia)
Qualquer outro valor é considerado true
, até mesmo a String
false
e 0
, pois não são Strings
vazias.
Há dois tipos especiais de valores, undefined
e null
. Eles indicam a ausência de valor.
Imagine que você tenha um formulário que pergunta a idade de uma pessoa, e ela não respondeu ainda. Não podemos dizer que a idade dessa pessoa é 0
. O melhor seria indicar que um valor não foi dado, e nesse caso, usaríamos undefined
ou null
.
Há uma diferença bem pequena entre undefined
e null
. Na verdade a existência de ambos para definir um valor inexistente foi devido a um acidente no projeto do desenvolvimento do JavaScript. Em outras linguagens de programação, normalmente existe apenas o Null
.
Resumidamente, null
ainda é um valor e undefined
é quando o JavaScript não sabe qual o tipo de dado.
let x = null;
let y = 1;
y = null;
console.log(x,y);
Null
: O null
é um tipo de dado especial, ele representa a falta de valor de qualquer outro tipo de dado.
Exemplo: Neste exemplo, obj
é um objeto vazio, e tentamos acessar uma propriedade chamada someProperty
e o método someMethod
que não existe. Isso resultará em um erro e, consequentemente, em null
como saída.
const obj = {};
const result = obj?.someProperty?.someMethod() ?? null;
console.log(result); // Output: null
Undefined
: Este tipo de dado aparece quando criamos uma variável e tentamos acessar seu valor antes de ter atribuído algo a ela.
let x;
console.log(x); // Output: undefined
Undefined !== Null
: undefined
e null
são diferentes.
console.log(undefined !== null); // Output: true
Resumidamente, isto ocorre pois null
ainda é um valor e undefined
é quando o JavaScript não sabe qual o tipo de dado.
O tipo number
é usado para armazenar valores numéricos. Podemos ter números inteiros (sem casas decimais) e números flutuantes (com casas decimais, a qual é indicada por um ponto). As linguagens de programação normalmente têm vários tipos de valores numéricos, mas no JavaScript tudo é Number
.
- Número inteiro (int):
5
- Número flutuante (float):
5.3157
- Para números muito grandes, podemos usar a notação científica, adicionando um "
e
" seguido pelo expoente do número. 2.998e8
- Isso é o mesmo que
2,998 x 10^8
, que é igual a299.800.000
const obj = {};
const result = obj.toString.apply(7);
console.log(result) // Output: [object] number
Também temos três valores especiais no JavaScript que são considerados do tipo Number
, mas não são números comuns.
Os dois primeiros são o Infinity
e -Infinity
, que indicam valores infinitos positivos e negativos.
O último é o NaN
(not a number). Esse valor do tipo Number
indica que um valor não é um número. Por exemplo, se você tentar multiplicar a letra "a"
pelo número 5
, o resultado não pode ser um número, então resultará em NaN
.
As Strings
são usadas para representar textos. Sempre que quisermos um texto teremos que incluir aspas entre o texto, duplas ou simples.
Exemplos:
"Olá, sou uma string"
'Eu também sou'
'7'
' '
As aspas servem para definir onde um texto começa e onde ele termina. Em JavaScript, para manter um padrão de código, é recomendado usar as aspas simples.
Porém, se você precisar usar aspas simples em um texto, é mais fácil criar a String
com aspas duplas, ou sua String
será fechada:
"Mc Donald's"
A aspa simples pôde ser usada normalmente dentro destaString
;'Mc Donald's'
Após o "d", a aspa simples fechou a string, deixando o "s" e a outra aspa soltos. Isso irá resultar em um erro.
Hoje em dia também temos um novo tipo de string, que usa o acento grave (crase) ao invés de aspas. Mais para frente veremos melhor sobre como trabalhar com Strings e a importância desse novo tipo de String.
Para descobrir o tamanho de uma string é usado a propriedade length
:
var txt = 'abcdfghijklmnopqrstuvwxyz'
console.log(txt.length);
Como as strings são descritas entre aspas, o JavaScript não entenderá a string de fora delas.
var txt = 'We are the so-called'Vikings'from the north';
console.log(txt); // Output: Uncaught SyntaxError: Unexpected identifier 'Vikings'
A solução para resolver esse problema é com o uso de caractere de escape de barra invertida.
O caractere de escape de barra invertida “\
” torna caracteres especiais em caracteres de string:
\’
aspas simples:
var txt = 'We are the so-called \'Vikings\' from the north';
console.log(txt); // Output: We are the so-called 'Vikings' from the north
Obs: É possível também alterar o formato das aspas com os valores da linguagem JavaScript.
\"
aspas duplas:
var txt = 'We are the so-called \"Vikings\" from the north';
console.log(txt); // Output: We are the so-called "Vikings" from the north
\\
barras invertidas:
var txt = 'We are the so-called \\ from the north';
console.log(txt); // Output: We are the so-called \ from the north
Outras seis sequências escapes são válidas em JavaScript:
\b |
Retrocesso |
\f |
Formulário voluntário |
\n |
Nova linha |
\r |
Retorno de transporte |
\t |
Tabulador horizontal |
\v |
Tabulador vertical |
O Symbol
é um novo tipo primitivo do JavaScript. Ele é um tipo de dado que é único e imutável. Podemos usá-los como identificadores de propriedades de objetos, que conheceremos melhor mais para frente.
![](https://private-user-images.githubusercontent.com/61624336/345891471-6733bf82-6a3d-482e-bf55-0562c485c8b5.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjYxNTk4MzYsIm5iZiI6MTcyNjE1OTUzNiwicGF0aCI6Ii82MTYyNDMzNi8zNDU4OTE0NzEtNjczM2JmODItNmEzZC00ODJlLWJmNTUtMDU2MmM0ODVjOGI1LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MTIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTEyVDE2NDUzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTgwOWFkNzk4NDFiMGM4YWU3MmJlMjA1NmFlNTI1YWRiNmQ5MWRhMDRiNjcyYzA3OWI5OGEzZmQwOWJiNmI1NGMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.StIHVSPNLeQ-RoA6uheIbA2SHWDw14gvrnRfE3y-h5A)
Até agora só vimos valores soltos que não fazem nada. Para fazermos alguma operação com esses valores, usamos os chamados "operadores".
Um exemplo bem simples: 7 + 10
O sinal +
é um operador, o qual podemos usar para somar dois valores numéricos.
Há vários tipos de operadores para as mais diversas operações. Nos próximos capítulos nós veremos vários grupos com seus operadores mais comuns e suas respectivas funções.
![](https://private-user-images.githubusercontent.com/61624336/344786612-2caeeae0-19de-4294-85cb-b692067dfdb2.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjYxNTk4MzYsIm5iZiI6MTcyNjE1OTUzNiwicGF0aCI6Ii82MTYyNDMzNi8zNDQ3ODY2MTItMmNhZWVhZTAtMTlkZS00Mjk0LTg1Y2ItYjY5MjA2N2RmZGIyLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MTIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTEyVDE2NDUzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTg4MTYyOGJkMmE5ZmEzN2QyYTU4NTVkN2MzZDlhY2ViYzA2MjJiZGY1MDUzNjUxYjQ0NTY2YWNjYjVlN2MxODEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.2qdhbVnaroiSbVz8zzPmoqM-7QAQQ-1PcKMrtMaCuN4)
Chamamos de Operadores Lógicos aqueles que nos ajudam a trabalhar com o tipo Boolean
(verdadeiro ou falso). Assim como na tabela-verdade e portas lógicas, o &&
indica uma condição e
, e o ||
indica uma condição ou
. Basicamente servem para juntar dois valores do tipo Boolean
e ver se o resultado é algo verdadeiro
(true
) ou falso
(false
). Vamos se basear no seguinte exemplo: sorvete de baunilha
Operador &&
(AND): Se tivermos duas verdades, o resultado só pode ser verdadeiro, correto? Se eu disser que esse objeto é um sorvete E é baunilha
, são duas verdades, o que resulta em true
.
E se tivermos duas mentiras, o resultado só pode ser falso. Se eu disser que esse objeto é um garfo E é vermelho
, são duas mentiras, o que resulta em false
.
Agora, se eu disser algo falso e algo verdadeiro (ou verdadeiro e falso, não importa a ordem), isso fará com que minha frase seja falsa. Se eu disser que é um sorvete E é chocolate
, uma simples parte falsa torna a frase inteira falsa.
Dica: Resumindo, o resultado do operador
&&
só será verdadeiro se tudo na operação também for verdadeira. Basta apenas um elemento ser falso que o resultado se tornará falso.
Operador ||
(OU): Vamos usar o mesmo copo azul
para explicar o operador OU. Se eu disser duas verdades, o resultado só pode ser verdadeiro. Se eu disser que o objeto é um copo OU é azul
, são duas verdades, o que resulta em true
.
Se eu disser duas mentiras, o resultado só pode ser falso. Se eu disser é um garfo OU é vermelho
, são duas mentiras, o que resulta em false
.
Agora aqui é diferente do &&
. Em uma comparação ||
, se houver uma verdade, o resultado será verdadeiro.
Se eu disser que o objeto é um copo OU é verde
(a ordem não importa), eu não estou mentindo. O resultado aqui será true.
Dica: Resumindo, o resultado do operador
||
só será falso se tudo na operação também for falso. Basta apenas um elemento ser verdadeiro que o resultado se tornará verdadeiro.
Operador ??
: O operador de coalescência nula (??
) em JavaScript é um operador lógico que retorna o seu operando do lado direito quando o operando do lado esquerdo é null
ou undefined
. Caso contrário, ele retorna o seu operando do lado esquerdo.
Em outras palavras:
- Se o valor à esquerda do operador for
null
ouundefined
, o valor à direita é retornado. - Se o valor à esquerda não for
null
nemundefined
, o valor à esquerda é retornado.
Isso é útil para fornecer um valor padrão quando o valor original é null
ou undefined
. Por exemplo:
const valorOriginal = null;
const valorPadrao = "Olá!";
const resultado = valorOriginal ?? valorPadrao;
console.log(resultado); // Output: "Olá!"
O operador de coalescência nula evita comportamentos inesperados que podem ocorrer com o operador lógico OR (||
), que também é usado para fornecer valores padrão, mas considera outros valores “falsy” (como 0
, ‘’
, ou NaN
) como utilizáveis.
Os Operadores Aritméticos são bem simples de se entender. Eles são usados com números para que possamos fazer cálculos.
+
(adição)-
(subtração)*
(multiplicação)/
(divisão)%
(módulo) = resto da divisão**
(potenciação)
Também temos os operadores de incremento ++
e decremento --
. O operador ++
aumenta o valor em 1
unidade, ou seja, se colocarmos com o valor 2
, seu valor se tornará 3
.
O operador --
diminui o valor em 1
unidade, ou seja, se colocarmos com o valor 3
, seu valor se tornará 2
. Veremos melhor sobre esses operadores mais para frente.
Os operadores de igualdade servem para compararmos se dois valores são iguais ou diferentes. A operação da comparação retornará um valor true
ou false
.
==
serve para verificarmos se dois valores são iguais.!=
serve para verificarmos se dois valores são diferentes.
Obs: O operador
=
é somente usado para atribuir um valor e não para verificar os dois valores como os operadores==
ou!=
. Ele é muito usado em variáveis, que veremos mais pra frente!
Dica:
!
é um operador que indica negação. Então "!=
" seria o equivalente que dizer que algo é "não igual".
Usar esses comparadores pode causar alguns problemas, pois eles vão pelo valor, ignorando o tipo do valor. Vamos entender melhor:
Lembra que foi dito que o 0
tem valor false
? Então se compararmos 0 == false
será retornado true
.
Se tivermos um número 3
e uma String "3", ambos são diferentes, certo? Pois o primeiro é um número e o segundo é um texto.
Porém, se fizermos a comparação 3 == "3"
, a String
será convertida automaticamente para o tipo Number
, e a comparação retornará true
.
Isso pode causar algumas inconsistências em certos casos. Por isso que é muito recomendado sempre fazer comparações com valores do mesmo tipo. Para garantir que estamos fazendo comparações com valores e tipos iguais, acrescentamos um =
a mais na comparação.
Isso significa que a comparação 3 == "3"
retorna true
, mas a comparação 3 === "3"
retorna false
, pois ===
também leva em consideração o tipo do valor.
Dica:
===
é um operador que é usado para extrema igualdade.
Para ter certeza que algo é diferente, incluindo o tipo, temos o operador !==
.
Dica:
!==
é um operador que é usado para extrema diferença.
Os Operadores Relacionais servem para compararmos valores, verificando se algo é maior ou menor. São mais usados com valores numéricos, mas também podem ser usados com Strings. Eles sempre retornam um valor true
ou false
.
<=
verifica se um valor é menor ou igual;>=
verifica se um valor é maior ou igual;<
verifica se um valor é menor;>
verifica se um valor é maior;
Além de valores numéricos, podemos também comparar Strings, como:
"a" < "z".
O Operador +
também tem outra função além de somar números: ele concatena Strings. Isso significa que podemos usá-lo para juntar duas ou mais Strings em uma só:
"Olá" + "" + "João";
"Minha idade é" + 20;
No exemplo acima nós juntamos uma String com um cumprimento, uma String com um espaço vazio e uma String com um nome. Isso pode ser muito útil quando você possui um texto padrão para exibir e deve inserir dados do seu usuário, como o nome, no meio do texto.
Até agora vimos operadores que precisam de dois elementos para funcionar, como é o caso da soma (5 + 3), onde passamos dois números. Esses operadores são chamados de Operadores Binários.
Também temos os Operadores Unários, que são aqueles que só recebem um valor para funcionar.
O primeiro é o "-
". Além de ser usado como operador de subtração, ele pode ser usado para inverter o sinal de um número. Então um número positivo se torna negativo e um negativo se torna positivo.
-3
Como vimos antes, esse operador serve para negação !
. Ele inverte os valores do tipo Boolean
. Então um valor true
se torna false
e um false
se torna true
.
!true
Nem todos os operadores são símbolos. Um exemplo deles é o "typeof
". Ele nos ajuda a descobrir o tipo de algum valor, se é String
, Number
, etc.
typeof 3
Vimos os operadores binários e unários. Vamos ver agora o Operador Ternário Condicional. Ele recebe três valores e serve para verificarmos uma condição.
3 > 1 ? 'É maior' : 'É menor' // retorna a String "É maior"
Podemos dividir então em três partes:
(3 > 1) ? ('É maior') : ('É menor')
A primeira parte é uma condição, a qual deve ter um valor true
ou false
. Nós comparamos se 3 é maior que 1. Veja que é como se perguntássemos "3 é maior que 1?"
Caso a resposta seja verdadeira, o segundo elemento que passamos será retornado, no caso, a String "É maior". Se a resposta for falsa, o terceiro elemento que passamos será retornado, no caso, a String "É menor".
3 > 8 ? 'É maior' : 'É menor' // retorna a String "É menor"
No mundo da programação temos o chamado "Conversão de Tipos". Isso porque muitas vezes estamos trabalhando com um valor que é de um tipo, mas precisamos fazer alguma operação com ele como se ele fosse de um outro tipo.
Um exemplo clássico é quando perguntamos a idade de um usuário. Nada impede que o usuário tecle "ABC
". Mesmo que ele escreva apenas números, receberemos uma String
, como "21
".
Porém, para trabalharmos com isso, precisamos que este valor seja do tipo Number. Então precisaremos converter a String
em Number
.
Ou caso a gente faça um cálculo e queira exibir uma mensagem com o resultado. Precisaremos converter esse número para String
para podermos concatená-lo com nosso texto.
Em muitas linguagens de programação, essa conversão deve ser feita manualmente. O JavaScript faz conversões automaticamente. Isso pode deixá-lo mais dinâmico, mas se não for usado com cuidado pode causar muitos problemas e falhas de lógica, causando resultados inesperados.
"5" – 1
Estamos subtraindo 1
de uma String
. O JavaScript automaticamente tenta converter a String
para o tipo Number
para fazer a operação de subtração, resultando em 4
.
"5" + 1
Aqui ele verá a operação como uma concatenação de Strings. Então o 1
será convertido para String, resultando em "51"
.
Por isso é importante conhecer bem o comportamento da linguagem, para não ter surpresas com o que ocorre automaticamente.
Vimos até agora alguns comandos simples com os operadores. Vimos que eles produzem um valor quando executados, como é o caso de "5 + 3"
que produz o valor "8"
.
Até mesmo quando simplesmente digitamos 8
estamos gerando o valor 8
. Todo fragmento de código que produz um valor é chamado de "expressão".
Podemos aninhar expressões para gerar códigos mais complexos, assim como podemos juntar várias palavras e frases para formar grandes textos para passar ideias para outras pessoas. Um programa é feito de linhas de códigos cheios de comandos, que em outras palavras, é uma lista de expressões.
A capacidade de escrever diversas informações na tela, como "Olá, mundo!"
pode ser divertido por um tempo, mas não é uma forma universal de escrever programas. É hora de começar a aprender mais sobre os elementos do quebra-cabeça que permitirão criar programas que resolvam problemas reais. Existem alguns desses elementos e iremos apresentá-los gradualmente, embora não necessariamente em uma cronologia simples. Freqüentemente voltaremos ao que já foi discutido, ampliando as informações anteriores com algo novo. Às vezes também avançaremos, utilizando mecanismos que só serão explicados com mais detalhes ao longo do tempo.
No início pode parecer um pouco esmagador, mas com o tempo tudo deverá começar a fundir-se num quadro coerente. O primeiro elemento de programação sobre o qual falaremos é a variável. Você pode conhecer o nome de uma variável da matemática, onde significa um símbolo usado como espaço reservado para diferentes valores que podem mudar. Eles têm um papel semelhante na programação. Para que realmente precisamos deles? Como você pode imaginar, a maioria dos programas é bastante complexa e raramente conseguimos resolver o problema com uma única operação. Normalmente, o programa consistirá em muito mais operações, cada uma das quais poderá produzir alguns resultados intermediários, que serão necessários nas próximas etapas. As variáveis nos permitem armazenar tais resultados, modificá-los ou alimentá-los em operações subsequentes, funcionam como contêineres de dados.
Até agora só escrevemos simples códigos que não servem para nada. Simplesmente escrevemos um valor e no máximo fizemos algumas operações com os valores que digitamos. Como você deve imaginar, um programa não fica pedindo dados toda hora para o usuário. Ele armazena esses dados e pode fazer várias operações com esse valor. Mas se escrevermos um valor, como acessá-lo novamente em outro lugar? Se escrevemos um valor "5"
no comando, como alterá-lo depois ou gerar novos valores? É aí que entram em cena as chamadas variáveis.
Imagine as variáveis como caixinhas onde podemos armazenar um valor e depois ir lá modificar ou apagar. Também damos um nome para essa "caixinha", para podermos acessar o nosso valor por um nome.
Em muitas linguagens de programação, como Java, C# e TypeScript, precisamos indicar qual o tipo que a variável irá armazenar, como Boolean
(booleano) ou String
(caractere). Dizemos que a linguagem possui "Tipagem Estática".
O JavaScript possui o que chamamos de "Inferência de Tipo". Nós não precisamos declarar o tipo da variável. Se passarmos um número para uma variável, o JavaScript já saberá que aquela variável será do tipo Number
. Isso também ocorre em linguagens como PHP, Python, Ruby e C# (sim, o C# também aceita inferência de tipos). Nesse caso, dizemos que a linguagem possui uma "Tipagem Dinâmica". Além disso, as variáveis do JS se organizam de cima para baixo.
Imagine variáveis como contêineres nos quais você pode armazenar certas informações (tais informações serão chamadas de valores de variáveis). Cada container deverá ter um nome próprio, pelo qual poderemos indicá-lo claramente.
Normalmente temos bastante liberdade na hora de inventar esses nomes, mas lembre-se que eles devem se referir ao que armazenaremos na variável (por exemplo, altura, cor, contador de passos e assim por diante). É claro que o JavaScript não verificará a correlação entre o nome e o conteúdo da variável – é simplesmente uma das muitas boas práticas que tornam mais fácil para nós e para outros entender o código posteriormente.
Na maioria das linguagens de programação, uma variável deve ser declarada antes de ser usada, e JavaScript não é exceção. Declarar uma variável é simplesmente “reservar” o nome da variável. Desta forma, informamos ao programa que no final da execução utilizaremos este nome para nos referirmos ao nosso container, a fim de recuperar um valor dele, ou salvar um valor nele.
Em JavaScript, os nomes das variáveis podem consistir em qualquer sequência de letras (minúsculas e maiúsculas), dígitos, caracteres de sublinhado e cifrões, mas não devem começar com um dígito. Existe uma lista de palavras reservadas que não podem ser usadas como nomes de variáveis (veja a tabela abaixo).
O importante também é que o interpretador JavaScript faça distinção entre letras minúsculas e maiúsculas, também em nomes de variáveis, portanto nomes como teste
, Teste
ou TESTE
serão tratados como diferentes.
Os nomes das variáveis em JavaScript podem ser praticamente qualquer sequência de caracteres. No entanto, existe um conjunto de palavras reservadas que não podem ser usadas para nomear variáveis, funções ou qualquer outra coisa. Eles são partes integrantes da linguagem e recebem um significado que não pode ser alterado. Abaixo você encontrará uma lista deles. | |||
abstract |
arguments |
await |
boolean |
break |
byte |
case |
catch |
char |
class |
const |
continue |
debugger |
default |
delete |
do |
double |
else |
enum |
eval |
export |
extends |
false |
final |
finally |
float |
for |
function |
goto |
implements |
if |
import |
in |
instanceof |
int |
interface |
let |
long |
native |
new |
null |
package |
private |
protected |
public |
return |
short |
static |
super |
switch |
synchronized |
this |
throw |
throws |
transient |
true |
try |
typeof |
var |
void |
volatile |
while |
with |
yield |
Como mencionamos antes, declaramos a variável para reservar um nome para ela. Isso é uma simplificação, pois na verdade o espaço de memória também é reservado para a variável, mas quando programamos em JavaScript praticamente nunca precisamos pensar no que acontece na memória. Normalmente, os valores armazenados na variável poderão ser modificados durante a execução do programa (afinal são "variáveis"). Por que normalmente? Porque podemos declarar variáveis cujos valores não podem ser alterados. Para ser honesto, nós nem as chamamos mais de variáveis – nós as chamamos de constantes.
Para as declarações, usamos as palavras-chave var
ou let
para variáveis e const
para constantes. Por enquanto, porém, vamos ficar com as variáveis usuais e retornaremos às constantes em um momento. Vamos analisar o seguinte exemplo de código (você também o encontrará na janela do editor – execute-o lá e observe os resultados no console):
var height;
console.log(height); // -> undefined
console.log(weight); // -> Uncaught ReferenceError: weight is not defined
A primeira linha é a declaração da variável (podemos ver a palavra-chave (keyword) chamada var
). Esta declaração significa que a palavra altura (height
) será tratada como o nome do contêiner para determinados valores. A declaração, como outras instruções JavaScript, deve terminar com ponto e vírgula (;
). Na segunda linha, tentamos escrever o valor desta variável (ou seja, o que está no container) no console. Como ainda não colocamos nada lá, o resultado é indefinido (undefined
) (o intérprete conhece essa variável, mas ela ainda não tem valor – o valor é indefinido). Na próxima linha, tentamos imprimir o conteúdo da variável peso (weight
) que esquecemos de declarar. Desta vez, veremos ReferenceError
. O interpretador JavaScript, que executa nosso programa, nos informou que não conhece uma variável com este nome (portanto, a própria variável é indefinida).
A alternativa é a palavra-chave let
. Usamos ambas as palavras-chave da mesma maneira. Ambos são destinados à declaração de variáveis e podem ser encontrados em diferentes exemplos na Internet ou em livros. No entanto, eles não são exatamente iguais e discutiremos as diferenças em sua operação posteriormente (mesmo em vários lugares). A palavra-chave var
vem da sintaxe original do JavaScript e a palavra-chave let
foi introduzida muito mais tarde. Portanto, você encontrará var
em programas mais antigos. Atualmente, é altamente recomendável usar a palavra let
por motivos que discutiremos em breve. Então, vamos dar uma olhada em nosso exemplo reescrito desta vez usando a palavra-chave let
.
let height;
console.log(height); // -> undefined
Uma das diferenças básicas no uso de var
e let
é que let
nos impede de declarar outra variável com o mesmo nome (é gerado um erro). Usar var
permite declarar novamente uma variável, o que pode levar a erros na execução do programa.
var height;
var height;
console.log(height); // -> undefined
O exemplo acima demonstra a possibilidade de redeclarar uma variável usando a palavra-chave var
. Nesta situação não causará erro, mas em programas mais complexos uma redeclaração, principalmente por acidente, pode não ser mais isenta de consequências. Ao declarar com let
, o interpretador verifica se tal variável já foi declarada, independentemente de let
ou var
ter sido usado na declaração anterior.
let height;
let height; // -> Uncaught SyntaxError: Identifier 'height' has already been declared
console.log(height);
Portanto, use let
para declarar variáveis, mesmo porque você não deseja declarar acidentalmente uma variável novamente.
Após uma declaração bem-sucedida, a variável deve ser inicializada, ou seja, deve receber seu primeiro valor. A inicialização é feita atribuindo um determinado valor a uma variável (indicada pelo seu nome). Para atribuí-lo, usamos o operador =
.
Você pode atribuir a uma variável: um valor específico; o conteúdo de outra variável; ou, por exemplo, o resultado retornado por uma função. A inicialização pode ser feita junto com a declaração ou separadamente como um comando independente. É importante inserir o primeiro valor na variável antes de tentar lê-la, modificá-la ou exibi-la.
let height = 180;
let anotherHeight = height;
let weight;
console.log(height); // -> 180
console.log(anotherHeight); // -> 180
weight = 70;
console.log(weight); // -> 70
No exemplo acima (confira no editor), as declarações das variáveis height
e anotherHeight
são combinadas com sua inicialização, enquanto a variável weight
é declarada e inicializada separadamente. As variáveis height
e weight
são inicializadas fornecendo valores específicos (mais precisamente, um número), enquanto a variável anotherHeight
recebe um valor lido da variável height
. Os valores de todas as variáveis são exibidos no console.
A propósito, preste atenção em uma coisa. Se você especificar um nome de variável em console.log
, o interpretador a reconhecerá e exibirá seu valor. Se você colocar o mesmo nome entre aspas, ele será tratado como texto simples e exibido como tal.
let height = 180;
console.log(height); // -> 180
console.log("height"); // -> height
O JavaScript teve algumas mudanças importantes introduzidas em 2009 e 2015. A maioria dessas mudanças estendeu a sintaxe da linguagem com novos elementos, mas algumas delas diziam respeito apenas à operação dos interpretadores JavaScript. Muitas vezes tratava-se de esclarecer o comportamento dos intérpretes em situações potencialmente errôneas, como em casos de inicialização de variáveis sem qualquer declaração prévia. Vejamos um exemplo:
height = 180;
console.log(height); // -> 180
À primeira vista, você pode ver que esquecemos de declarar a variável height
. A sintaxe original do JavaScript permitia tal negligência e no momento da inicialização fez esta declaração para nós. Parece uma solução bastante boa, mas infelizmente às vezes pode levar a situações ambíguas e potencialmente errôneas (diremos mais algumas palavras sobre isso enquanto discutimos o escopo). Vamos modificar nosso exemplo:
"use strict";
height = 180; // -> Uncaught ReferenceError: height is not defined
console.log(height);
No início do nosso código, adicionamos "use strict";
. Esta afirmação mudou radicalmente o comportamento do intérprete. Por que? Usamos isso quando queremos forçar o interpretador a se comportar de acordo com os padrões modernos do JavaScript. Portanto, contanto que você não esteja executando um código muito antigo, você deve sempre usá-lo. E desta vez, usar uma variável sem sua declaração anterior é tratado como um erro. A frase “use strict”;
deve ser colocado bem no início do código. Isso fará com que o intérprete lide com o restante do código usando o modo estrito, que é o padrão JavaScript moderno. Todos os outros exemplos do nosso curso estarão preparados para funcionar neste modo por padrão, mesmo que "use strict";
nem sempre aparece no início do código.
O "Strict mode"
é uma funcionalidade do ECMAScript 5 (ES5) que permite que você coloque um programa ou uma função em um modo operacional que ajuda a escrever código mais seguro e de melhor performance. Isso é feito adicionando a linha "use strict";
no início do seu script ou função. Quando em strict mode, o JavaScript impõe várias restrições que não estão presentes no modo normal (ou "sloppy mode"). Essas restrições ajudam a evitar erros comuns de programação e a criar um código mais previsível.
Principais benefícios do strict mode:
- Erros silenciosos tornam-se visíveis: Sem o strict mode, certos erros que normalmente passariam despercebidos ou seriam silenciosamente ignorados são agora lançados como exceções.
- Impede o uso de variáveis globais acidentais: No modo estrito, atribuir um valor a uma variável que não foi declarada resulta em um erro.
- Elimina alguns recursos que são considerados problemáticos: O strict mode desativa algumas funcionalidades do JavaScript que são confusas ou propensas a erros.
- Melhora a otimização pelo compilador: O código em strict mode pode ser otimizado de forma mais eficiente pelos compiladores JavaScript.
Exemplo 1: Uso global do strict mode
"use strict";
x = 3.14; // Isto causará um erro porque x não foi declarado
Exemplo 2: Uso do strict mode dentro de uma função
function myFunction() {
"use strict";
y = 3.14; // Isto causará um erro porque y não foi declarado
}
Exemplo 3: Erro ao deletar uma propriedade não configurável
"use strict";
var obj = {};
Object.defineProperty(obj, "x", { value: 42, writable: false });
obj.x = 9; // Isto causará um erro porque x não é gravável
Exemplo 4: Erro ao usar palavras reservadas para variáveis
"use strict";
var eval = 5; // Isto causará um erro
var arguments = 10; // Isto causará um erro
Regras específicas do strict mode:
-
Variáveis não declaradas: No strict mode, qualquer tentativa de atribuir um valor a uma variável que não foi declarada previamente resultará em um erro.
-
Palavras reservadas: Palavras que são reservadas para futuras versões do ECMAScript (como
implements
,interface
,let
,package
,private
,protected
, public,static
, eyield
) não podem ser usadas como identificadores. -
Parâmetros duplicados: Funções não podem ter parâmetros duplicados.
-
Objeto
this
: Dentro de funções, o valor dethis
não será convertido em objeto global se não estiver definido. -
Propriedades não configuráveis: Não é possível deletar propriedades não configuráveis.
-
with
statement: O uso dewith
não é permitido.
Esses exemplos e regras ilustram como o strict mode pode ajudar a evitar erros comuns e melhorar a qualidade do código JavaScript.
Variáveis, como o próprio nome sugere, podem armazenar dados que variam. As alterações são feitas atribuindo um novo valor à variável, que substitui o anterior.
let steps = 100;
console.log(steps); // -> 100
steps = 120; // -> 120
console.log(steps);
steps = steps + 200;
console.log(steps); // -> 320
Em nosso exemplo, declaramos uma variável chamada etapas (steps
). Inicialmente, ele contém o número 100
, que é então alterado para 120
. Em seguida, adicionamos 200
ao conteúdo atual da variável, e como resultado a variável contém 320
.
Variáveis na linguagem JavaScript não são digitadas (ou, para ser mais preciso, são digitadas de forma fraca e dinâmica). Isso significa que o JavaScript não controlará o tipo de valor que armazenamos na variável. Qual é exatamente o tipo de dados? Você provavelmente pode responder intuitivamente a essa pergunta sozinho. O tipo determina a pertença de um determinado dado a um determinado conjunto que compartilha as mesmas propriedades e no qual é possível realizar as mesmas operações. Os tipos de dados variam muito dependendo da linguagem de programação. Em JavaScript, os principais tipos são números e sequências de caracteres. Falaremos muito mais sobre tipos no próximo capítulo. Vamos declarar algumas variáveis e inicializá-las com valores de diferentes tipos:
let greeting = "Hello!";
let counter = 100;
Como você pode ver, a variável saudação (greeting
) é iniciada com um valor do tipo string
, enquanto a variável contador (counter
) é iniciada com um valor do tipo Number
. Continuando o exemplo, faremos uma pequena alteração no conteúdo da variável saudação.
console.log(greeting); // -> Hello!
greeting = 1;
console.log(greeting); // -> 1
JavaScript nos permite substituir facilmente a variável de saudação por um valor cujo tipo seja diferente daquele originalmente armazenado lá. JavaScript vai um passo além e não apenas nos permite alterar os tipos de valores mantidos em uma variável, mas também realiza sua conversão implícita se necessário (também voltaremos a este tópico de conversão quando discutirmos tipos). Vamos restaurar o valor original da variável saudação e então adicionar o valor da variável contador a ele.
greeting = "Hello!";
greeting = greeting + counter;
console.log(greeting); // -> Hello!100
O intérprete verificará o tipo de valor armazenado na variável de saudação e converterá o valor da variável contador para o mesmo tipo antes de realizar uma operação de adição. Como resultado, a string "100"
será adicionada ao campo "Hello!"
cadeia de caracteres e armazenada na variável de saudação. A propósito, observe que o JavaScript interpreta 100
como um número, mas “100”
como uma string.
Até agora, presumimos que após declarar uma variável, seu nome poderia ser usado em todo o código do programa (ou seja, o escopo da variável é global). Isto não é totalmente verdade – o escopo de uma variável depende de onde ela é declarada. Infelizmente, para uma boa compreensão do escopo de variáveis, precisamos aprender mais alguns elementos de programação, como instruções ou funções condicionais, que serão discutidos com mais detalhes posteriormente neste curso. Portanto, aqui nos limitaremos às informações básicas e voltaremos a esse assunto em diferentes partes do curso. Um dos elementos básicos que influenciam o escopo das variáveis é um bloco de programa.
Podemos separar o código de um programa em blocos. Nos blocos que criamos usando chaves, existe um conjunto de instruções, que por algum motivo devem ser tratadas de forma independente. Os blocos geralmente estão associados a instruções condicionais, loops ou funções, dos quais falaremos mais tarde. Também podemos separar um bloco de um programa não relacionado com nada de especial, simplesmente escolhendo um determinado conjunto de instruções (na prática, isto não se justifica particularmente, e por enquanto apenas o faremos por motivos educativos). Vejamos um exemplo:
let counter;
console.log(counter); // -> undefined
{
counter = 1;
console.log(counter); // -> 1
}
counter = counter + 1;
console.log(counter); // -> 2
Primeiro, declaramos a variável contador. Em seguida, abrimos um bloco dentro do qual inicializamos esta variável e exibimos seu conteúdo. Fora do bloco, aumentamos o valor armazenado na variável em 1
e o exibimos novamente. Neste caso, o intérprete executará o programa como se não tivesse percebido o bloco, percorrendo as instruções antes do bloco, no bloco e depois do bloco. Criar um bloco aqui, sem, por exemplo, instruções condicionais, não tem justificativa real – é apenas um exemplo de uso de colchetes.
Os blocos de programa podem ser aninhados, ou seja, podemos criar um bloco dentro de outro.
let counter;
console.log(counter); // -> undefined
{
counter = 1;
{
console.log(counter); // -> 1
}
}
counter = counter + 1;
console.log(counter); // -> 2
A propósito, observe que o código dentro do bloco foi movido para a direita. Isso é chamado de recuo. Para um interpretador JavaScript, isso não importa, mas definitivamente aumenta a legibilidade do código, permitindo que os leitores (incluindo você) descubram rapidamente quais partes do código estão dentro e quais estão fora do bloco. Os editores de código geralmente adicionam recuos nos lugares certos sozinhos, mas é um bom hábito lembrar disso você mesmo e, se eles não aparecerem automaticamente, formatar o código manualmente.
Vamos ver também como podemos declarar e nomear variáveis, sendo que as variáveis podem ser classificadas em duas categorias:
Variáveis locais são as variáveis que estão dentro do escopo de um programa / função / procedimento. Acessíveis apenas dentro do bloco de código (função, loop, etc.) onde foram definidas.
function showLocalVar() {
var localVar = "I am local";
console.log(localVar); // Output: "I am local"
}
showLocalVar();
console.log(localVar); // Error: localVar is not defined
Variáveis globais são as variáveis que estão no escopo para o tempo de execução do programa. Elas podem ser recuperadas por qualquer parte do programa. São acessíveis em qualquer parte do código.
var globalVar = "I am global";
function showGlobalVar() {
console.log(globalVar); // Output: "I am global"
}
showGlobalVar();
console.log(globalVar); // Output: "I am global"
Outro ponto, são os escopos que são definidos pela região ao qual variáveis e outros dados são visíveis dentro do código, funcionam como se fosse uma hierarquia em camadas. Em ambos os casos e os tipos de escopos, podemos utilizar as variáveis do JS: var
, let
e const
.
Existem três tipos de escopos:
Escopo Global é quando uma variável declarada fora de uma função, torna-se global e todos os scripts e funções em uma página da Web podem acessá-la.
Exemplo:
var valor = 12;
let umaFuncao = function() {
console.log(valor + 2);
}
umaFuncao();
Escopo de Função é quando uma variável declarada dentro de uma função, torna-se parte somente da função que a página da Web pode acessá-la.
Exemplo:
function testarValor () {
const valor = prompt('Digite o valor: ');
if(valor > 15){
return 'O valor é maior do que 15';
}
else if(valor < 15){
return 'O valor é menor do que 15';
}
else if(valor >= 15 && valor <= 15){
return 'O valor está na faixa de 15';
}
else{
return 'Não é um número';
}
}
testarValor();
Obs: Não utilize o comando
return
para chamar a função, isso retornará o erroUncaught SyntaxError: Illegal return statement
. Isso sinaliza que oreturn
não é necessário para retornar uma função simples.
Escopo Local são variáveis declaradas dentro de um local cercado por { }
.
Exemplo:
function exemploFuncao() {
if (true) {
let localLet = "Eu sou uma variável local com let";
const localConst = "Eu sou uma variável local com const";
console.log(localLet); // Saída: Eu sou uma variável local com let
console.log(localConst); // Saída: Eu sou uma variável local com const
}
// Tentando acessar as variáveis fora do bloco resultará em erro
// console.log(localLet); // Erro: localLet is not defined
// console.log(localConst); // Erro: localConst is not defined
}
exemploFuncao();
Agora, vamos ver alguns princípios de noções e boas práticas de código para essas variáveis:
A variável global não é muito recomendada, pois pode gerar conflitos com outras variáveis dependendo do escopo.
a = 5;
A variável local e global, muito recomendada para ambos os escopos!
var a = 5;
Esse tipo de variável está dizendo explicitamente que a variável é global na janela:
window = 5;
Exemplo de execução de variáveis:
var idade = 5;
var idade = 7;
console.log(idade)
// Output: 7
O JS é Case Sensitive, ou seja, as letras maiúsculas e minúsculas fazem diferença na declaração de variáveis. Ademais, as variáveis no JS são declaradas no topo do código para baixo, por isso o valor é definido corretamente. Além disso, as variáveis não podem conter acentos ou espaços, para caracteres especiais somento o "$
" e o "_
", mas não são muito recomendados. Ademais, números são permitidos desde que sejam precedidos de uma ou mais letras.
Dica: É opcional, mas se possível crie variáveis em inglês para deixar o seu código mais uniforme, facilitará muito mais no entendimento.
Exemplo: O nome da variável Idade
substitua para Old
ou yearOld
.
var Old = 5;
var yearOld = 7;
console.log(idade)
// Output: 7
Bem uniforme e fácil de compreensão para todos!
Declarando variáveis com operadores de atribuição:
var myValue = 5;
myValue = myValue + 2; // myValue += 2
Os atalhos de operação de atribuição são:
+=
--=
-/=
-*=
-%=
-**=
-
Obs: Também funciona com a concatenação e incremento ou decremento.
var myText = 'abc';
myText = myText + 'def'; // myText += 'def'
Podemos também alterar o valor de definição dessa variável, no exemplo abaixo, eu usei no console do browser:
// input
var curso = "Javascript";
// output
curso
// resultado do output = 'Javascript'
// outro input
curso = "PHP";
// resultado = 'PHP'
Incremento e decremento de valores das variáveis:
var myValue = 5;
myValue = myValue - 1; // myValue -= 1;
var newValue = myValue++;
E se, fizermos uma pequena alteração? Perceba como isso iria afetar logicamente o nosso código:
--myValue
ignora o valor antigo e executa o decremento;myValue--
chama o antigo e executa o decremento.
Isso funciona com o incremento
++
também.
Veja agora, a diferença entre os tipos de variáveis no JavaScript, é algo bastante notório no escopo e na execução do código:
var
funciona em qualquer lugar do programa independente de onde foi declarado. Além disso, pode ser alterada e renovada.
var nome = "Samuel";
if(true) {
var nome = "Isaac";
}
console.log(nome);
// Output: Isaac
let
funciona em apenas um determinado bloco do programa. Não permite que use a mesma variável de novo.
nome = "Samuel"
if(true) {
let nome = "Isaac";
nome += " Alves";
console.log(nome);
}
// Output: Isaac Alves
A palavra-chave const
é usada para declarar contêineres semelhantes a variáveis. Esses contêineres são chamados de constantes. Constantes também são usadas para armazenar certos valores, mas uma vez que os valores tenham sido inseridos nelas durante a inicialização, eles não poderão mais ser modificados. Isso significa que este tipo de contêiner é declarado e inicializado simultaneamente. Por exemplo, a seguinte declaração da constante de saudação está correta:
const greeting = "Hello!";
Mas este próximo definitivamente causa um erro:
const greeting; // -> Uncaught SyntaxError: Missing initializer in const declaration
greeting = "Hello!";
Como dissemos, uma mudança na constante é impossível. Desta vez a declaração está correta, mas tentamos modificar o valor armazenado na constante.
const greeting = "Hello!";
greeting = "Hi!"; // -> Uncaught TypeError: Assignment to constant variable.
O principal objetivo de uma constante é erradicar a possibilidade de alteração acidental de um valor nela armazenado. Isso é importante quando temos alguns valores que realmente nunca deveriam mudar. Exemplos típicos de constantes são caminhos para recursos, tokens e outros dados que nunca mudam durante a vida útil do script. Mas as constantes também podem ser usadas como subresultados em cálculos ou em outros locais onde qualquer informação que tenha sido coletada ou calculada não sofrerá mais alterações. Utilizar um const
, além de evitar que um valor seja alterado por engano, permite que o mecanismo JavaScript otimize o código, o que pode afetar seu desempenho.
O const
não deixa você alterar o dado atribuído, o seu escopo é bloqueado. Só trabalha com valores fixos! Variáveis declaradas com const
são ideais para valores que não devem ser reatribuídos ao longo do tempo, proporcionando maior segurança e previsibilidade no código. No entanto, é importante lembrar que const
não impede a modificação de objetos ou arrays, apenas a reatribuição do identificador da variável, o que o torna imutável é o valor de uma variável declarada com const
não poder ser reatribuído. Isso significa que após a inicialização, você não pode alterar o valor armazenado nessa variável. Você deve inicializar uma variável const
no momento em que ela é declarada. Lembrando, não é possível declarar uma variável const
sem atribuir um valor a ela imediatamente.
const pi = 3.14159; // Declaração de uma constante chamada 'pi'
console.log(pi); // Output: 3.14159
// Tentando reatribuir um valor a uma variável 'const' resultará em um erro
// pi = 3.14; // Isso causará um TypeError: Assignment to constant variable.
Obs:
const
elet
só funcionam dentro do escopo do bloco{ }
. Ou seja, são acessíveis apenas dentro do bloco{}
onde foram definidas.
Há uma outra forma de chamar uma variável, com template string, usando as crases e o cifrão com as chaves, esse placeholder concatena a frase com a variável sem a realização dos operadores aritméticos.
Exemplo:
const nome = 'Jennifer';
console.log(`O nome dela é ${nome}`); // Output: 'O nome dela é Jennifer'
Tem uma forma de fazermos variáveis input também, o método prompt()
exibe a mensagem para o usuário e recolhe o valor para aplicar na variável.
Exemplo:
const nome = prompt('Digite o seu nome: ');
console.log(`Parabéns! Você é um campeão ${nome}!`);
Já vimos como alterar o valor de uma variável ou de um item no array no JavaScript, mas posso mudar o nome de uma String
no JS? Como faço para mudar o nome de uma string no JavaScript? A resposta para essa pergunta é com uma série de métodos que alteram os valores das variáveis, veja a tabela de métodos para os valores em JS:
Método | Função do método |
replace("", "") |
muda a String selecionada por outra string informada |
toUpperCase() |
Todas as letras maiúsculas da String |
toLowerCase() |
Todas as letras minúsculas da String |
Exemplo:
var frase = "O Brasil é o melhor país do mundo!";
console.log(frase.replace("Brasil", "Estados Unidos").toUpperCase());
// Output: O ESTADOS UNIDOS É O MELHOR PAÍS DO MUNDO!
Os array (vetor) é uma estrutura de dados de uma lista ou coleção de dados que pode ser acessada por índice. Para criar um vetor vazio basta criar uma variável e atribuir [ ]
a ela. Lembrando, como já vimos em estrutura de dados e algoritmos, que o índice de um array geralmente começa com 0
e assim por diante na sua contagem da lista. Observe que o índice começa no 0
, então o primeiro item está na posição 0
, o segundo na posição 1
e assim por diante.
Exemplo: Vamos atribuir valores, você pode criar um vetor com seus valores separados por vírgula.
let vetor = [1, 22, 0, 100];
// 4 itens = indices [0,1,2,3]
// 1 === indice [0]
console.log(vetor);
Exemplo: Você pode adicionar valores de qualquer tipo no vetor e acessar os valores através de seu índice.
let vetor = [1, "Hello, World!", true, [1,2,3], '100'];
console.log(vetor[1]); // Output: Hello, World!
console.log(vetor[0]+vetor[4]); // Output: 1100
Exemplo: Podemos alterar e atribuir valores pelo índice, com o índice, você pode: Alterar um valor existente e inserir um novo valor em uma posição específica.
let vetor = [3, "Hello, World!", true, 0, false, [0,1,2,3], '100', null, undefined, NaN, (0,1,2,3)];
vetor[11] = 7; // Inserindo o valor 7 na posição 11, cujo não existia, mas foi criada após a execução.
vetor[0] = 1; // Alterando o índice na posição 0 com o valor 1
console.log(vetor) // Output: (12) [1, 'Hello, World!', true, 0, false, Array(4), '100', null, undefined, NaN, 3, 7]
Exemplo: Outra forma de inserir um array "separadamente".
numero = Array(4);
numero[0] = -2;
numero[1] = 12;
numero[2] = 4;
numero[3] = 0;
numero[4] = -1;
console.log(numero) // Output: (5) [-2, 12, 4, 0, -1]
Exemplo: Podemos organizar um array da seguinte forma.
const cars = [
"Porsche 911",
"Ferrari 488",
"Lamborghini Aventador",
"McLaren 720S",
"Ford GT"
];
console.log(cars.sort(Intl.Collator().compare));
Exemplo: Array Mod
var lista = ["maçã", "laranja", "pêra"];
console.log(`Adicionando: ${lista.push("uva")} - ${lista[3]} \n Lista atualizada: ${lista.toString()}.\n`);
Existem alguns métodos e argumentos que mudam a funcionalidade de um array, tais como:
Método | Função do método |
sort() |
|
push("value") |
Adiciona elemento |
pop("array value") |
Retira elemento |
length |
Retorna o tamanho da lista ou n° de elementos |
reduce() |
|
every() |
|
some() |
|
filter(function(currentValue, index, arr), thisValue) |
Cria um array preenchida com todos os elementos do array que passam em um teste (fornecido como uma função) |
toString(Array) |
Mostra todos os itens da lista |
find() |
|
splice() |
|
slice() |
|
join() |
Substitui elementos que separam a string |
reverse() |
Reverte |
map() |
|
forEach() |
|
concat() |
|
shift("array value") |
|
unshift("array value") |
Exemplo: Caso queira remover itens duplicados de array, use filter
para obter itens únicos de uma array.
const techs = [
'javascript',
'v8',
'v8',
'typescript',
'nodejs',
'css',
'v8',
'typescript',
'css'
]
const filteredTechs = techs.filter((tech, index) => {
return techs.indexOf(tech) === index
})
console.log(filteredTechs) // ['javascript', 'v8', 'typescript', 'nodejs', 'css']
Um objeto em JavaScript é um tipo de dado composto pelos outros tipos. Com ele, podemos organizar informações relacionadas em uma variável e os dados do objeto são acessados pelas propriedades desses objetos. Na criação, um objeto vazio é bem simples de criar { }
.
Exemplo: No caso de um objeto com propriedades (variáveis), fazemos assim. Caso você já tenha criado o objeto e queira adicionar um novo, você pode fazer de duas formas:
let veiculo = {
rodas: 4,
cor: "branco",
marca: "Hyundai",
Modelo: "Hyundai Creta",
ano: 2017,
venda: true
}
veiculo.portas = 4;
veiculo["cor"] = "vermelho";
console.log(veiculo); // Output: {rodas: 4, cor: 'vermelho', marca: 'Hyundai', Modelo: 'Hyundai Creta', ano: 2017, …}
Note que se você usar a segunda opção, precisa ter uma String
dentro dos [ ]
, a alteração de dados funciona da mesma forma.
Podemos também inserir objetos dentro de arrays, fomando Arrays de Objetos [{ }]
, você pode ter um array que contém vários objetos. Isso é útil, por exemplo, para representar uma lista de itens, onde cada item é um objeto com várias propriedades.
Exemplo: Array de objetos pessoas
.
const pessoas = [
{ nome: 'Alice', idade: 25 },
{ nome: 'Bob', idade: 30 },
{ nome: 'Carol', idade: 35 }
];
console.log(pessoas[0].nome); // Output: 'Alice'
console.log(pessoas[1].idade); // Output: 30
Podemos também fazer objetos com arrays como propriedades, você pode ter um objeto que contém arrays como valores de suas propriedades. Isso é útil para organizar dados relacionados.
Exemplo: objetos com arrays como propriedades em uma variável turma
.
const turma = {
nome: 'Turma A',
alunos: ['Alice', 'Bob', 'Carol']
};
console.log(turma.nome); // Saída: 'Turma A'
console.log(turma.alunos[1]); // Saída: 'Bob'
Além disso, podemos trabalhar com objetos aninhados em arrays, onde você pode aninhar objetos dentro de arrays e vice-versa para criar estruturas de dados mais complexas.
Exemplo: objetos aninhados em arrays com a variável escola
.
const escola = {
nome: 'Escola XYZ',
turmas: [
{ nome: 'Turma A', alunos: ['Alice', 'Bob'] },
{ nome: 'Turma B', alunos: ['Carol', 'Dave'] }
]
};
console.log(escola.turmas[0].alunos[1]); // Saída: 'Bob'
console.log(escola.turmas[1].nome); // Saída: 'Turma B'
Portanto, podemos manipular arrays e objetos, podemos facilmente adicionar, remover ou modificar elementos em arrays e objetos usando métodos e operadores JavaScript. Veja o exemplo abaixo:
// Adicionar um objeto a um array
pessoas.push({ nome: 'Dave', idade: 40 });
console.log(pessoas);
// Modificar uma propriedade de um objeto dentro de um array
pessoas[0].idade = 26;
console.log(pessoas[0]);
// Adicionar um novo aluno a uma turma
escola.turmas[0].alunos.push('Eve');
console.log(escola.turmas[0].alunos);
Podemos também usar laços de repetição, iterando sobre arrays de objetos, você pode usar loops para iterar sobre arrays de objetos e acessar ou modificar suas propriedades.
const pessoas = [
{ nome: 'Alice', idade: 25 },
{ nome: 'Bob', idade: 30 },
{ nome: 'Carol', idade: 35 }
];
pessoas.forEach(pessoa => {
console.log(`${pessoa.nome} tem ${pessoa.idade} anos.`);
});
// Output:
// Alice tem 26 anos.
// Bob tem 30 anos.
// Carol tem 35 anos.
// Dave tem 40 anos.
Existe outra forma de inserir variáveis de uma só vez e chamar elas de uma vez, com os dicionários do JS que envolvem as variáveis entre { }
. Dicionário é um termo genérico usado para descrever uma estrutura de dados que armazena pares chave-valor e permite a recuperação eficiente de valores baseados em suas chaves. Em muitas linguagens de programação, como Python, há uma estrutura de dados específica chamada "dicionário" (dict
). No JavaScript, os objetos são usados como a implementação padrão desse conceito.
Embora JavaScript não tenha uma estrutura de dados chamada "dicionário", um objeto JavaScript pode funcionar de forma muito semelhante a um dicionário em outras linguagens:
Exemplo:
var fruta = {nome: "maçã", cor: "verde"};
console.log(fruta.nome, fruta.cor);
// Output: maçã verde
Obs: Também funcionam com arrays, dessa forma
[{ }]
.
Exemplo:
var fruta = [{nome: "maçã", cor: "verde"}, {nome: 'uva', cor: 'roxa'}];
console.log(fruta[1].nome, fruta[0].cor);
// Output: uva verde
![](https://private-user-images.githubusercontent.com/61624336/341537219-cbe79d06-9676-4415-bc64-38a52e360d1b.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjYxNTk4MzYsIm5iZiI6MTcyNjE1OTUzNiwicGF0aCI6Ii82MTYyNDMzNi8zNDE1MzcyMTktY2JlNzlkMDYtOTY3Ni00NDE1LWJjNjQtMzhhNTJlMzYwZDFiLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MTIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTEyVDE2NDUzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTZiZjY0OWRmYjYwMmU5OTY4NjRlNzY0ODljMjAyN2U3YmRjM2MwNDkwMGNmMWYyMDU0MTA2N2ZhMGMyYWU3N2YmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.zFmdfAtgXyHHMEYmRmmu7L6LFVmBrfrxXcDRf-gyILY)
Estruturas de programação são os blocos básicos que compõem um programa de computador. Elas definem a forma como o código é organizado, como as instruções são executadas e como os dados são manipulados. As estruturas de programação permitem controlar o fluxo de execução e a lógica do programa.
Note que o diagrama de fluxo ao lado representa a seguinte condição: se o número A
for maior que o número B
, o algoritmo irá entender que a condição é verdadeira
e deve exibir a mensagem “o número A é maior que o número B
”, se esta condição não for atendida, ou seja, se ela for falsa
, o algoritmo não irá tomar nenhuma ação, pois ela não atende a condição.
Existem algumas categorias para as estruturas de programação, elas podem ser:
- Estruturas Iterativas: Usadas para repetir um bloco de código várias vezes até que uma condição específica seja atendida.
- Estruturas Condicionais: Usadas para tomar decisões no código com base em condições.
- Estruturas Sequenciais: Executam instruções em ordem linear, uma após a outra.
- Estruturas de Funções/Sub-rotinas: Blocos de código reutilizáveis que podem ser chamados com diferentes argumentos.
- Estruturas de Tratamento de Exceções: Usadas para lidar com erros de maneira controlada.
Aqui estão as principais estruturas de programação em JavaScript (e na maioria das linguagens de programação):
As condições são expressões que retornam um valor true
ou false
. Podem ser usadas como previsões para algum valor ou evento acionado.
O valor true
ou false
é usado para que a máquina escolha se uma expressão deve ou não ser executada. Chamamos isso de Execução Condicional.
Um exemplo é o Operador Ternário Condicional que vimos anteriormente.
Exemplo:
3 > 8 ? 'É maior' : 'É menor' // Output: 'É menor'
Ele escolhe o que irá retornar. Porém, tudo na mesma linha não é muito legível. O Operador Ternário é recomendado apenas para operações simples e curtas. Para a maioria dos casos, usaremos o comando if
(se).
Caso precise de uma segunda decisão oposta da primeira if
utilize o else
(senão). Se precisar de mais decisões utilize o else if
(senão se) que é mais indicado do que somente if
e o else
no escopo, pois eles podem gerar conflito no código!
Exemplo: Variáveis com vírgula.
var n1 = 3, n2 = 5;
if (n1 > n2) {
n1 + n2
}
else if (n1 >= n2) {
n1 / n2
}
else{
n1 * n2
}
Exemplo 2: Confirmando a quantidade de produtos com as variáveis. Note que não é necessário declarar em uma condição se o valor é true
, ele reconhece automaticamente.
let pedido = prompt('Digite quantos produtos deseja:')
let disponível = true;
let quantidade = 1;
pedido == quantidade;
if (disponível && pedido == 1){
console.log(`O produto está disponível! Há ${quantidade} unidade no estoque.`);
}
else if (disponível && pedido > 1){
console.log(`Lamentamos, mas só possuímos ${quantidade} unidade no estoque.`);
}
else{
console.log('Produto indisponível');
}
Exemplo 3: Com objeto JavaScript, onde o acesso ao sistema está liberado se a pessoa for o usuário "mundoJS", daí pode realizar o login, caso contrário o acesso será negado, e se o valor for contra o estabelecido terá o aviso de erro ao se conectar no servidor!
let pessoa = prompt('Digite seu nome:')
let objetoServidor = {
acesso: true,
login: "mundoJS"
};
let objetoServidor2 = {
erro: "Erro ao se conectar no servidor!"
};
function conexaoLogin() {
if(this.acesso && pessoa == this.login) {
return `login: ${this.login}`;
}
else if(this.acesso && pessoa !== this.login){
return 'Acesso negado!';
} else {
return this.erro;
}
}
// Usando a função com objetoServidor
conexaoLogin.call(objetoServidor,objetoServidor2); // Output: login: mundoJS
Para um grande número de condições e categorias específicas é necessário um comando mais especializado do que somente o if
, else
ou else if
, o comando switch
é ideal para essa proposta. Observe a imagem abaixo:
Exemplo:
var n1 = 3;
switch(n1) {
case 1: // if (n1 === 1)
console.log('n1 é igual a 1')
break;
case 2: // if (n1 === 2)
console.log('n1 é igual a 2')
break;
case 3: // if (n1 === 3)
console.log('n1 é igual a 3')
break;
default: console.log('n1 possui valor fora da categoria')
}
O comando break
(quebrar) serve para pausar a execução por cada case
(caso), pois senão ele executa todas de uma só vez. O comando default
funciona como se fosse o "senão" em termos de funcionalidade da declaração e sintaxe do switch case
.
Em ciência da computação, estruturas iterativas são construções de programação que permitem a repetição de um bloco de código várias vezes até que uma condição específica seja atendida. Essas estruturas são fundamentais para a execução de tarefas repetitivas de maneira eficiente. Essas estruturas iterativas são essenciais para tarefas como processamento de listas, operações de busca e ordenação, repetição de cálculos até a convergência, e muitas outras situações onde a repetição controlada é necessária.
Uma das vantagens das máquinas sobre as pessoas é que elas podem executar várias tarefas repetitivas sem se cansar e de maneira muito mais rápida. Após a tomada de decisões, outra parte básica no aprendizado da programação é a execução de repetição de comandos, os quais chamamos de Laços de Repetição (Loops). Imagine que você queira imprimir na tela a soma de todos os números de 1
a 100
, daria muito trabalho digitar tudo. E se precisássemos alterar esse 100
para 1000
? Ou 1000000
? Com um simples comando podemos fazer essa conta em um piscar de olhos com os laços de repetição.
O for
loop executa X vezes uma ação seguindo a forma como foi definido para ele faze-la. A instrução do laço for
é separada por ponto e vírgula em três partes.
Sintaxe:
for (declaração 1; declaração 2; declaração 3) {
// code block to be executed
}
Exemplo: Normalmente é a criação de uma variável de controle. A condição para encerrar o for
. Neste caso, ele executará enquanto i
for menor do que 10
, ou seja todos os números antecessores de 10
até 0
. Caso essa condição nunca se torne “false
”, teremos um loop infinito. Tenha bastante cuidado com loops infinitos, podem sobrecarregar seu navegador ou sua máquina! Final de cada repetição. Normalmente é o incremento ou decremento de 1
da variável.
for (var i = 0; i < 10; i++) { // i += 1 , i + 8
console.log(i); // Output: Imprime o número de 0 a 9
}
Exemplo: Podemos ler ou modificar todos os itens de um vetor. Nesse caso, estamos interessados em saber o tamanho da nossa lista.
let lista = ["cachorro", "gato", "galinha"];
for (let i = 0; i < lista.length; i++) {
console.log(lista[i]);
}
Exemplo: Combinando as variáveis e multiplicando os itens do array por 2
. Com isso, iremos imprimir somente os valores pares de uma contagem de 1
a 10
.
let valores = [1,2,3,4,5];
for(let i = 0; i < valores.length ; i++) {
valores[i] = valores[i] * 2;
console.log(valores[i]);
}
For in
loop serve para percorrer pelas propriedades de um objeto.
for (variável in interável) {
// bloco de código a ser executado
}
Exemplo: Nesse caso, temos um objeto JS person
, uma variável do tipo String
sem texto chamada text
e uma variável vazia chamada x
. Quando executamos o laço de repetição for(x in person)
significa que a variável x
vazia está em um objeto JS. Logo, a variável sem texto opera a soma juntamente com o objeto JS.
var person = {fname: "John", lname: "Doe", age: 25};
var text = "";
var x;
for (x in person){
text += person[x];
}
// Output: JohnDoe25
for of
loop é específico para iterar entre os elementos de uma lista. Você pode ler ele como “Para cada item de uma lista”. No exemplo abaixo, o dia começará sendo com o valor “segunda” e o último loop será “sexta”. Ele é muito importante para percorrer a lista em ordem crescente. No entanto, caso você precise trabalhar com índices ou múltiplas posições da lista, talvez seja melhor usar o for
normal.
Sintaxe:
for (variável of interável) {
// bloco de código a ser executado
}
Exemplo:
let dias = ["Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"];
for (let dia of dias) {
console.log(dia);
}
Exemplo:
for(let numero of [0,1,2,3,4,5,6,7]){
console.log(numero);
}
while
loop são laços de repetição que podem executar um bloco de código longo se a condição específica for verdadeira. O laço de repetição while
repete através de um bloco de código enquanto uma condição específica é verdadeira.
Sintaxe:
while (condição) {
// Bloco de código a ser executado
incremento++ || decremento--
}
Exemplo: Seguindo o exemplo, o código no laço de repetição vai rodar, os números de 0
a 9
, enquanto (i
) é menor do que 10
.
var i = 0;
while (i < 10) {
console.log(i); i++;
}
Do while
loop é um variante do while
. Esse loop vai executar o bloco de código uma vez, antes verificando se a condição é verdadeira, então vai repetir o loop, enquanto a condição for verdadeira.
Sintaxe:
do {
// bloco de código a ser executado
} while (condição);
Exemplo:
do {
var number = Number.parseFloat(prompt('Insira um número:'));
window.alert(`
The number entered is: ${number} \n
His predecessor is: ${number-1} \n
His sucessor is: ${number+1} \n
The double is: ${number*2} \n
The triple is: ${number*3} \n
The half is: ${number/2} \n
The square root is: ${Math.sqrt(number)}
`)
} while(number = number)
Os comandos continue
e break
servem para loops e condições, porém a diferença entre eles é na sua funcionalidade, o break
(quebrar) quebra no final da execução e assim o compilador executa outra etapa do código, já o continue
(continuar) continua até finalizar a execução.
Exemplo:
for(var i = 0; i < 5; i++){
if (i === 2){
continue;
}
console.log(i);
}
Como já vimos anteriormente, as funções (function
) são utilizadas para criarmos uma sequência de operações para serem executadas. As funções no JavaScript são de Primeira Classe, ou seja, elas podem servir de parâmetros para outras funções. Existem vários tipos de funções no JavaScript, cada uma com uma sintaxe diferente e algumas com funcionalidades diferentes, tudo vai depender do contexto do seu código.
Assim como em todas as linguagens de programação, as funções no JavaScript requerem um nível de atenção maior, visto que é uma das partes essenciais para a construção de um programa, no entanto, as funções em JavaScript têm várias peculiaridades que as distinguem de funções em outras linguagens de programação, por isso, tenha bastante atenção no que você está fazendo.
As funções possuem um corpo onde pode conter várias declarações, relacionadas aos parâmetros ou não, e retornando a saída desse corpo com a palavra-chave return
. Veja abaixo, os principais tipos de sintaxe de funções JavaScript:
Sintaxe de diferentes funções no JavaScript | ||
Function | Arrow function | Immediatly invoked function expression with Arrow Function |
function hello() {
return 'Hello, world!';
}
hello(); |
hello = () => {
return('Hello, world!');
}
hello(); |
(() => {
return('Hello, world!');
})(); |
O nome (name) das duas funções é hello
e a entrada dos dados (input/parameters/argumentos) é undefined
, note que as funções não recebem nenhum parâmetro, como indicado pelos parênteses vazios ()
. Quando você chama hello()
, não está passando nenhum argumento para a função. Portanto, no início da execução, a função hello
não tem nenhum parâmetro. Dentro do corpo da função (body), podemos fazer muitas declarações, tendo ou não haver com os parâmetros/argumentos da função, e a saída do corpo é o comando return
que devolve um valor para a função, e deve ser usado somente em funções. Caso você não coloque o return
, por padrão as funções devolvem undefined
. E, por fim, devemos chamar ou invocar a nossa função hello()
, a partir daí será exibido a saída (output) do nosso código 'Hello, world!'
. Outro ponto sobre funções é se for mais de um argumento, é obrigatório o uso de parênteses.
Algumas funções são peculiares da própria linguagem de programação JavaScript, tais como:
- Funções são cidadãos de primeira classe.
- Arrow functions e seu
this
lexical. - Contexto dinâmico de
this
. - Funções como construtores (para objetos).
- Closures e escopo léxico.
- Hoisting de funções.
- Funções anônimas e IIFEs (Immediately Invoked Function Expressions).
Exemplo: Um simples exemplo de cálculo de soma de valores.
function soma(n1,n2){
return n1 + n2;
}
console.log(soma(7,7)); // Output: 14
Exemplo: Testando o tamanho do valor inserido.
function testarTamanho(valor){
if(valor > 0){
return "maior";
}
else if(valor < 0){
return "menor";
}
else if(valor >= 3 && valor <= 3){
return "na faixa"
}
}
console.log(testarTamanho(20)) // Output: maior
Exemplo:
function inicio() {
let numbers = [39, 45, 55, 77];
for(var position = 0; position <= 3; position++){
console.log(numbers[position]);
}
}
inicio();
/* Output:
39
45
55
77
*/
Exemplo:
function inicio() {
let numbers = [39, 45, 55, 77];
for(var position = 0; position <= 3; position++){
console.log(numbers[position]);
}
}
inicio();
Um ponto bastante importante sobre funções no JS, é sobre a função anônima (Anonymous function) em JavaScript é uma função que não tem um nome associado a ela. Essas funções são frequentemente usadas como expressões de função, que podem ser atribuídas a variáveis, passadas como argumentos para outras funções, ou retornadas de outras funções.
Exemplo: função anônima atribuída a uma variável.
let funcao = function(){
console.log('Olá!');
}
funcao();
Exemplo: Criamos uma função anônima atribuída a uma variável, cuja a variável const
atribui a função somar
, onde possuimos duas variáveis como parâmetros dessa função, valor1
e valor2
.
const somar = function(valor1, valor2) {
let resultado = valor1 + valor2;
console.log(resultado)
}
somar(7,7);
somar(14,8);
somar(8,9);
Exemplo: função anônima atribuída a uma variável, semelhante ao Exemplo 2, porém com o resultado diferente.
const funcaoSomar = function(valor1, valor2) {
let resultado = valor1 + valor2;
return resultado;
}
console.log(funcaoSomar(7,7));
Exemplo:
var log = function(value){
return(value);
}
log('test');
Tradicionalmente, para fazer a função executar, você precisa chama-la com os parênteses, mas também é possível passar valores para a função acessar. No entanto, agora vamos conhecer outras maneiras de inserir funções no JavaScript. Com o arrow function (funcão flecha) é uma função que possui uma forma bem mais enxuta de ser inserida com os arrows. Elas são funções anônimas, ou seja, você só pode utiliza-las atribuindo a uma variável ou passando para outra função.
Em JavaScript, uma arrow function pode ser definida e imediatamente invocada sem a necessidade de atribuí-la a uma variável. No exemplo abaixo, a arrow function hello
é atribuída a uma variável de escopo global e depois chamada. No entanto, você também pode definir e chamar uma arrow function diretamente dentro de uma expressão.
Exemplo: Caso comum de arrow function.
hello = () => {
return "Hello, World!";
}
console.log(hello());
Exemplo: A arrow function imediatamente invocada, possui a funcionalidade de auto-execução da função assim que é utilizada.
((x, y) => {
console.log(x + y);
})(10, 5);
Veja agora, uma função anônima imediatamente invocada, em comparação ao Exemplo 2.
(function() {
return 'Hello World';
})()
Exemplo: A função Car
no seu exemplo é uma função construtora em JavaScript. Funções construtoras são usadas para criar novos objetos do mesmo tipo e são normalmente nomeadas com a primeira letra maiúscula para diferenciá-las das funções regulares.
function Car() {
this.foo = 'bar';
}
console.log(new Car());
Exemplo: Com parâmetros (return
implícito).
hello = (val) => "Hello," + " " + "World!";
console.log(hello());
// Output: Hello, World!
Mesmo exemplo acima, porém com redução de linhas:
hello = () => "Hello, World!"; console.log(hello()); // Output: "Hello, World!"
Exemplo: Sem parênteses e um argumento.
var sum = a => a;
console.log(sum(5));
Exemplo: Estamos puxando a função soma
para dentro da função calcularSoma
, onde os parâmetros a,b
são convertidos para x,y
, e assim, exibindo o resultado da função na variável.
var soma = function(a,b){
return a+b;
}
const calcularSoma = (x, y) => soma(x, y); // f(a,b)
let resultado = calcularSoma(5, 7);
console.log(resultado); // Output: 12
Toda linguagem de programação moderna possui contadores de tempo. Com o JavaScript não é diferente.
Sintaxe: No código abaixo, iniciamos uma variável data
criando uma instância JavaScript de Date
que representa um único momento no tempo. Objetos Date
são baseados no valor de tempo que é o número de milisegundos desde 1º de Janeiro de 1970 (UTC).
variável data = new Date();
console.log(data.getTime());
O JS é ótimo para manipular o tempo através de seus métodos, os métodos adiante definem o tempo no JavaScript, veja os exemplos abaixo:
Método | Função do método |
getDate() |
Define a data atual |
getFullYear() |
Define o ano atual e completo |
getYear() |
Define o ano e incompleto |
getMonth() |
Define os meses |
getDay() |
Define o dia |
getHours() |
Define as horas |
getMinutes() |
Define os minutos |
getMilliseconds() |
Define os milisegundos |
getSeconds() |
Define os segundos |
Exemplo: Retorna o ano atual.
const ano = new Date();
console.log(ano.getFullYear());
// Output: 2024
Exemplo: Retorna o dia atual.
const dia = new Date();
console.log(dia.getDate());
// Output: Dia atual
Exemplo: Aplicação front-end para manipular o tempo com um contador de final de ano.
// DOM do Tempo
const secondsContainer = document.querySelector('#seconds'); // Obter e armazenar os id's
const minutesContainer = document.querySelector('#minutes');
const hoursContainer = document.querySelector('#hours');
const daysContainer = document.querySelector('#days');
// DOM do próximo ano
const nextYearContainer = document.querySelector('#year');
const spinnerLoading = document.querySelector('#loading');
const countdownContainer = document.querySelector('#countdown');
const nextYear = new Date().getFullYear() + 1; // ano dinâmico atualizando para mais 1 ano
const newYearTime = new Date(`January 01 ${nextYear} 00:00:00`); // "template string" recebendo o ano novo
nextYearContainer.textContent = nextYear;
const insertCountdownValues = ({ days, hours, minutes, seconds}) => {
secondsContainer.textContent = seconds < 10 ? '0' + seconds : seconds;
minutesContainer.textContent = minutes < 10 ? '0' + minutes : minutes;
hoursContainer.textContent = hours < 10 ? '0' + hours : hours;
daysContainer.textContent = days < 10 ? '0' + days : days;
}
const updateCountdown = () => {
const currentTime = new Date(); // nova data
const difference = newYearTime - currentTime;
const days = Math.floor(difference / 1000 / 60 / 60 / 24); // número arredondado sem milésimos
const hours = Math.floor(difference / 1000 / 60 / 60) % 24;
const minutes = Math.floor(difference / 1000 / 60) % 60;
const seconds = Math.floor(difference / 1000) % 60;
insertCountdownValues({ days, hours, minutes, seconds});
}
const handleCountdownDisplay = () => {
spinnerLoading.remove();
countdownContainer.style.display = 'flex';
}
setTimeout(handleCountdownDisplay, 1000);
setInterval(updateCountdown, 1000);
![](https://private-user-images.githubusercontent.com/61624336/344160749-dcf18538-2a42-4c5d-b35d-0e6a6e3fc21a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjYxNTk4MzYsIm5iZiI6MTcyNjE1OTUzNiwicGF0aCI6Ii82MTYyNDMzNi8zNDQxNjA3NDktZGNmMTg1MzgtMmE0Mi00YzVkLWIzNWQtMGU2YTZlM2ZjMjFhLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA5MTIlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwOTEyVDE2NDUzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTJjYmExNzM5M2ZlZDczODc3NTRhOWY1ZTEzNmM2NDIwM2YxMGFiMGQ4NmE2MDFhNmYxZjQyMzI1MjNjM2NkZDgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.n6xuyWtfYJwHEAowGNfsLHC4bTta1N8RB_5nhVtOm-I)
Já que aprendemos todos os conceitos, funcionalidades e valores primordiais do JavaScript, está na hora de apresentar o primeiro paradigma da linguagem, a procedural. O JavaScript procedural funciona com todas as funcionalidades que já vimos de maneira organizada para a execução de um programa, vejamos o exemplo:
Exemplo:
var letter = prompt("Digite uma letra:", " "), isVower = false;
Diferente da linguagem HTML, a linguagem JavaScript corresponde à programação orientada a objetos (OOP), isto significa que todos os elementos de uma página da Web são tratados como objetos. Estes objetos são agrupados de acordo com seu tipo ou finalidade.
Seguindo a hierarquia de objetos da linguagem JavaScript, são criados os seguintes objetos ao ser carregada uma página:
window
: O objeto mais acima na hierarquia, contém propriedades que se aplicam a toda a janela. Há também um objeto desta classe para todas as "sub-janelas" de um documento com frames.
location
: Contém as propriedades da URL atual.
history
: Contém as propriedades das URLs visitadas anteriormente.
document
: Contém as propriedades do documento contido na janela, tais como o seu conteúdo, título, cores, etc.
Cada objeto existente na manipulação do JavaScript possuem propriedades (características/ atributos). Exemplo, sabemos que um documento HTML possuem título e corpo, estas características do documento podemos chamar de propriedades que existem neste documento.
A utilização de propriedades se dá acompanhada de seu objeto sendo separados por um ponto .
apenas. Abaixo, a sintaxe de utilização de propriedades:
nomeObjeto.propriedade
Além das propriedades, os objetos podem conter métodos (ações/ verbos), que são funções prédefinidas pela linguagem JavaScript que irão executar determinada operação.
nomeObjeto.método(argumento/ parâmetro)
Na sintaxe apresentada, nomeObjeto
faz referência ao objeto a ser utilizado e o qual sofrerá uma ação do método, já método é o nome de identificação do método usado e entre parênteses (argumento/ parâmetro) é a expressão ou valor opcional que será usada para alterar sobre o objeto.
Onde escrever um JavaScript? Já aprendemos algumas formas de escrever o JavaScript anteriormente. No entanto, há uma outra forma para controlar bem os objetos da linguagem! Por meio do DOM e BOM.
-
Como evento de um elemento (IMG, A, INPUT etc);
Como elemento <script> dentro de <body>;
Como função, dentro de <head>
Quando se trata de herança, o JavaScript tem somente um construtor: objetos. Cada objeto tem um link interno para um outro objeto chamado prototype. O prototype é baseado em protótipos e possui uma variável que é armazenada na referencial o __proto__
, além de utilizar uma cadeia de objetos, como o objeto constructor. O prototype pode ser acessado no console do navegador, assim como a cadeia de protótipos.
Exemplo:
console.log(document.__proto__);
Nota-se que o Object.prototype
é o único que não tem duas conexões, pois ele faz uma lista dos objetos inseridos. Esse objeto prototype também tem um atributo prototype, e assim por diante até o que o valor null
seja encontrado como sendo o seu prototype null
que, por definição, não tem prototype, e age como um link final nesta cadeia de protótipos (prototype chain).
Aprenderemos mais sobre os eventos no próximo capítulo. Veremos melhor como funciona essa hierarquia de objetos e como utiliza-las em uma página, nos próximos capítulos.
São fatos que ocorrem durante a execução do sistema, a partir dos quais o programador pode definir ações a serem realizadas pelo programa. Um evento é gerado como resultado de uma ação: Um clique, um movimento do mouse, uma seleção de texto, o abandono da página etc. A associação é realizada em HTML nos elementos que suportam eventos do tipo Event através dos atributos onEvent
.
Exemplo 1: Executando um evento
Exemplo 2: Chamada de função por evento
Quando não atribuimos o segundo valor para a variável, atribuimos ele dentro da função, observe abaixo!
Exemplo 2: Validação de Tipo (com operador ternário)
Exemplo 3: Inserindo o valor no parâmetro da função
Exemplo 4: Poder de atribuição
OBS: A ordem dos argumentos importa na função, qualquer alteração no sentido da ordem pode ocasionar um erro na execução do código.
Exemplo 5: Lazy evaluation A característica que permite podermos utilizar funções para definir valores de um argumento e a mesma só será invocada quando o argumento for indefinido.
A maneira clássica de escrever objetos literais é como o exemplo abaixo:
Observe a função abaixo:
Exemplo 2: Função com vários argumentos (método antigo do ES6)
Exemplo 3: Suponhamos que precisamos fazer uma soma com muitos algarismos em um índice.
Escreve com ...
antes do parâmetro e ele traz métodos de array para manipular os seus argumentos. Quando o rest operator é utilizado nos argumentos de uma função, além da lista de argumentos, ele também traz os métodos e propriedades de array por ser uma instância de um array.
Exemplo 3: Ele pega parâmetros restantes na função transformando o Rest em um array
Exemplo 4:
function sum(...args) {
return args.reduce((acc, value) => acc + value, 0);
}
console.log(sum(5,5,5,2,3));
Exemplo 5: Integrar uma função com a outra
const multiply = (...args) => args.reduce((acc, value)) => acc * value, 1)
const sum = (...rest) => {
return multiply.apply(undefined, rest); // método apply serve para integrar uma função com a outra
};
console.log(sum(5,5,5,2,3));
Escreve-se da mesma forma que o Rest Operator, porém seu funcionamento é diferente do Rest Operator. No sentido de que o Rest Operator pega todos os parâmetros da função e transforma em um array, no caso do Spread Operator ele pega todos os itens do array e transforma em parâmetro na segunda função.
Ele pode ser usado em Strings, Arrays, Objetos Literais e Objetos Iteráveis. Só pode usar o Spread em objetos literais não iteráveis. Que no caso é para construir novos objetos. Além disso, a ordem de cada objeto importa durante a execução! Ao construir um objeto literal a partir de outro, utilizando o spread operator, a ordem é importante pois a ordem define quais valores das chaves com o mesmo nome irão prevalecer.
A forma de combinar dois arrays utilizando spread operator: [...arr1, ...arr2];
Exemplo 6: Shallow Clone - um Subobjeto gerando um Spread
Ao trabalhar com JavaScript, em vários cenários a gente acaba pegando partes de variáveis e atribuindo a outras variáveis. No entanto, quando alteramos a variável não alteramos o objeto diretamente. O destructuring pode ser usado em nested objects (objetos aninhados).
Exemplo: Destructuring Assignment
Como fazer um destructuring assignement em um array (arr), atribuindo o valor do seu primeiro índice para uma constante teste? const [ teste ] = arr;
Exemplo: É possível combinar default function arguments com destructuring? Sim, sempre que necessário podemos utilizar os dois, respeitando as regras de ambos.
Possui uma maneira de gerar um identificador único e a forma de gerar esse identificador é invocando o Symbol
. O valor do Symbol
não é texto, uma String
, não é um número e etc. Ele é único, sem ser desenhado ou descrito e ele passa metapropriedades aos seus objetos!
Exemplo 3: Comparando identificação
Exemplo 4: Gerando propriedade privada
Você pode modificar o symbols com as suas propriedades.
Exemplo: Well known Symbols
Symbol.
Generators são funções com pausa e elas despausam valores através da interface de iteração.
Exemplo 3: Ordenando a função Generator
Exemplo 3: Ele pega parâmetros restantes na função transformando o Rest em um array
Exemplo 4:
function sum(...args) {
return args.reduce((acc, value) => acc + value, 0);
}
console.log(sum(5,5,5,2,3));
Exemplo 5: Integrar uma função com a outra
const multiply = (...args) => args.reduce((acc, value)) => acc * value, 1)
const sum = (...rest) => {
return multiply.apply(undefined, rest); // método apply serve para integrar uma função com a outra
};
console.log(sum(5,5,5,2,3));
Escreve-se da mesma forma que o Rest Operator, porém seu funcionamento é diferente do Rest Operator. No sentido de que o Rest Operator pega todos os parâmetros da função e transforma em um array, no caso do Spread Operator ele pega todos os itens do array e transforma em parâmetro na segunda função.
Ele pode ser usado em Strings, Arrays, Objetos Literais e Objetos Iteráveis. Só pode usar o Spread em objetos literais não iteráveis. Que no caso é para construir novos objetos. Além disso, a ordem de cada objeto importa durante a execução! Ao construir um objeto literal a partir de outro, utilizando o spread operator, a ordem é importante pois a ordem define quais valores das chaves com o mesmo nome irão prevalecer.
A forma de combinar dois arrays utilizando spread operator: [...arr1, ...arr2];
Exemplo 6: Shallow Clone - um Subobjeto gerando um Spread
Ao trabalhar com JavaScript, em vários cenários a gente acaba pegando partes de variáveis e atribuindo a outras variáveis. No entanto, quando alteramos a variável não alteramos o objeto diretamente. O destructuring pode ser usado em nested objects (objetos aninhados).
Exemplo: Destructuring Assignment
Como fazer um destructuring assignement em um array (arr), atribuindo o valor do seu primeiro índice para uma constante teste? const [ teste ] = arr;
Exemplo 10: É possível combinar default function arguments com destructuring? Sim, sempre que necessário podemos utilizar os dois, respeitando as regras de ambos.
Possui uma maneira de gerar um identificador único e a forma de gerar esse identificador é invocando o Symbol.
Exemplo 1: O valor do Symbol não é texto, uma String, não é um número e etc. Ele é único, sem ser desenhado ou descrito e ele passa metapropriedades aos seus objetos!
Exemplo 3: Comparando identificação
Exemplo 4: Gerando propriedade privada
Você pode modificar o symbols com as suas propriedades.
Exemplo 1: Well known Symbols
Symbol.
Generators são funções com pausa e elas despausam valores através da interface de iteração.
Exemplo 3: Ordenando a função Generator
As Promises são um conceito essencial do JavaScript. Elas estão presentes em praticamente todo o ecossistema da linguagem e possui um fluxo assíncrono. Promises são um padrão de desenvolvimento que visam representar a conclusão de operações assíncronas. Elas não eram nativas do JavaScript até o ES6, quando houve uma implementação oficial na linguagem, antes delas, a maioria das funções usavam callbacks. As promises são muito necessárias porque paralelalizam cada componente do site, ou seja, os arquivos HTML, CSS e JS funcionam de maneira paralela.
Pensamos de forma linear e sincronamente. A maioria das linguagens de programação trabalha de forma assíncrona, pois a maioria trabalha com internet e quando fazemos requisições, e essas coisas são assíncronas.
De acordo com a imagem acima você precisa calcular o tempo, que no caso são 9s de execução. As vantagens desse fluxo é que você não usará muitos casos de uso, entre outras palavras muito fluxo de código de uma vez só.
Uso de código assíncrono:
- Requests HTTP
- Leitura de arquivos
- Acesso a serviço externo
- I/O
No código assíncrono, ao invés de ter o fluxo seguindo um de cada vez, teremos na verdade todas as quatro requisições que fizemos ao mesmo tempo e o tempo total será da maior Promise, que é o tempo que demorou a maior requisição acontecer. Então, isso reduz drasticamente o tempo de execução do seu código e isso também ajuda você poder otimizar o tempo que você está tendo na hora de fazer alguma requisição de dados.
Em 2004 começaram a aparecer aplicações web, como o Gmail da Google. Ele usava uma técnica chamada AJAX (Asynchronous JavaScript And XML), a qual permite enviar e receber dados de um servidor sem ter que recarregar a página inteira, apenas os dados são trafegados e então são inseridos no meio do HTML.