📚 Estudos do curso Javascript Ninja
Documentação dos estudos das aulas do curso JavaScript Ninja , do professor Fernando Daciuk .
Acessando o console do Node JS
Variáveis e tipos de dados
Atribuindo números float
à variáveis
Acessando propriedades de objetos
Operadores aritméticos abreviados
+=
Pega todo o valor que uma variável já tem e soma com o valor especificado
-=
Pega todo o valor que uma variável já tem e diminui pelo valor especificado
*=
Pega todo o valor que uma variável já tem e multiplica pelo valor especificado
/=
Pega todo o valor que uma variável já tem e divide pelo valor especificado
===
igual a, e do mesmo tipo
!==
diferente, mas do mesmo tipo
Visualizando todas as branches criadas
Atualizando uma branch quando o repositório original foi alterado
Dando um push em uma nova branch
Prioridade / precedência entre operadores
++
Revisão do operador de soma abreviado - pós incremento
!
- Invertendo um valor com o operador not
Precedência de operadores de multiplicação e divisão
!!
Descobrindo a representação booleana de um valor sem utilizar o if
Declarando variáveis sem a palavra-chave var
Retorno de funções além dos tipos primitivos
Funções retornando arrays
Funções retornando objetos
Arrays como parâmetros de funções
Objetos como parâmetros de funções
Acessando um arquivo no console do Node JS
{'prop': 1}
- Strings como propriedades de Objetos
O que verdadeiramente são os arrays em JS
switch
- Estrutura condicional
Estruturas de repetição (loop)
++
Pós Incremento (revisão)
.length
- Propriedade de array e String
while()
e .length
- Iterando por itens de um array
.push()
- Método de array
A importância de nomear funções ES5
ES6(ES2015) e a nomeação de funções
.name
- Propriedade de função
Introdução à Programação Funcional (Functional Programming)
Objetos/cidadãos de primeira classe
Retornando objetos em funções
Retornando funções através de outras funções
Passando objetos como parâmetros de funções
Passando uma função como parâmetro de outras funções
Posicionamento de variáveis no código
Hoisting e Posicionamento de funções no código
Hoisting e Posicionamento de variáveis no código
console.log
com parâmetros
Invocando uma função dentro dela mesma
IIFE - Immediately-invoked function expression
Vantagens de se utilizar uma IIFE
Wrapper Objects / Objetos construtores
Wrapper objects criam novos objetos
name.valueOf()
- Método de objeto
String(value)
, Number(value)
, Boolean(value)
- Conversores de tipo
typeof
- Verificando tipos de valores primitivos
Verificando se um valor realmente é null
Acessando propriedades de objetos evitando o uso de if, switch ou ternário
Nomes de funções que retornam um valor boolean
Nomes de funções que retornam / mostram uma mensagem
Saltos - return
, break
, continue
delete
- Deletando propriedades de um objeto
Mais sobre objetos (Mutabilidade)
Manipulação de objetos por referência
Object
Palavra-chave do objeto interno do JS
Criação de objetos (literais, com new, método
Object.create()`)
Object.prototype
Introdução a protótipos de objetos
Array
Palavra-chave do array interno do JS
Date
Palavra-chave do date interno do JS
Herança através de encadeamento de protótipos
hasOwnProperty('propName')
- Verificando quais propriedades são específicas (não herdadas) de um objeto
Fazendo um for in em um objeto e mostrando somente propriedades específicas dele
Contando o número de propriedades de um objeto
obj.isPrototypeOf(otherObj)
Atribuição manual de itens a um array
arr.pop()
- Método de array
arr.join()
/ arr.join(sep)
- Método de array
.reverse()
- Método de array
arr.sort()
- Método de array
Introdução ao obj.toString()
- Método de objeto
arr.toString()
- Método de array
arr.concat(param)
- Método de array
arr.unshift(item1, item2...)
- Método de array
arr.shift()
- Método de array
arr.slice(firstItemIndex, +1indexFinalItem)
- Método de array
arr.splice()
- Método de array
arr.forEach(function(item) {})
- Método de array
arr.every(function(item) {})
- Método de array
arr.some(function(item) {})
- Método de array
arr.map(function(item, index, array) {})
- Método de array
arr.filter(function(item, index, array) {})
- Método de array
Encadeando os métodos map()
e filter()
arr.reduce(function(acc, act, index, array) {}, acc)
- Método de array
arr.reduceRight(function() {}, acc)
- Método de array
arr.indexOf(value, index)
- Método de array
arr.lastIndexOf()
- Método de array
Array.isArray(arr)
- Método de array
Introdução à JavaScript no browser
<script>
dentro de <head>
Por que utilizar script externo
window
- O Objeto global do browser
Criando construtores personalizados
'use strict'
- Criação de variáveis sem o var
Variáveis acessíveis no console do browser
'string'.length
- Propriedade de string
'string'.charAt(index)
- Método de string
'string'.concat(string1, string2)
- Método de string
'string'.indexOf(caracter, indexStart)
- Método de string
'string'.lastIndexOf('string')
- Método de string
'string'.replace('string', 'newString')
- Método de string
'string'.slice(startIndex, finalIndex+1)
- Método de string
'string'.split(separator, limit)
- Método de string
'string'.substring(startIndex, finalIndex+1)
- Método de string
'string'.toLowerCase()
- Método de string
'string'.toUpperCase()
- Método de string
Encadeando métodos de string para retornar apenas o primeiro caractere de uma string em maiúsculo
IIFE - Passando parâmetros
if / while / for com uma linha não precisam das chaves
Revisando o método prompt
Como pegar a resposta do usuário
DOM - Document Object Model
Como interagir com os elementos do DOM
document.getElementById()
document.getElementsByClassName()
document.getElementsByTagName()
document.getElementsByName()
'$' no início de variáveis
Valores mutáveis nos métodos getElement/s
querySelector() e querySelectorAll()
Suporte para querySelector() e querySelectorAll()
.addEventListener('click')
Prevenindo o comportamento padrão do button
.addEventListener('submit')
Inserindo um addEventListener() em um input
Inserindo um addEventListener() no próprio document
Relembrando if's de apenas uma linha
Introdução à curto-circuito
Pegando inputs através do type
Pegar inputs através do type não é uma boa prática
Preenchendo um input com o valor entrado pelo usuário
'is' e 'has', no início de funções
Validando emails com RegExp()
setTimeout() + Revisando o event loop
setTimeout() sendo executado várias vezes repetidas
Pausando uma função recursiva dentro do temporizador setTimeout
Métodos que param ou limpam o intervalo
Crie um arquivo index.html e adicione esse script a ele
Crie um campo input
do tipo text
, e inicie-o com um valor 0 (zero). Ele será o nosso cronômetro
Crie 3 botões para as ações do cronômetro: Start, Stop e Reset
Atributo data-js
para nomear o campo e os botões
Ao clicar em Start, o valor do campo deve ser incrementado de 1 em 1, a cada segundo
O operador +
utilizado como unário
Fazendo com que o valor do input seja incrementado a cada segundo
Ao clicar em Stop, o cronômetro deve parar de contar
Ao clicar em Reset, o cronômetro deve zerar e parar de contar
Duplicação de código e o uso de funções
.call(this, arg1, arg2, ..., argN)
.apply(this, [arg1, arg2, ..., argN])
Estendendo objetos com o .prototype
Criando propriedades depois de instanciar o objeto
Sobrescrevendo o .prototype
Especificando um segundo parâmetro para forEach
, map
e filter
Como utilizar o editorconfig
Crie dois objetos, que serão duas pessoas. Cada um deve ter as propriedades name
e lastName
, preenchidos com o nome e sobrenome da pessoa.
Agora crie uma função chamada getFullName
que retorne as propriedades name
e lastName
dos objetos acima, formando um nome completo. A função não deve receber nenhum parâmetro, mas as propriedades name
e lastName
devem ser dinâmicas. A mesma função deve servir para as duas pessoas (ou qualquer outra que for criada). Depois disso, invoque essa função, mostrando no console o nome completo das pessoas que foram criadas anteriormente, passando as pessoas acima como contexto da função. Use um console.log por pessoa.
Crie uma função chamada sum
. Essa função pode receber uma lista de parâmetros variável, e deverá retornar a soma de todos eles. Não use estruturas de repetição para somar os argumentos. Na primeira linha, dentro da função, deixe um console.log para mostrar todos os parâmetros passados para essa função.
Como somar os arguments de uma função
Mostre no console que a função acima funciona, invocando-a em 3 console.log
diferentes, com quantidades variáveis de parâmetros passados.
Declare uma variável chamada userEntry
, que irá receber alguns valores entrados pelo usuário. Mostre para o usuário a seguinte frase: "Entre com alguns números que serão somados:"
Mostre no console o valor entrado pelo usuário
Crie uma função chamada justNumbers
, que recebe por parâmetro uma string e remove tudo o que não for número, retornando um array somente com os números da string. Mostre a representação em string dessa função no console.
Usando a função acima, faça a limpeza dos valores entrados pelo usuário, atribuindo o resultado à uma variável numbers
.
Agora com o array de números, utilize a função sum
para somar todos os números desse array e mostre o resultado no console.
Usando a aba sources
para debugar o código
Acessando funções sem breakpoints específicos
Browsers e suas APIS de console
console.time()
e console.timeEnd()
HTML básico da calculadora
Deve ter somente 1 input, mas não deve ser possível entrar dados nesse input diretamente
O input deve iniciar com valor zero
Deve haver 10 botões para os números de 0 a 9. Cada botão deve ser um número
Deve haver 4 botões para as operações principais: soma (+), subtração(-), multiplicação(x) e divisão(÷)
Deve haver um botão de "igual" (=) que irá calcular os valores e um botão "CE" que irá limpar o input, deixando-o com valor 0
Especificando atributos no HTML para acessar seus elementos com JavaScript
A cada número pressionado, o input deve atualizar concatenando cada valor digitado, como em uma calculadora real
JavaScript da Calculadora
A cada número pressionado, o input deve atualizar concatenando cada valor digitado, como em uma calculadora real
JavaScript da Calculadora (cont.)
Ao pressionar o botão "CE", o input deve ficar zerado
Ao pressionar um botão com uma das 4 operações, deve aparecer o símbolo da operação no input
Se o último caractere no input já for um símbolo de alguma operação, esse caractere deve ser substituído pelo último pressionado
JavaScript da Calculadora (cont.)
Ao pressionar o botão de igual, o resultado do cálculo deve ser mostrado no input
JavaScript da Calculadora (cont.)
Ao pressionar o botão de igual, o resultado do cálculo deve ser mostrado no input (cont.)
JavaScript da Calculadora (cont.)
Ao pressionar o botão de igual, o resultado do cálculo deve ser mostrado no input (cont.)
Organizando o código dentro de funções (initialize)
Sobre a quantidade de linhas de uma função
Refatorando uma função com muitas linhas (handleClickEqual()
)
Sobre acoplamento de funções
Evitando a repetição de código dentro de funções
Refatorando os operadores
Refatorando os operadores (cont.)
Refatorando uma regex literal
Sobre duplicação de código
Melhorando a legibilidade de uma regra
Sobre números de linhas por arquivo
Sobre comentários em código
javascript:
ao invés do javascript:void(0)
void(0)
e javascript:
em códigos legados
event.preventDefault()
em links
Refatorando o código que pega o elemento html e atrela um evento à ele
Sobre abstração de código
O parâmetro use capture - false
ou true
como terceiro parâmetro em eventos
Acumulando eventos em um mesmo elemento
A desvantagem de atrelar eventos usando atribuições sem o addEventListener()
Removendo um evento com o removeEventListener()
A importância de se usar funções nomeadas em eventos
Eventos em elementos de formulário
Percorrendo elementos do DOM
Os text Nodes de .childNodes
, .firstChild
e .lastChild
Tabela com os números dos nodeTypes
Comentários também são nodes
Suporte de features nos browsers
Diferenças entre NodeList
e HTMLCollection
.childElementCount
ou .children.length
Métodos utilizados para manipular o DOM
.hasAttribute(attributeName)
Boas práticas em nomes de funções
.insertBefore(node, beforeWho)
document.createTextNode(text)
document.createElement(tagName)
Especificando element.id
ou element.className
como setter
setAttribute(attr, value)
O nome da lib deve ser "DOM". Ela deve ser uma função construtora, que receberá uma string por parâmetro. Essa string será o nó do DOM a ser selecionado; No construtor, você deve atribuir à this.element
todos os elementos do DOM selecionados;
Extenda a lib para ter os métodos on
, off
e get
O método get
deve retornar os elementos
O método on
irá adicionar um listener de evento a todos os elementos selecionados
O método off
irá remover o listener de evento de todos os elementos selecionados
Lista de propriedades do DOM que incluem nós de texto e comentários
Lista de propriedades do DOM que incluem apenas elementos
Lista de métodos do DOM - document
Lista de propriedades que pegam atributos html válidos
Lista de propriedades que pegam qualquer atributo html
document.createDocumentFragment()
- Manipulando elementos do DOM com performance
Lista de propriedades que pegam qualquer atributo html
document.createDocumentFragment()
- incluindo um fragmento no DOM
Posição dos script
no html
importa
O evento DOMContentLoaded
: resolvendo o problema de scripts
no head
Por que posicionar script
's no fim do body
Testes com imagens pesadas e o DOMContentLoaded
Copiando um array com o map()
Copiando um array com o slice()
Copiando um array-like com o Array.prototype.slice.call(arrayName)
Manipulando o mesmo array com 2 referências diferentes
Descobrindo o tipo real de um elemento
.toString()
em objetos literais
Object.prototype.toString.call(thisObjName)
- Descobrindo o tipo real de um elemento
Descobrindo se um objeto é do tipo array
Descobrindo se um objeto é do tipo function() {}
Descobrindo se um objeto é do tipo arguments
Criando funções que verificam os tipos de objetos
Aproveitando a lib DOM que fizemos na semana anterior, crie agora para ela métodos semelhantes aos que existem no array, mas que sirvam para os elementos do DOM selecionados. Crie os seguintes métodos: - forEach, map, filter, reduce, reduceRight, every e some.
Criando um método forEach para os elementos do DOM selecionados
(cont...) Aproveitando a lib DOM que fizemos na semana anterior, crie agora para ela métodos semelhantes aos que existem no array, mas que sirvam para os elementos do DOM selecionados. Crie os seguintes métodos: - forEach, map, filter, reduce, reduceRight, every e some.
Testando os métodos de arrays criados
Crie os seguintes métodos para verificação de tipo: - isArray, isObject, isFunction, isNumber, isString, isBoolean, isNull.
Devidos cuidados ao invocar os métodos de verificação de tipo
Uma observação sobre o undefined
Uma observação sobre o number
O objeto window.XMLHttpRequest()
Os três passos básicos para que uma requisição AJAX funcione
Como funciona uma requisição AJAX
O evento readystatechange
Os números de estado das requisições
ajax.status - Verificando os status da requisição
Manipulando respostas de requisições ajax
JSON.parse(ajax.responseText) - Manipulando dados JSON
ajax.responseXML - Manipulando dados XML
throw new Error('error message') e throw new SyntaxError('error message') - Como disparar erros em JavaScript
Crie um formulário com um input de texto que receberá um CEP e um botão de submit
Crie uma estrutura HTML para receber informações de endereço: "Logradouro, Bairro, Estado, Cidade e CEP." Essas informações serão preenchidas com os dados da requisição feita no JS
Crie uma área que receberá mensagens com o status da requisição: "Carregando, sucesso ou erro."
Utilize a lib DOM criada anteriormente para facilitar a manipulação e adicionar as informações em tela
Substituindo o cep da url
Limpando o cep entrado pelo usuário
Preenchendo os dados do cep com a propriedade .textContent
try / catch - Fazendo com que o o objeto json parseado seja null em casos de erros de requisição
Enquanto os dados são buscados, na área de mensagens de status, deve mostrar a mensagem: "Buscando informações para o CEP [CEP]..." Se não houver dados para o CEP entrado, mostrar a mensagem: "Não encontramos o endereço para o CEP [CEP]." Se houver endereço para o CEP digitado, mostre a mensagem: "Endereço referente ao CEP [CEP]:"
(cont.) Enquanto os dados são buscados, na área de mensagens de status, deve mostrar a mensagem: "Buscando informações para o CEP [CEP]..." Se não houver dados para o CEP entrado, mostrar a mensagem: "Não encontramos o endereço para o CEP [CEP]." Se houver endereço para o CEP digitado, mostre a mensagem: "Endereço referente ao CEP [CEP]:"
Variáveis no início do código
Posicionando as mensagens de erro, acerto e loading
As funções clearCep() e replaceCep(str)
Limpando os campos em caso de erro do request
Separando o código em módulos
Exportando a lib/módulo DOM
Restringindo o acesso à métodos de uma função
Restringindo o acesso à métodos de uma função exportada
Criando o index.html do app
Separe o nosso módulo de DOM criado nas últimas aulas em um arquivo DOM.js
Alterando os métodos da lib DOM para que sejam estáticos
E aqui nesse arquivo, faça a lógica para cadastrar os carros, em um módulo que será nomeado de "app"
O this
dentro de module patterns
Inserindo dados da empresa usando AJAX
Iniciando o cadastro de carros na tabela
Melhorando o método get() da DOM lib
Melhorando a função construtora principal da DOM lib
Fazendo com que o new seja desnecessário ao instanciar um objeto com a DOM lib
Referenciando o DOM através do $
Preenchendo os dados da tabela a cada vez que o form é submetido
O erro com o método get()
Cadastrando um carro na tabela
Evitando o uso repetitivo do app como function (app().nomeDoMetodo)
document.createDocumentFragment() - Criando os elementos do DOM a serem inseridos na tabela
Exemplos de closure com variáveis de escopo global e local
Exemplos de closure com variáveis contadoras e incrementos
Exemplo de closure com variáveis que recebem uma IIFE
elementName.style.cssProperty
Estilizando elementos através do método setAttribute('style', 'styleProperties')
Estilizando elementos através da propriedade elementName.classList
elementName.classList como getter
elementName.classList como setter
elementName.classList.contains('className')
elementName.classList.add('className')
elementName.classList.toggle('className')
elementName.classList.remove('className')
.innerHTML
- Fazendo com que o elemento permaneça com todo o html interno que ele já tem + o html setado
.innerHTML
vs. .textContent
Descobrindo o tipo de um objeto com o toString
Provocando um erro com uma imagem e um script inline
Limpando o html da página atual com o input no textarea
insertAdjacentHTML(position, htmlText)
Tabela com as possíveis posições a serem passadas por parâmetro para o insertAdjacentHTML(position, htmlText)
Problemas de segurança do insertAdjacentHTML()
insertAdjacentHTML() - inserindo um elemento do DOM como segundo parâmetro
console.dir(htmlElement) - visualizando as propriedades disponíveis de um elemento html
new Date() - Criando e instanciando uma nova data
new Date() - Construindo e manipulando uma nova data através de parâmetros
new Date() - A contagem dos meses
arrayMonths.indexOf(monthName)
new Date() - A contagem dos dias
new Date() - A contagem dos Meses - Parte 02
Date.now() - Convertendo milisegundos para segundos
Date.now() - Convertendo segundos em minutos
Date.now() - Convertendo minutos em horas
Date.now() - Convertendo horas em dias
Date.now() - Convertendo dias em anos
Date.now() - Sabendo em quantos milisegundos um código foi executado
Tabela com métodos que podem ser usados após instanciar o objeto new Date()
Outros métodos do Date Object
Tabela com alguns métodos usados com o objeto Math
O padrão de arredondamento em números decimais
Usando Math.max(x) e Math.min(x) com o apply()
Math.random() - retornando um número entre 0 e 3
Math.floor(Math.random() * 3) - retornando um número arredondado entre 0 e 2
Math.ceil(Math.random() * 3) - retornando um número arredondado de 1 a 3
Math.round(Math.random() * 3) - retornando um número arredondado de 0 a 3
AJAX - Aprendendo como tudo isso funciona no servidor
Listagem inicial dos diretórios e arquivos
Utilizando o Node para testar códigos
Subindo o servidor com o Node
Exemplo de REST Api com Express
Instalando o Express Js localmente
Requisitando o express de node_modules
O método get('url', callback)
res.send('response') - Enviando uma resposta para o front-end
app.listen(numeroDaPorta) - Selecionando a porta em que a resposta será ouvida
Criando novas rotas / url's
Acessando uma rota inexistente
Criando uma nova rota, antes inexistente
Atualizando o servidor manualmente em casos de bug no nodemon
Fazendo uma requisição AJAX no front-end
Subindo um servidor front-end com o python
Testando o servidor front-end
require('cors') - Importando o módulo cors
app.use(cors()) - Liberando o acesso à REST Api
Pegando um usuário específico com o GET do ajax
Passando um usuário inexistente com o GET do ajax
Deixando as rotas de usuário dinâmicas no back-end
Passando informações específicas de um usuário na REST Api
Tratando uma requisição GET onde o usuário não existe
Observações finais sobre servidores back-end e REST Api
Fazendo uma requisição síncrona
O outro formato de requisição ajax
Exemplo prático de envio do método POST
ajax.setRequestHeader()
Enviando os dados do usuário
Padronizando as propriedades do objeto
Testando essa requisição com o método GET
O padrão de resposta de uma REST Api
app.post() - Criando o método Http POST no servidor back-end
Instalando o módulo body-parser
Cadastrando temporariamente novos usuários no objeto users
Utilizando o método some para pegar o nome de um usuário
Testanto uma requisição GET
Cadastrando um usuário na memória
Pegando um usuário cadastrado, com o método GET
Criando uma verificação e evitando o recadastro de usuários repetidos
JSON.parse() - Convertendo o usuário de string para JSON
Testando uma calculadora simples
describe() - Começando a escrever o primeiro teste
O que ter em mente antes de escrever um teste
Sobre a estrutura de diretórios
it(desc) - Escrevendo a descrição de um teste
Importando um módulo para o teste
it(desc, callback) - Escrevendo a função de callback de um teste
Importando o chai para o teste
BDD - Behaviour Driven Development
expect() - Escrevendo a asserção que irá garantir que o teste funcione
Executando um teste falho com o mocha
O conceito baby steps / a base dos testes
module.exports = moduleName - Exportando um módulo no Node
Executando um teste correto com o mocha
RED, GREEN, BLUE - As três etapas de um teste
Escrevendo o teste em que uma função receba dois parâmetros e deva retornar a soma desses dois parâmetros
A documentação gerada pelos testes
Escrevendo um teste especificando que uma função deve retornar 5 quando 2 e 3 foram passados por parâmetro
Escrevendo um teste especificando que uma função deve retornar um erro caso receba apenas um parâmetro
Escrevendo um teste especificando que os dois parâmetros passados para uma função sejam números, de fato
Escrevendo um teste especificando que os dois parâmetros passados para uma função sejam números, de fato (cont.)
Refatorando o if da função que irá validar se dois argumentos estão sendo passados ao invocar sum
Object.prototype.toString.call(arg) === '[object Number]'
- Refatorando o if da função que irá validar se o tipo do argumento num1 ou num2 é um número
Estabelecendo a quantidade de testes a serem escritos
Escrevendo um teste no formato TDD
O método assert.equal(value, result, message)
O método asset.strictEqual(value, result, message)
Documentações - Assert e Chai
Problemas com o _mocha
no windows
Executando um test coverage com o istanbul
Visualizando o code coverage no browser
Observações sobre o test coverage
Sobre testes unitários / testes de unidade
O plugin Lcov info - Atom
O exemplo da diretiva 'use strict';
Considerações sobre qual lib instalar
Estrutura de arquivos e pastas usadas para o exemplo
Criando o script do exemplo
Criando o html do exemplo
Criando um arquivo minificado com o uglifyjs
--compress
- Comprimindo ainda mais um arquivo .js
Como uma IIFE afeta a compressão dos arquivos
Executando o Atom através do terminal
uglifyjs --mangle - Minificando ainda mais o código
uglifyjs --mangle --compress - Minificando ainda mais o código ao combinar o mangle e o compress
Sobre o acesso via mobile
Pretty print - Melhorando a exibição de um código minificado
Drop ao usar variáveis não utilizadas
Minificando um código que usa variáveis sem o var (globais)
Uglifyjs - O uso do --mangle
Adicionando o --source-map caminhoDoArquivoMapASerGerado ao minificar um arquivo
Usando corretamente o ternário em uma aplicação
Por que é necessário entender o Garbage Collection
Code Style - Definindo padrões para um projeto
Espaços em branco / Pulo de linha no código