Notas delicinhas de Js :3

Galera abaixo está algumas notas de JavaScript que fiz mediante ao aprendizado com o passar do tempo. Espero que gostem, e o repo está publico, então se quiser contribuir com alguma nota fique avontade! É tudo nosso! 🚀📚

Tópicos

Console log

console.log('Vamos printar algo');
console.log("print 'com aspas simples'");
console.log('print "com aspas duplas"');
console.log(1234, 56.789, 'Números');
console.log(` 'tudo isso' "é um print" ${123}`);
console.log(` 'tudo isso' "é um print" ${variable}`);

Comentários

// Comentário na linha
/*
    Comentário
    Longo
*/

Variáveis

Em váriaveis geralmente se utiliza camelCase, por exemplo: nomeVariavel

LET

  • Podem ser iniciliadas vazias
  • Seus valores podem ser alterados no decorrer do código
  • Só existe dentro do escopo em que foi criada
let nome;
nome = 'Albert';
let sobreNome = 'Einstein';

CONST

  • Não pode ser inicializada vazia
  • Seu valor não pode ser diretamente alterado (Seu endereço de memória não pode ser alterado)
  • Só existe dentro do escopo informado
const nome = 'Einstein';
const dez =  10;

VAR

  • Não utilize var
  • Utilize let ou const :)
  • Var é global, oque pode trazer problemas para sua aplicação
var teste = 'teste'

Tipos de dados primitivos

const nome = 'Einstein' // string
const numero = 10 // number
const numero = 2.5 // number
let teste // undefined
const nulo = null // null
const aprovado = true // boolean
//symbol

TYPEOF - Ver o tipo da variavél

const nome = 'Einstein'
typeof nome // string
const numero = 10
typeof numero // number
typeof nome, numer // string number

Valores por referencia

Aqui os valores trabalham como ponteiros, onde uma variavel aponta para o mesmo endereço de memória que a outra. Dessa forma quando uma variavel que faz referencia a outra for alterada, tanto a variavél ponteiro quanto a varaivel referenciada será alterada.

Confuso? Dale exemplo abaixo :)

const a = [1,2,3]
const b = a
console.log(a,b) // [1,2,3] [1,2,3]
b.push(4)
console.log(a,b) // [1,2,3,4] [1,2,3,4]
// tando 'a' como 'b' apontam para os mesmos valores

Operadores aritimeticos

Precedencia documentação

  • ( ) - Primeiro - Resolve oque está no parênteses
  • / * % - Segundo - Resolve oque aparecer primeiro desses
  • - Terceiro
  • + Quarto

Contatenação utilizando strings

console.log('Albert' +  ' ' + 'Einstein') // 'Albert Einstein'
console.log('Albert ' + 1) // 'Albert 1'

Adição e subtração

console.log(10 + 10) //20
console.log('10' + 10) // 20 Ele faz algumas conversões sozinho
console.log(20 - 10) // 10
console.log('10' - 10) // 0 Conversão novamente

Potenciação

console.log(2**2) // 4

Resto da divisão

console.log(10 % 3) // 1

Incremento decremento

let num = 10
num++ // 11
num-- // 9
++num // 11
--num // 9
num = num + 10 // 20
num += 10 // 20
num = num - 10 // 0
num -= 10 // 0
num *= 10 // 100
num **= 2 // 10000

NaN = not a number

Conversão de tipo de dados

parseInt('5') //number - 5
parseInt('5.2') //number - 5 - Remove a casa decimal
parseFloat('5.2') //number - 5.2

// Melhor maneira
Number('5') //number - 5
Number('5.2') //number - 5.2
String(50) //string - '50'

Alert

É utilizado para trazer mensagens para o usuário na tela. Porém existem jeitos mais elegantes para se fazer isso :3

Ele habita dentro do objeto window, assim como o método console.log.

  • retorna undefined
window.alert('alerta')
alert('alerta')
alert(123)

Confirm

É bem parecido com o Alert, porém neste existe botões para aceitar, então você pode aceitar ou não oque a caixa flutuante de texto diz.

  • retorna um boolean
window.confirm('mensagem')
confirm('mensagem')

prompt

Igualmente parecido com os outros dois citados anteriormente (Alert, Confirm). Aqui é possível inserir valores na caixa de texto flutuante

  • retorna uma string, então se você inserir um Number, terá que converter
window.prompt('mensagem')
confirm('mensagem')

String

É um tipo de dado que representa um texto.

typeof 'Isso é um texto' // string
typeof "Isso também é um texto" // string
typeof `Isso é um texto com números ${123}` // string
typeof 'Isso também é um texto com números ' + {123} // string

Escapar um caracter

Beleza, as vezes queremos printar esse caracter '', e se você fizer isso dará problema, pois esse caracter representa outra coisa dentro de uma string, então para isso você utiliza ele da forma abaixo:

'Barra invertida \\' // Barra invertida \
'Posso pegar a aspa \' assim' // Posso pegar a aspa ' assim

Posições / Index

Uma string tem um tamanho e cada caracter tem um posição.

Uma Srting sempre começa no index 0

 012345678
'Meu texto'

Então para obter o valor de uma determinada posição podemos fazer da seguinte forma

const meuTexto = 'Meu texto'
meuTexto[0] // M
meuTexto[1] // e
meuTexto[2] // u
meuTexto[3] //  
meuTexto[4] // t
meuTexto[5] // e
meuTexto[6] // x
meuTexto[7] // t
meuTexto[8] // o

indexOf

Usado para buscar a posição de um valor informado na String

Ele retornará a primeira posição que achar com o valor que for informado

const texto = 'teste'
texto.indexOf('e') //1
texto.indexOf('w') //-1 - Retorna -1 quando valor não é encontrado

lastIndexOf

Faz a mesma coisa que o indexOf, porém ele começa a percorrer as posições de trás para frente

const valor = 'teste'
valor.lastIndexOf('e') // 1  
valor.lastIndexOf('s') // 2

concat

Usado para juntar as coisas - Concatenar

'string' + 'string' // Primeira forma
`${umaString} mais outra string` // Forma mais utilizada
umaString.concat('outraString') // Terceira forma

Endwith

Para checar se a string acaba com o valor que você informar

Retorna um boolean

'string'.endsWith('a') // false

replace

Usado para trocar valores

'teste'.replace('s', 'x') // texte

length

Pegar o comprimento das coisas

'teste'.length //5

slice

Quando a string é fatiada pelo metodo slice, ela não tem o seu valor realmente modificado, slice apenas retorna os valores entre o intervalo que você informar.

'teste'.slice(2,4) // 's'
'teste'.slice(1,-1) // este

subString

Retorna os valores dentro de um range informado

'teste'.subString(0, 2) // te

split

Esse cara aqui consegue fatiar sua string, você informar em qual caracter ele vai fatiar e pronto :3

Retorna um array

'isso vai cortar'.split(' ') // ['isso', 'vai', 'cortar']

toUpperCase

Função utilizada para deixar em maiusculo

'teste'.toUpperCase() // 'TESTE'

toLowerCase

função utilizada para deixar em minusculo

'TESTE'.toLowerCase()

Expressões regulares

match

Usado para encontrar uma cadeia de caracteres (Regex) em uma string.

Retorna um array

//Encontrar somente as letras minusculas
'teste'.match(/[a-z]/g) // ['t', 'e', 's', 't', 'e']
//Encontrar letras minusculas e maisculas
'Teste'.match(/[a-zA-Z]/g) //['T', 'e', 's', 't', 'e']
//Encontrar números
'tenho 1 número'.match(/[0-9]/g) // [1]

search

Usado para encontrar um valor, passando como parametro uma cadeia de caracteres (Regex)

Retonar o index / posição do elemento encontrado

'Teste'.search(/s/) 2

Replace com regex

Da para utilizar as cadeias de carateres no replace também

// Trocar a primeira letra 's' para 'x'
'tesssste'.replace(/s/, 'x') // texssste
// Trocar todas as letras 's' para 'x'
'tesssste'.replace(/s/g, 'x') // texxxxte

Numbers

JavaScript faz as contas com base no padrão IEEE 754-2008. Existe sempre uma pequena imprecisão na hora de calcular numéros flutuantes abaixo de 1 (Com cadas decimais).

let num1 = 10 // number
let num2 = 10.0123012 // number

Numero para string

let num = 10 
num.toString() // '10'

Casas decimais

tofixed - Escolher quantas casas decimais aparecer

let num = 10.123124324
num.toFixed(2) // 10.12
//number.toFixed(numero_casas_decimais)

Saber se o numéro é inteiro

let num1 = 10
Number.isInteger(num1) // true

let num2 = 10.312
Number.isInterger(num2) //false -  É um Number (Casas decimais)

Saber ser é um NaN (Not a number)

const ola = 'ola'
Number.isNaN(ola) //true

const num = 10
Number.isNaN(num) //false

Padrão de calculo - IEEE 754-2008

Toma cuidado com calculos aqui, que o bixo não é tão preciso @-@

Até a nubank teve problema com isso

Tem que lascar tratativas

let num1 = 0.1
let num2 = 0.3

console.log(num1 + num2) //0.399999999999 - Aqui está a imprecisão
// Solução
console.log(parseFloat((num1 + num2).toFixed(2)) //Pouco elegante mas funciona
console.log(Number((num1 + num2).toFixed(2)) //Pouco elegante mas funciona
(num1 * 100) + (num2 * 100) / 100 // 0.4 - Muito pouco elegante, mas funciona

Math

Arrendondar numeros

Para baixo - Math.floor

Math.floor(9.123) // 9

Para cima - Math.ceil

Math.ceil(9.123) // 10

Para o mais próximo - Math.round

  • Abaixo de 50 arredonda par abaixo
  • Acima de 0.49 arredonda para cima
Math.round(0.49) // 0
Math.round(0.50) // 1

Achar maior e menor numero

let numbers = [1,2,3,4,5,6]
Math.min(numbers) //1
Math.max(numbers) // 6

Gerar numeros aleatórios

Math.random() // 0.56487434
//gerar aleatório em um intervalo
Math.random() * (max - min) + min
//exemplo
const number = Math.random()* (10 - 5) + 5 // numeros entre 5 e 10

Potenciação

Math.pow(2,2) // 4
// Mas assim também da certo
2**2 // 4

Divisão por zero

É necessário tomar cuidado, pois o JavaScript permite a divisão por zero classificando a variavel como infinity e true

10 / 0 // Infinity - true

Tratando divisão por zero

Maneira citada StackOverflow por Mike Samuel

function notZero(n) {
  n = +n;  // Coerce to number.
  if (!n) {  // Matches +0, -0, NaN
    throw new Error('Invalid dividend ' + n);
  }
  return n;
}

numerator / notZero(denominator)

Arrays

Deve tomar cuidado com atribuições diretas, isso ocasiona em ponteiros. Então tudo oque você fizer em uma variavel ira refletir na outra. Para isso existem maneiras corretas descritas abaixo para fazer a atribuição de valores.

const users = ['Albert', 'Nikola', 'Leonardo', 1, 2, 3] //Da para colocar oque quiser aqui no meio
users[0] //Albert
users[0] = 'Einstein'
users[0] // Einstein

Obter valores do array

const users = ['Albert']
users[0] // Albert

Mudando os valores do array

const users  = ['Albert']
users[0] = ['Nikola']
users[0] // Nikola

Passando valores entre arrays

Aqui é necessário ter atenção, para não referenciar diretamente um array a outra variavél. Pois dessa forma a variavel vai apontar para o mesmo endereco de memoria do array.

Exemplo

const array_1 = [1,2,3]
const array_2 = array_1

array_2[2] = 123123123

// Eles teram os mesmo valores, pois as duas variaveis apontam para o mesmo endereço de memoria
array_1 // [1,2,123123123]
array_2 // [1,2,123123123]

Uma das maneiras correta de se passar o valor do array para outra variavél

const array_1 = [1,2,3]
const array_2 = [...array_1] // maneira correta de se fazer 
array_2[2] = 123123123

array_1 // [1,2,3]
array_2 // [1,2,123123123]

Atribuição via desestruturação (Arrays)

//exemplo simples
let a
let b
let c
[a,b,c] = [1,2,3]
a //1
b //2
c //3

//desestruturação
const numbers = [1,2,3,4]
const [first, second, ...rest] = numbers
first // 1
second // 2
rest // [3, 4]

//pulando valores
const [number1 , , number3] = numbers
number1 // 1
number3 // 3

Esses ... que está antes de array_1 [...array_1] significa que todo o valor de array_1 será espalhado, e como no caso a variável array_2 está recebendo [...array_1], significa que o valor de array_1 será espalhado dentro de array_2.

Comprimento do array - length

const users = ['Albert', 'Nikola', 'Leonardo']
users.length //3

Inserir valores no array - push/unshift

const users = ['Albert', 'Nikola']

//Inserir no final
users.push('Leonardo')
users // ['Albert', 'Nikola', 'Leonardo']

//Inserir no começo
users.unshift('Thomas')
users // ['Thomas', 'Albert', 'Nikola', 'Leonardo']

Romover valores do array - pop/shift/delete

const users = ['Albert', 'Nikola', 'Leonardo']

//Remover do final
// pop retorna o valor removido
users.pop()
users // ['Albert', 'Nikola']

//Remover do começo
//shift retorna o valore removido
users.shift()
users // ['Nikola']

//Remover item deixando espaço vazio
delete users[0]
users // [<emptyitem>]

Fatiar um array - slice

Quando o array é fatiado pelo metodo slice, ele não tem o seu valor realmente modificado, slice apenas retorna os valores entre o intervalo que você informar.

const users = ['Albert', 'Nikola', 'Leonardo'] 
users.slice(0,2) // ['Albert' , 'Nikola']
users.slice(0,-1) // ['Albert', 'Nikola', 'Leonardo'] 

-1 Inidica a última posição do array

Checkar instancia de array

const users = ['Albert', 'Nikola']
users instanceof Array // true

Retirar valores de um determinado range - Splice

Esse método retira os valores do range que você selecionar. Com isso você pode descartar esses valores ou utiliza-los posteriormente.

// array.splice(posicao_inicial, quantidade_elementos_a_deletar, addElement, addElement, addElement)
const array = [1,2,3,4,5]
const elementos_removidos = array.splice(3,2)
array // [1,2,3]
elementos_removidos // [4,5]

//Example utilizando MAX_VALUE
const array = [1,2,3,4,5]
const elementos_removidos = array.splice(2, Number.MAX_VALUE)
elementos_removidos // [3,4,5]

//Adicionando valores com splice
const array = [1,2,3,4,5]
array.splice(3,0,'value')
array // [ 1, 2, 3, 'value', 4, 5 ]

//Removendo e adicionando ao mesmo tempo
const array = [1,2,3,4,5]
array.splice(3,2,'Albert', 'Nikola')
array // [1,2,3,'Albert', 'Nikola']

Concatenar array

const array1 = [1,2,3,4]
const array2 = [5,6,7,8]

array1.concat(array2) // [1,2,3,4,5,6,7,8 ]

Filtrar o array

Sempre retorna um array

//forma classica
const array = [1,2,3,4,5]

function callBackFilter(value, index, array){
    return value > 2; 
}

const newArray = array.filter(callBackFilter)
newArray // [3,4,5]

//Forma mais elegante
const array = [1,2,3,4,5]

const newArray = array.filter(value => value > 2)
newArray // [3,4,5]

//Da para fazer assim também
const array = [1,2,3,4,5]

const newArray = array.filter((value, index, array) => {
    // use value index array logic
    //return 
})

Mapear o array

Esse método permite passar por todas as posições do array. É bem parecido com um for, você também pode colocar sua lógica para ser executada em cada posição.

Sempre retorna um array

const array = [1,2,3]

array.map((value,index,array) => {
    return value
})

// Exemplo - retonar um novo array que valores dobrados
const array = [1,2,3]
const newArray = array.map(value => value * 2)
newArray // [2,4,6]

// Exemplo - Retornar apernas o nome dos objetos
const peoples = [
    {name: 'Albert', surname: 'Einstein'},
    {name: 'Nikola', surname: 'Tesla'}
]

const arrayWithNames = peoples.map(value => value.name)
arrayWithNames // ['Albert', 'Nikola']

Reduce

Permite você passar por todas as posições, e também ter um único retorno. Por exemplo fazer a soma de todos os valores dentro do array, aqui teremos um unico retorno que será o valor total.

Reduzir array a um elemento

// Exemplo de soma
const array = [1,2,3]
const total = array.reduce(function(acumulador, valor, indice, array){
    acumulador += valor
    return acumulador
})
total // 6

// Exemplo de retorno de array
const array = [1,2,3]
const anotherArray = array.reduce(function(acumulator, value ){
    acumulador.push(value)
    return acumulador
}, [] )// Valor inicial do acumulador)
anotherArray // [1,2,3]

// Exemplo - Retornar o mais velho
const pessoas = [
    {name: 'Albert', age: 76},
    {name: 'Nikola', age: 86},
    {name: 'Isaac', age: 84}
]

const pessoaMaisVelha = pessoas.reduce(function(acumulador, valor){
    // O acumulador sempre inicia pegando o valor da primeira posição
    // O 'Valor' sempre inicia pegando o valor da segunda posição
    if (acumulador.age > valor.age) return acumulador
    return valor
})

pessoaMaisVelha // {name: Nikola, age: 86}

Foreach

Apenas passa sobre o array, assim como um for clássico

const array = [1,2,3]
array.forEach((value, index, array) => {
    //logic
})

Funções

Criar função - function

Funções podem ter retornos ou não, assim como parametros

//Quando se declar uma função da maneira abaixo, a função poderá ser chamada em qualquer lugar do código - Efeito Hosting
//Escopo básico de função
function name (parameters) {
    //logic
}

// Função com retorno
function teste(){
    return alert('teste')
}

Arrow function

É a mesma coisa que a função normal, porém ela veio para deixar o código mais elegante

//Escopo básico
(parameters) => {logic}

//example
//Aqui como é uma linha não precisa de return, o return é automatico
(num) => num ** 0.5
//or
num => num ** 0.5
//or
const raiz = num => num ** 0.5

Parametros de função

//Pegar parametro via desestruturação de objeto
const obj = { name: 'Albert', surname: 'Einstein'}

//Pegando somente o nome
function getName({name}) {
    console.log(name)
}
getName(obj) // Albert

//Pegar valores via desestruturação de um array
const array = [1,2,3,4]

const getThreeFirstNumbers = ([num1,num2,num3]) => {
    console.log(num1,num2,num3)
}
getThreeFirstNumbers(array) // [1,2,3]

// Função com valores padrões. Funciona também para desestruturação
function soma(x=10, y=20){
    return x + y
}

Parametros de resto - Rest operator

O parametro de resto deve ser o ultimo parametro da funcão

//Rest operator
const a = 1
const b = 2
const c = 3
const d = 4
const e = 5

function example(a,b,...rest){
    console.log(a,b,rest)// 1 2 [3,4,5]
}

example(a,b,c,d,e)

Funções dentro de uma variavel - Function expression

const sayHello = function () {
    console.log('Hello')
}
// or
const sayHello = () => console.log('Hello')

Passando função como parametro

const sayHello = () => console.log('Hello')
sayHello()

Arguments

Arguments em functions

Funciona apenas em function e não em arrow function. Para fazer funcionar de forma semelhante em arrow function, utilize o rest operator

function soma (){
    let total = 0
    //dentro de arguments, se encontra todos os valores
    for (let argument of arguments){
        total += Number(argument)
    }
    return total
}
//Vai somar todos esses valores 
soma(1,2,3,4,5,123,123,4,56,7,23,8)

Closures - Function dentro de function

Habilidade da função acessar seu escopo léxico (Onde foi definida)

function multiplica(multiplicador){
    return function(n){
        return n * multiplicador
    }
}

const duplica = multiplica(2) // Recebe a função dentro da função, por conta do return
duplica(4) // 8

Função de callback

Passar funções para ser executadas após outras funções. É bem semelhante ao exemplo mais acima

const first = (callback) => {
    console.log('first')
    if (callback)
        callback()
}
const second = (callback) => {
    console.log('second')
    if (callback)
        callback()
}
const third = (callback) => {
    console.log('third')
    if (callback)
        callback()
}

first(() => second(() => third())) // first second third

IIFE - Immediately invoked function expression

A função é executada assim que é invocada

// Escopo classico
(function (parameters){
    // logic
})(parameters);
// Escopo com arrow function
(() => {
    //logic
})()
//exemplo
(() => console.log('teste'))()

Funções geradoras

Entrega um valor por chamada. Quando se utilizar [return] a função geradora será parada

A funcão geradora podem usar *

function* geradora1() {
    // ... Lógica
    yield 'valor1'
    // ... Lógica
    yield 'valor2'
    // ... Lógica
    yield 'valor3'
}

const valorGerado = geradora1()
valorGerado.next() // valor 1
valorGerado.next() // valor 2
valorGerado.next() // valor 3

//Exemplo de delegação
function geradora2(){
    //Delega a primeira chamada a geradora 1
    yield* geradora1()
    yield 4
    yield 5
    yield 6
}

//Consultar os valores da função geradora
const valores = geradora2()
for (value of valores){
    console.log(valores)
}

//Utilizando chamadas de funções em sequencia com funções geradoras
const function_1 = () => console.log('function 1')
const function_2 = () => console.log('function 2')

function functionsSequence(){
    yield function_1()
    yield function_2()
}

const callInSequence = functionsSequence()
callInSequence.next() //function_1
callInSequence.next() //function_2

Funções recursivas

Função que chama ela mesma

//Fará o laço de repetição 5 vezes
const recursive = (max) => {
    if (max >= 5)
        return
    max++;
    recursive(max)
}
recursive(0)

Objetos

Lembrete - Quando for criar um metodo que se repete em cada objeto, é bem mais performatico utilizar o prototype. Para que o metodo seja criado em apenas um lugar ;)

Criar objeto

// Criação literal - Dicionario
const pessoa = {
    nome: 'Albert',
    sobrenome: 'Einstein'
}
// or
const pessoa = new Object()
pessoa.nome = "Albert"
pessoa.sobrenome = "Einstein"

Acessar valores do objeto

const people = {
    name: 'Albert',
    surname: 'Einstein'
}

people.name // Albert
people['name'] // Albert

Atribuição via desestruturação (Objetos)

const awesomePeople = {
    name: 'Albert',
    surname: 'Einstein',
}

const {name, surname} = awesomePeople
// com valores padrões, para caso os valores não existam no objeto
const {name='Albert', surname='Einstein'} = awesomePeople
//mudar o nome das variaveis para não seguir os nomes dos atributos dos objetos
const {name: sayYourName, surname: sayYourName} = awesomePeople
sayYourName // 'Albert'
sayYourSurname // 'Einstein'

//another example

const people = {
    name: 'name',
    address: {
        street: 'california',
        number: 124
    },
    age: 10
}

const {name, address:{street}, ...rest} = people
name // 'name'
street // 'california'
rest // age: 10

Fabrica de objetos

// forma padrão
function criaPessoa (name, surname){
    return {
        name,
        surname,
        getAllName: () => `${this.name} ${this.surname}`
    }
}

//Se os parametros tiverem os mesmos nomes dos atributos, ficara dessa forma.

//Equivalente a forma de cima
function criaPessoa (nome, sobrenome){
    return {
        nome,
        sobrenome
    }
}

Factory Functions

Funções fabricas

const createPeople = (name, surname) => {
    return {
        name,
        surname,
        sayHello: () => {
            //This sempre se refere ao objeto chamado
            return `Hello! I'm ${this.name}.`
        }
    }
}

const people = createPeople()
people.sayHello()

Utilizando Getter

createPeople = (name, surname, age) => {
    name,
    surname,
    age,
    get completeName(){
        return `${this.name} ${this.surname}`;
    }
}

const people = createPeople('Albert', 'Einstein', 76 )
people.compleName // Albert Einstein

Utilizando Setter

createPeople = (name) => {
    return {
        name,
        surname: '',
        set setSurname(surname){
            this.surname = surname
        }
    }
}

const people = createPeople('Albert')
people.setSurname = 'Einstein'
people.surname // Einstein

Contructor functions

É interessante iniciar com letra maiuscula por convenção.

function Pessoa(nome, sobrenome) {
    //Atributos privados
    const id = 1;
    //metodos privados
    const metodo_privado = () => {}
    //Atributos publicos
    this.nome = nome;
    this.sobrenome = sobrenome;

    this.metodo = function (){

    };
}

const pessoa1 = new Pessoa('Albert', 'Einstein')
const pessoa2 = new Pessoa('Nikola', 'Tesla')

Congelar objeto - freeze

Não permitir alteração no objeto.

//Congelar na criação
function People(name, surname) {
    this.name = name
    this.surname = surname

    Object.freeze(this)
}

//Congelar depois da criação
function People(name, surname) {
    this.name = name
    this.surname = surname
}

const people = new People('Albert', 'Einstein')
Object.freeze(people)

Métodos do objeto

const pessoa = {
    nome,
    sobrenome,

    falar(){
       console.log('Hello World!') 
       console.log(`i'm ${this.nome}!`)
    },

    pular(){
        console.log(`${this.nome} pulou!`)
    }
}

Propriedades do objeto

Apenas um atributo

function People (name, surname){
    this.name = name
    this.surname = surname

    Object.defineProperty(this, 'surname', {
        enumerable: true, // show key
        value: surname, // show value
        writable: false, // update
        configurable: true, // reset configurations
    })
}
const people = new People('Albert', 'Einstein')

Todos os atributos

function People (name, surname){
    this.name = name
    this.surname = surname

    Object.defineProperties(this, {
        name : {
            enumerable: true, // show key
            value: name, // show value
            writable: false, // update
            configurable: true, // reset configurations
        },
        surname: {
            enumerable: true, // show key
            value: surname, // show value
            writable: false, // update
            configurable: true, // reset configurations
        }
    })
}

const people = new People('Albert', 'Einstein')
Object.keys(people) // name, surname

Propiedades do objeto com getters e setters

function People (name, surname){
    this.name = name
    // let surname = surname
    Object.defineProperty(this, 'surname', {
        enumrable: true,
        configurable: true,
        get: function() {
            return surname
        },
        set: function(value) {
            if(typeof value !== 'string')
                throw new TypeError('message')
            surname = value
        }
    })
}

const people = new People('Albert', 'Einstein')
people.surname // 'Einstein'
people.surname = 1 // Error :)

Metodos uteis para objetos

Copiar objeto

const people = {name: 'Albert', surname: 'Einstein'}
//example 1
const copyPeople = {...people, age: 76}
//example 2
const copyPeople = Object.assign({}, people, {age : 76})

people // {name: 'Albert', surname: 'Einstein'}
copyPeople // {name: 'Albert', surname: 'Einstein', age: 76}

Checar como estão as propiedades do objeto

const people = {name: 'Albert', surname: 'Einstein'}
Object.getOwnPropertyDescriptor(people, 'name') /*
    {value: 'name',
    writable: true,
    enumerable: true,
    configurable: true}
*/

Pegar o valor do objeto

const people = {name: 'Albert', surname: 'Einstein'}

Object.values(people) // ['Albert', 'Einstein']

Pegar valor do objeto com entries

Retorna um array com os valores do objeto

const people = {name: 'Albert', surname: 'Einstein'}
console.log(Object.entries(people)) // ['name', 'Albert'], ['surname', 'Einstein']

Prototypes

Cara é muito bom! Cria uma função apenas para todos os objetos. Mantendo assim uma melhor performance.

function People(name, surname){
    this.name = name
    this.surname = surname
}

People.prototype.completeName = function(){
    return `${this.name} ${this.surname}`
}

Manipulação de prototype

const object_A = { keyExample_A: 'ExampleA'}
const object_B = { keyExample_B: 'ExampleB'}

// O object_A vai ser o protótipo do object_B
Object.setPrototypeOf(object_B, object_A)
object_B.keyExample_A // 'ExampleA'

Criando objeto pelo prototype

function People(name) {
    this.name = name
    People.prototype.getName = function (){
        return `Here return name`
    }
}

const example = Object.create(People.prototype, {
    newKey: {
        writable : true,
        configurable: true,
        enumerable : true,
        value: 'example'
    }
})

example // People {newKey: 'Example'}
example.getName() // Here return name

Herança

function Produto(nome, preco){
    this.nome = nome
    this.preco = preco
}
Produto.prototype.aumento = function(quantia){
    return this.preco += quantia
}

function Camiseta(nome, preco, cor){
    //Onde a herança acontece
    Produto.call(this, nome, preco)
    this.cor = cor
}

//Setar o mesmo prototype do produto
Camiseta.prototype = Object.create(Produto.prototype)
// Para setar o objeto como uma Camiseta, senão vai ficar como produto
Camiseta.prototype.constructor = Camiseta
// Camiseta se torna uma especialização de produto

const camiseta = new Camiseta('Camiseta', 100, 'Azul')
camiseta.aumento(10)
camiseta.preco // 110
//Para reescrever um metodo do pai
Camiseta.prototype.aumento = function(parameters){
    //logic
    //Quando aumento for chamado, ele fará oque essa função pedir, em vez de fazer oque o pai está passando
}

Polimorfismo

Fazer uma classe filha se comportar de forma diferente do pai (Sobreescrita de métodos)

Factory Functions + Prototype

function createGenius(name, surname) {
    const pessoaPrototype = {
        sayHello (){
            console.log('Hello')
        }
    }

    return Object.create(pessoaPrototype, {
        name: {value: name},
        surname: {value :surname}
    })
}
const people = createGenius('Albert', 'Einstein')

Composing / Mixing

const sayHello = {
    sayHello () {
        console.log(`Hello i'm ${this.name}!`)
    }
}

const peoplePrototype = {...sayHello}
// const peoplePrototype =  Object.assign({}, sayHello)

function createGenius(name, surname) {
    return Object.create(peoplePrototype, {
        name: {value: name},
        surname: {value: surname}
    })
}

const people = createGenius('Albert', 'Einstein')

Object map

const genius = [
    {name: 'Albert', surname:'Einstein'},
    {name: 'Nikola', surname: 'Tesla'},
    {name: 'Charles', surname: 'Darwin'}
]

const newGenius = new Map()
for (const people of genius) {
    const {name} = people
    newGenius.set(name, {...people})
}
console.log(newGenius)
console.log(newGenius.get('Albert'))

Class

Cara que maravilha linkar os prototypes aqui

class People {
    constructor(name, surname){
        this.name = name,
        this.surname = surname
    }

    sayHello(){
        console.log(`Hello i'm ${this.name}!`)
    }
}
const people = new People()

Getter & Setter

const _velocity = Symbol('Velocity')
class Car {
    constructor(name){
        this.name = name
        this[_velocity] = 0
    }

    get velocity(){
        return this[_velocity]
    }
    
    set velocity(value){
        if (typeof value !== 'number') return
        if (value >= 100 || value <= 0) return

        this[_velocity] = value
    }
}

const car = new Car('Fusca')
car.velocity = 50
car.velocity // 50 

Herança com classes

class Genius{
    constructor(name){
        this.name = name
    }

    sayHello(){
        console.log('Hello')
    }
}

class People extends Genius{
    constructor(name, age){
        super(name) //Construtor pai
        this.age = 76
    }

    //Sobre escrever o metodo da classe pai
    sayHello(){
        console.log("I'm another hello")
    }
}

Metodos estaticos

Acessa a classe sem instanciar a classe

class Genius{
    constructor(name){
        this.name = name
    }

    //metodo de instancia
    sayHello(){
        console.log('Hello')
    }
    //metodo estatico
    static sayHelloToEverybody(){
        console.log('Hello world!')
    }
}

Genius.sayHelloToEverybody() // Hello world

Valores primitivos e por referencia

Valores primitivos (imutaveis)

Esses valores criam uma nova cópia quando são copiados

  • string
  • number
  • boolean
  • undefined
  • null
  • bigint
  • symbol
// Não da para mudar fazendo isso
let a = 10
a[0] = 20 //Isso não muda o valor
a // 10

Valores do referencia (mutavel)

Esses valores apontam para o mesmo lugar da memória quando são copiados

  • Array
  • Object
  • Function
//Da para mudar seus valores
const teste = [1,2,3]
teste[0] = 50
teste // [50,2,3]

JavaScript Lógica de programação

Operações de comparação

  • > Maior que
  • < Menor que
  • > Maior ou igual que
  • <= Menor ou igual que
  • == Igualdade
  • === Igualdade estrita - Checa valor e tipo (Recomendado)
  • != Diferença
  • !== Diferença estrita - Checa valor e tipo (Recomendado)

Operadores lógicos

  • && (and - e)
  • || (or - ou)
  • ! (not - negação)

And - Para a comparação lógica ser verdadeira, todas as outras comprações devem ser verdadeiras

Or - Para a comparação lógica ser verdadeira, pelo menos uma das comparações devem ser verdadeiras

! - Nega a operação lógica

Exemplo

//&& - And - Todas devem ser verdadeiras
0 === 0 && 1 === 1 //true
0 === 0 && 1 === 2 //false

//|| - Or - Pelo menos uma dever ser verdadeira
0 === 0 && 1 === 1 //true
0 === 0 && 1 === 2 //true
0 === 1 && 1 === 2 //false

//! - Negação
true //true
!true //false

false //false
!false //true

!!false //false
!!!false //true

Avaliação de curto circuito (Short-circuit)

Retorno de valores e operações lógicas

Valores que avalião em false

  • false
  • 0
  • ''
  • null
  • undefined
  • NaN

Operador && and

false - Retorna o valor falso quando for encontrado

true - Sempre retornará o ultimo valor avaliado

//false
'Luiz Otavio' && 0 && 'Maria' // 0 pois 0 avalia em falso
//true
'Luiz' && 'Albert' && 'Maria' // Maria - Retorna o ultimo valor avaliado

Operador || or

Retorna o primeiro valore verdadeiro encontrado

Caso não haja valor verdadeiro, retorna o ultimo valor falso encontrado

false || false || 'Albert' || true // 'Albert' - Pois Albert é o primeiro resultado verdadeiro encontrado

Exemplos de validação

const cor = ''
const corPadrao = cor || '#fcfcfc'
corPadrão // '#fcfcfc' - Pois '' é avaliado como false

Estruturas condicionais

if else if e else

  • If pode ser utilizado sozinho
  • Para se usar else, é necessário ter um if antes
  • Pode haver vários if else
  • Só pode haver um else na checagem
  • Não é necessário ter else/else if
//estrutura simples
if (true)
    return 'verdadeiro'
else
    return 'falso'

//estrutua composta
if (true)
    return 'verdadeiro'
else if (false)
    return 'falso'

//exemplo
const num = 10

if (num > 9){
    console.log(num)
    console.log('Numero maior que 9')
} else if (num === 10) {
    console.log(num)
    console.log('Numero igual a 10')
} else if (num < 5) {
    console.log(num)
    console.log('Numero menor que 5')
} else {
    console.log(num)
    console.log('Numero entre 9 e 5')
}

Avaliação por curto-circuito

É utilizada para tomar uma ação somente quando a condição for verdadeira. Esse método de avaliação não aceita else.

condition && trueLogic
//Exemplo
1 === 1 && console.log('True') // true

Operação ternario

Esse é delinha!

Pode substituir parte do código com condicionais mais simples

condition ? true : false
//example
5 > 10 ? 'Maior' : 'Menor'

Objeto date

const data = new Date() // Data atual por padrão
new Date(0) // 01/01/1970 - Timestamp unix ou época unix
new Date(2019, 3, 20, 15, 14, 27, 500) // 2019/4/20 - 15:14:27:500
new Date('2019-04-20 20:20:59')
Date.now() //Data atual em milesimos de segundos
new Date(Date.now()) // Data atual
//data.toString()

Obter ano, mes, dia, horas, minutos, segundos, milesimos

const data = new Date()
data.getFullYear() //ano
data.getMonth() //mes - Começa do zero
data.getDate() //dia
data.getHours() //horas
data.getMinutes() //minutos
data.seconds() //segundos
data.getMilliseconds() //milesimos
data.getDay() //dia da semana - 0 Domingo - Sábado

Formatar data

const data = new Date()
data.toLocaleTimeString('pt-BR', {
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false
}) // 00/00/00 00:00:00

Switchs

switch (variable){
    case condition:
        //logic
        break
    case condition:
        //logic
        break
    default:
        //logic
        break //Não tem necessidade
}

Estrutura de repetição

  • For clássico - Geralmente com iteráveis (Array ou string)
  • For in - Retorna o indice ou chave (string, array, objetos)
  • For of - Retorna o valor (iteráveis, arrays ou string)

For

for (let i = 0; i > length; i++){
    //logic
}

For in

const names = ['Albert', 'Nikola', 'Thomas']
for (let index in names){
    // first enter
    index //1
    // Second enter
    index // 2
}

const people {
    name: 'Albert',
    surname: 'Einstein'
}

for (let key in people){
    //first enter
    console.log(people[key]) // Albert
    //second enter
    console.log(people[key]) //Einstein
}

For of

for (let value of list){
    //logic
}

//example
const peoples = [
    {name: 'Albert'},
    {name: 'Nikola'},
    {name: 'Thomas'},
]

for (let people of peoples){
    //first
    people // {name: Albert}
    //Second
    people // {name: Nikoa}
    //third
    people // {name: Thomas}
}

While

Checa a condição e depois entra no laço de repetição

while (i <= 10){
    //logic
    i++;
}

Do while

Entra pelo menos uma vez no laço e depois checa a condição

do {
    //logic
} while (condition)

Break e continue

Controle do laço. Funciona em todos os laços

  • Break - Parar o laço
  • Continue - Passar o laço para a próxima entrada

Continue

const nums = [1,2,3]

for (let num of nums){
    //pulando o console.log do número dois
    if (num === 2)
        continue
    console.log(num)
}

Break

const nums = [1,2,3]

for (let num of nums){
    //Parando o laço quando encontrar o número dois
    if (num === 2)
        break
}

DOM - Document object model

Estrutura básica do DOM

Window > Document > Html > Head | Body

O Dom possui uma api que nos permite interagir com ele. Podemos criar e modificar os dados que estão dentro dele

Seletores

Selecionar elemento

document.getElementById('id')
document.querySelector('#id') //mais moderno
document.querySelector('.class') //mais moderno

Selecionar mais de um elemento

documet.querySelectorAll('element')
// Exemplo
const elements = document.querySelectorAll('p')
elements // NodeArray p's

// Outro exemplo
const container = document.querySelector('.container')
container.querySelectorAll('p') // Get all p's inside in container

// Selecionar com contains
container.classList.contains('class')

Buscar pai de um elemento

const element = document.querySelector('p')
element.parentElement // elemento pai

Remover elemento

const element = document.querySelector('element')
element.remove()

remover pai do elemento

const element = document.querySelector('element')
element.parentElement.remove()

Pegar o texto de um elemento

const element = document.querySelector('element')
element.innerText //Return text

Eventos e listeners

Adicionar listener a um elemento

const input = document.querySelector('.input')
input.addEventListener('event', function(event){
  //logic  
})

// Exemplo 
const input = document.querySelector('.input')
input.addEventListener('click', () => console.log('teste'))

Selecionar element via evento

document.addEventLister('click', (event) => {
    const element = event.target
})

Criar elemento

document.createElement('element')
//example
const p = document.createElement('p')
p.classList.add('class-name')
p.innerHTML += 'text'

//Exemplo de criação de nó de texto
const textNode = document.createTextNode('text')
p.appedChild(textNode) // inserir o texto na tag p

Inserir dados a elemento

const example = document.querySelector('#id')
example.innerHTML = 'html'
axample.innerText = 'text'

Inserir filhos em um elemento

  • appendChild(element)
const example = document.querySelector('#id')
//criar p
const p = document.createElement('p')
//Adicionar class a p
p.classList.add('class-name')
//Adicionar p dentro de example
example.appendChild(p)

Pegar estilos de elementos

const styleBody = getComputedStyle(document.body) // pegar estilo do body
// Pegar o background 
styleBody.backgroundColor // 'ffffff'

Mudar estilos de um elemento

//Exemplo de mudança de cor
const element = document.querySelector('.class')
element.style.backgroundColor = 'red' // mudar a cor

Try Catch finally

try{
    // Execuçãoq uando não há erros
} catch (err){
    // Execução caso haja erro
} finally{
    // Sempre executado
}

Errors

throw new Error('message')
// Example
const number = 'text'
if (typeof number !== 'number')
    throw new Error('Precisa ser número')

Interval e Time outs

setInterval

Executa função em um periodo de tempo definido

setInterval(function, milliseconds)
//example
setInterval(() => console.log('teste'), 1000)

setTimeout

Define um tempo de expiração para um intervalo

//Criando uma função para executar em um intervalo
const interval = setInterval(() => console.log('teste'), 1000)

//Definindo o intervalo de 5 segundos para a função
setTimeout(() => {
    clearInterval(interval)
}, 5000)

JSON

Passar para json

const tasks = [1,2,3,4]
const tasksJson = JSON.stringify(tasks)
tasksJson = [] // '[1,2,3,4]'

Passar Json para um objeto JavaScript

const tasks = [1,2,3,4]
const tasksJson = JSON.stringify(tasks)
tasksJson = [] // '[1,2,3,4]'

const realTasks = JSON.parse(tasksJson)
realTasks // [1,2,3,4]

LocalStorage

Base de dados do navegdor

Salvar no localStorage

localstorage.setItem('name', string)
//Exemplo
const array = [1,2,3]
const arrayJson = JSON.stringify(array)
localStorage.setItem('array', arrayJson)

Buscar dados

localStorage.getItem('name-item')

Deletar do localStorage

localStorage.removeItem('keyName')

Promise

  • Pending
  • fullfilled - Resolvida
  • Rejected

Execução em pararélo, assincrono

Muito utilizado em conexões com banco de dados e chamadas em API. Esse método é utilizado quando não sabemos a hora correta que vamos receber um retorno da requisição feita. Então é retornado uma promessa de resultado, e podemos usar métodos para esperar essa promessa ser cumprida.

//Example - Modelo classico
function esperaAi(msg, tempo) {
    return new Promise((resolve, reject) => {
        if (typeof msg !== 'string') {
            reject('Valor incorreto')
            return
        }
        setTimeout(() => {
            resolve(msg)
        }, tempo)
    })
}

esperaAi('Frase 1', 1000)
    .then(resposta => {
        console.log(resposta)
        return esperaAi('Frase 2', 1000)
    })
    .then(resposta => {
        console.log(resposta)
    })
    .catch(e => {
        console.log('Erro: ',e)
    })

Métodos uteis para promisses

Promise.all

Resolve promessas em sequencia e retorna um array com os resultados

function esperaAi(msg, tempo) {
    return new Promise((resolve, reject) => {
        if (typeof msg !== 'string') {
            reject('Valor incorreto')
            return
        }
        setTimeout(() => {
            resolve(msg)
        }, tempo)
    })
}

promisses = [
    esperaAi('Frase 1', 1000),
    esperaAi('Frase 2', 1000),
    esperaAi('Frase 3', 1000),
]

Promise.all(promisses)
    .then(valor => console.log(valor))
    .catch(error => console.log(error))

// ['Frase 1', 'Frase 2', 'Frase 3']

Promise race

Retorna o primeiro valor que for resolvido

function esperaAi(msg, tempo) {
    return new Promise((resolve, reject) => {
        if (typeof msg !== 'string') {
            reject('Valor incorreto')
            return
        }
        setTimeout(() => {
            resolve(msg)
        }, tempo)
    })
}

promisses = [
    esperaAi('Frase 1', 1000),
    esperaAi('Frase 2', 5000),
    esperaAi('Frase 3', 500),
]

Promise.race(promisses)
    .then(valor => console.log(valor))
    .catch(error => console.log(error))

Promise resolve e reject

Retorna uma promise resolvida ou a rejeição dela

  • Resolve = Quando da tudo certo
  • Reject = Quando da ruim
function emCache(){
    const cache = true

    if (cache){
        return Promise.resolve('Em cache!')
    } else {
        return Promise.reject('Página sem cache')
    }
}

emCache()
    .then(mensagem => console.log(mensagem))
    .catch(mensagem => console.log(mensagem))

Async await

Método para facilitar resolver promessas de modo sincrono

O await é tudo de bom!

function esperaAi(msg, tempo) {
    return new Promise((resolve, reject) => {
        if (typeof msg !== 'string') {
            reject('Valor incorreto')
            return
        }
        setTimeout(() => {
            resolve(msg)
        }, tempo)
    })
}

// É necessário utilizar com funções
async function executa(){
    // Para capturar as rejeições é necessário utilizar try catch
    try{
        const frase1 = await esperaAi('Frase 1', 1000)
        console.log(frase1)
        const frase2 = await esperaAi('Frase 2', 2000)
        console.log(frase2)
        const frase3 = await esperaAi('Frase 3', 500)
        console.log(frase3)
    } catch(e) {
        console.log(e)
    }
    
}
executa()

Requisições

Utilização de requisições AJAX

XMLHttpRequest

Quase não se usa mais, pois o Axios está dominando geral

//Exemplo de requisição para o Google (Funciona dentro do site do Google)
const xhr = new XMLHttpRequest()
// xhr.open(method, url, async)
xhr.open('GET', 'https://www.google.com', true)
xhr.send()
xhr.status // 200

Fetch API

Maneira simples de fazer requisições

  • Retorna um Promise
//Exampo - Requisição para o Google (Funciona dentro do site do Google)
fetch('https://www.google.com')
    .then(result => result.text())
    // result.text() - Retorna outra promise
    .then(html => console.log(html))

Axios

Ele não é nativo do JS então precisa entrar na Doc dele no Github e baixar por lá

Mas em algums frameworks ele já vem no pacote :3

GitHub

axios('target').then().catch()

Import & Export

Cara, existem várias formas. Irei listar as mais usada abaixo, mas é bom ver a doc :3

Export

const name = 'Albert'
const surname = 'Einstein'
export name
export default name
export name as genius
export const name = 'Albert'
export {name as genius, surname as default}

import

import { name } from './path/file_name'
// If have export default
import anyName from './path/file_name'

import { name, surname as surnameOfGenius} from './path/file_name'
import defaultModule { surnameOfGenius } from './path/file_name'

Compiladores e transpiladores

Babel

Documentação

Instalação

npm install --save-dev  @babel/cli @babel/preset-env @babel/core

Conversão de código

npx babel main.js -o bundle.js --presets=@babel/env

Automazar a conversão de código

Dentro do arquivo package.json, na linha de scripts

"babel": "babel ./main.js -o ./bundle.js --presets=@babel/env -w"

WebPack

Instalação

npm i --save-dev @babel/preset-env @babel/cli @babel/core babel-loader webpack webpack-cli 
npm i core-js regenerator-

// loader para css
npm i style-loader css-loader

configuração

Dentro do arquivo webpack.config.js

//configuração padrão
const path = require('path')
 
module.exports = {
    mode: 'development',
    //Arquivo de entrada
    entry: './src/main.js',
    //Arquivo de saida
    output: {
        path: path.resolve(__dirname, 'public', 'assets','js'),
        filename: 'bundle.js'
    },
    module: {
        rules: [{
            exclude: /node_modules/,
            test: /\.js$/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: ['@babel/env']
                }
            }
        },
    {
        //loader do CSS
        test: /\.css$/,
        use: ['style-loader','css-loader']
    }]
    },
    devtool: 'source-map'
}