Introdução ao AJAX: Fundamentos, Exemplos e Cuidados

O AJAX, sigla para Asynchronous JavaScript and XML, é uma tecnologia fundamental na criação de páginas web interativas e dinâmicas. Ele permite que as páginas da web se comuniquem com o servidor em segundo plano, sem a necessidade de recarregar a página inteira. Isso proporciona uma experiência mais fluida e responsiva aos usuários, uma vez que apenas partes específicas da página são atualizadas conforme necessário. Neste artigo, exploraremos os fundamentos do AJAX, forneceremos exemplos práticos e discutiremos os cuidados ao usá-lo.

Fundamentos do AJAX

O AJAX é baseado em três tecnologias fundamentais:

  1. JavaScript: O JavaScript é a linguagem de programação que permite adicionar interatividade e funcionalidade às páginas da web. No contexto do AJAX, o JavaScript é usado para iniciar solicitações assíncronas ao servidor e manipular os dados retornados.
  2. XMLHttpRequest: O objeto XMLHttpRequest é o pilar do AJAX. Ele permite que o JavaScript faça solicitações HTTP assíncronas ao servidor. Com esse objeto, você pode enviar dados para o servidor, receber respostas e atualizar partes da página com base nas respostas.
  3. XML ou JSON: Inicialmente, o AJAX foi projetado para trabalhar com dados em formato XML. No entanto, o uso de JSON se tornou mais comum devido à sua simplicidade e eficiência. XML e JSON são usados para estruturar os dados transmitidos entre o servidor e o cliente.

Exemplos de Uso do AJAX

Agora, vamos explorar dois exemplos simples de uso do AJAX:

Exemplo 1: Carregamento de Conteúdo Assíncrono

Imagine um site de notícias que deseja carregar artigos adicionais quando o usuário rolar até o final da página, sem recarregar a página inteira. O AJAX torna isso possível. Aqui está um exemplo básico:

// Função para carregar mais artigos
function carregarMaisArtigos() {
  fetch("servidor.php?pagina=2")
    .then(response => {
      if (!response.ok) {
        throw new Error("Erro ao carregar os artigos.");
      }
      return response.text();
    })
    .then(novoConteudo => {
      // Atualizar a página com o novo conteúdo
      document.getElementById("conteúdo").innerHTML += novoConteúdo;
    })
    .catch(error => {
      console.error(error);
    });
}

Neste exemplo, utilizamos a função fetch para fazer uma solicitação GET assíncrona ao servidor. Quando a resposta é recebida com sucesso, o conteúdo é atualizado na página. Qualquer erro durante o processo é tratado e exibido no console.

Exemplo 2: Autenticação de Usuário

// Função para autenticar o usuário
function autenticarUsuario() {
  var username = document.getElementById("username").value;
  var password = document.getElementById("password").value;

  fetch("autenticacao.php", {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: "username=" + username + "&password=" + password
  })
    .then(response => {
      if (response.ok) {
        // Usuário autenticado com sucesso
        alert("Autenticação bem-sucedida!");
      } else {
        // Falha na autenticação
        alert("Falha na autenticação. Verifique suas credenciais.");
      }
    })
    .catch(error => {
      console.error(error);
    });
}

Neste exemplo, utilizamos o fetch com um método POST para enviar os dados de autenticação para o servidor. Dependendo da resposta do servidor, uma mensagem de autenticação bem-sucedida ou uma mensagem de falha é exibida.

Lembre-se de que o código acima é apenas uma introdução ao uso do fetch para fazer solicitações AJAX. É importante continuar seguindo as melhores práticas, como tratamento de erros, segurança e considerações de desempenho, ao usar o fetch em projetos mais complexos.

Cuidados ao Usar o AJAX

Embora o AJAX seja uma ferramenta poderosa, é importante usá-lo com cuidado e considerar algumas práticas recomendadas:

  1. Progressive Enhancement: Certifique-se de que seu site ou aplicativo funcione mesmo quando o JavaScript estiver desativado. Use o AJAX para melhorar a experiência, não para torná-la essencial.
  2. Tratamento de Erros: Sempre trate erros adequadamente ao fazer solicitações AJAX. Isso inclui lidar com timeouts, respostas inesperadas e falhas de rede.
  3. Segurança: Proteja suas solicitações AJAX contra ataques de segurança, como Cross-Site Scripting (XSS) e Cross-Site Request Forgery (CSRF). Valide e sanitize os dados antes de enviá-los para o servidor.
  4. SEO: Lembre-se de que os mecanismos de busca podem ter dificuldade em indexar conteúdo carregado via AJAX. Certifique-se de que o conteúdo crítico seja acessível diretamente no HTML.
  5. Performance: Evite fazer muitas solicitações AJAX desnecessárias, pois isso pode afetar o desempenho do seu site. Agrupe solicitações sempre que possível e use o cache quando apropriado.

Em resumo, o AJAX é uma tecnologia essencial para criar páginas da web interativas e dinâmicas. Com a capacidade de enviar e receber dados do servidor de forma assíncrona, ele melhora significativamente a experiência do usuário. No entanto, é importante usá-lo com responsabilidade, seguindo as práticas recomendadas e considerando os aspectos de segurança e desempenho ao incorporá-lo em seus projetos web.

Gostaria de saber mais? De ujma olhada nas referencias e bons estudos

  1. Documentação Mozilla para Fetch:
  2. Livro online “You Don’t Know JS” (Capítulo sobre Fetch):
  3. Livro online “Eloquent JavaScript” (Capítulo sobre Fetch):
  4. W3Schools – Tutorial AJAX:
  5. SitePoint – A Guide to Fetch API:
  6. Artigo sobre Boas Práticas de AJAX:
  7. Artigo sobre Segurança em AJAX:

Esses recursos fornecem uma base sólida para entender e trabalhar com a API Fetch e o AJAX em JavaScript, bem como as melhores práticas associadas a essas tecnologias. Certifique-se de explorar esses materiais para aprofundar seus conhecimentos.

Entendendo o Prototype do JavaScript

Uma das características mais poderosas do JavaScript é a sua capacidade de trabalhar com objetos, que são instâncias de classes ou protótipos. O sistema de protótipos do JavaScript permite que os desenvolvedores criem objetos de forma flexível e eficiente. Neste artigo, vamos explorar o conceito de prototype no JavaScript e entender como ele funciona.

O que é o Prototype / Protótipo?

O prototype é um mecanismo interno do JavaScript que permite aos objetos herdar propriedades e métodos de outros objetos. Essa herança é diferente da herança de classe tradicional encontrada em linguagens orientadas a objetos, como Java e C#. No JavaScript, a herança ocorre através da chamada “herança prototípica” e é baseada em objetos, em vez de classes.

Herança Prototípica

A herança prototípica é a base do sistema de objetos do JavaScript. Cada objeto em JavaScript tem uma referência interna a outro objeto, chamado de “protótipo”. Quando uma propriedade ou método é acessado em um objeto, o JavaScript primeiro verifica se essa propriedade ou método existe no próprio objeto. Se não for encontrado, o JavaScript procurará no protótipo do objeto. Esse processo continua até que a propriedade ou método seja encontrado ou até que a cadeia de protótipos termine.

Essa cadeia de protótipos é a principal característica que permite a herança no JavaScript. Quando um objeto herda de outro objeto, na verdade está herdeiro do protótipo desse objeto.

Funções Construtoras e o Prototype

No JavaScript, funções construtoras são usadas para criar objetos com propriedades e métodos específicos. Quando uma função é chamada com a palavra-chave “new”, um novo objeto é criado e sua referência de protótipo é atribuída ao protótipo da função construtora.

function Pessoa(nome, idade) {
    this.nome = nome;
    this.idade = idade;
}
const pessoa1 = new Pessoa("João", 30);

Neste exemplo, a função Pessoa é uma função construtora e cria objetos com as propriedades nome e idade. Quando criamos um objeto pessoa1 usando a palavra-chave “new”, o protótipo do objeto pessoa1 é configurado para ser o objeto Pessoa.prototype.

Adicionando Propriedades e Métodos ao Prototype

O prototype é um objeto comum e, como tal, você pode adicionar propriedades e métodos a ele. Isso é útil quando você deseja que todos os objetos criados por uma função construtora compartilhem propriedades e métodos sem precisar redefini-los em cada instância.

Pessoa.prototype.apresentar = function() {
    return `Olá, meu nome é ${this.nome} e tenho ${this.idade} anos.`;
};

console.log(pessoa1.apresentar()); // Olá, meu nome é João e tenho 30 anos.

Ao adicionar o método apresentar ao prototype da função construtora Pessoa, todos os objetos criados a partir dela terão acesso a esse método.

Qual a diferença entre herança de classes e herança herança Prototípica no JavaScript?

Bom, esse é um tópico que merece sua própria postagem. E você pode ver detalhes no post Qual a diferença entre Herança de classes e herança Herança Prototípica no JavaScript?

Mas resumidamente, a herança de classes é baseada em classes, enquanto a herança prototípica é baseada em objetos. Essa diferença fundamental afeta a forma como a herança e a reutilização de código são alcançadas em cada paradigma.

Conclusão

Isso ai, o sistema de protótipos do JavaScript é uma característica poderosa e flexível que permite a herança e o compartilhamento. Espero que tenha gostado e aproveita para conferir nossas outras postagens

Tratando erros em JavaScript

O JavaScript é uma linguagem amplamente utilizada em desenvolvimento web, com várias aplicações em front-end e back-end. Como em qualquer outra linguagem, é possível que ocorram erros durante a execução do código, o que pode afetar o desempenho do programa e, em alguns casos, impedir que ele funcione corretamente.

Felizmente, existem várias maneiras de lidar com erros em JavaScript, permitindo que os desenvolvedores criem códigos mais robustos e confiáveis. Nesta postagem, discutiremos as principais técnicas para tratar erros em JavaScript, juntamente com exemplos de código e as melhores práticas para aplicá-las.

Bloco Try-Catch

Uma maneira comum de lidar com erros em JavaScript é usando o bloco try-catch. O bloco try contém o código que pode gerar um erro, enquanto o bloco catch é usado para tratar o erro caso ele ocorra.

Aqui está um exemplo de como usar o bloco try-catch em JavaScript:

try {
    // código que pode gerar um erro
} 
catch (e) {
    // código que trata o erro
}

No exemplo acima, o bloco try contém o código que pode gerar um erro, enquanto o bloco catch é responsável por manipular o erro caso ele ocorra. A variável e contém informações sobre o erro, como o tipo de erro e uma mensagem de erro.

Eventos de erro

Outra maneira de lidar com erros em JavaScript é por meio de eventos. Alguns erros são gerados por eventos, como uma imagem que não foi carregada corretamente. Para lidar com esses tipos de erros, você pode usar eventos específicos do navegador, como onerror.

Veja um exemplo de como usar o evento onerror em JavaScript:

const img = document.createElement('img');
img.onerror = function() {
  // código que trata o erro
}
img.src = 'imagem_que_não_existe.png';

No exemplo acima, criamos um novo elemento img e definimos a propriedade onerror para uma função que será executada caso ocorra um erro ao carregar a imagem. Dentro dessa função, podemos inserir o código que irá lidar com o erro de acordo com as necessidades do nosso programa.

Validações

Além das técnicas acima, é importante lembrar que as validações são uma forma eficaz de prevenir erros em JavaScript. As validações podem ser usadas para verificar se o input do usuário é válido, se uma variável possui o tipo esperado, ou se um objeto possui todas as propriedades necessárias.

Veja um exemplo de validação em JavaScript:

function calculaQuadrado(x) {
  if (typeof x !== 'number') {
    throw new TypeError('O valor fornecido não é um número');
  }
  return x * x;
}

No exemplo acima, criamos uma função calculaQuadrado que recebe um parâmetro x. Antes de realizar o cálculo do quadrado, verificamos se o parâmetro é um número. Se não for, lançamos um erro de tipo usando o comando throw.

Quando evitar o tratamento de erros e usar validações

Embora seja importante tratar erros em JavaScript, existem situações em que pode ser adequado não tratar um erro. Isso pode ocorrer quando um erro é inofensivo ou irrelevante para o funcionamento do programa, ou quando o tratamento de erros pode ter um impacto significativo no desempenho.

Algumas situações em que pode ser aceitável não tratar um erro incluem:

  • Erros que ocorrem em ambientes controlados, como testes automatizados ou ambientes de desenvolvimento;
  • Erros que ocorrem em código que não é crítico para o funcionamento geral do programa;
  • Erros que ocorrem em eventos que você não tem controle, como a interrupção de uma conexão de rede.

Em vez de tratar um erro, outra abordagem pode ser usar validações para prevenir que ele ocorra em primeiro lugar. As validações podem ser usadas para verificar se o input do usuário é válido, se uma variável possui o tipo esperado ou se um objeto possui todas as propriedades necessárias. Dessa forma, é possível reduzir a probabilidade de erros ocorrerem, o que pode levar a um código mais eficiente e confiável.

Por exemplo, ao invés de tratar o erro de uma variável não ser um número dentro de uma função, podemos validar o input da função e garantir que somente números sejam passados como argumento:

function calculaQuadrado(x) {
  if (typeof x !== 'number') {
    throw new TypeError('O valor fornecido não é um número');
  }
  return x * x;
}

Conclusão

Lidar com erros em JavaScript é uma parte importante do processo de desenvolvimento, garantindo que o código seja eficiente e confiável. Neste artigo, discutimos as principais técnicas para tratar erros em JavaScript, incluindo o uso do bloco try-catch, eventos de erro e validações. Também vimos que, em algumas situações, pode ser aceitável não tratar um erro e, em vez disso, usar validações para prevenir que ele ocorra em primeiro lugar. Esperamos que essas informações ajudem você a criar códigos JavaScript mais robustos e confiáveis em seu próximo projeto.

Como usar Classes no JavaScript

Classes são uma das principais características da orientação a objetos no JavaScript e servem modelos para criar objetos (instâncias) que compartilham propriedades e métodos. É uma maneira de escrever o código de uma forma mais organizada e reutilizável.

Antes do ECMAScript 2015 (ES6), o JavaScript não tinha suporte nativo para classes. Em vez disso, os desenvolvedores usavam funções construtoras e herança por protótipo para imitar a funcionalidade de classes. Com a introdução do ES6, o JavaScript agora oferece suporte nativo para classes.

Estrutura Básica

A sintaxe básica de uma classe no JavaScript é a seguinte:

class NomeDaClasse {
  constructor(propriedade1, propriedade2) {
    this.propriedade1 = propriedade1;
    this.propriedade2 = propriedade2;
  }
  metodo1() {
    // código do método 1
  }
  metodo2() {
    // código do método 2
  }
}

A classe tem um construtor, que é uma função especial chamada quando um novo objeto é criado a partir da classe. O construtor pode ter parâmetros para inicializar as propriedades do objeto. Além disso, uma classe pode ter métodos, que são funções que fazem alguma coisa com o objeto.

Para criar uma nova instância de uma classe, você usa a palavra-chave “new”:

const minhaInstancia = new NomeDaClasse(valor1, valor2);

A partir daí, você pode acessar as propriedades e métodos da instância como:

minhaInstancia.propriedade1;
minhaInstancia.metodo1();

Como era antes do ES6

Precisamos lembrar que o JavaScript é uma linguagem prototipada, então a palavra “class” é um facilitador e por baixo dos panos faz algo parecido com o seguinte código:

function NomeDaClasse(propriedade1, propriedade2) {
  this.propriedade1 = propriedade1;
  this.propriedade2 = propriedade2;

  this.metodo1 = function() {
    // código do método 1
  };

  this.metodo2 = function() {
    // código do método 2
  };
}

var objeto = new NomeDaClasse('valor1', 'valor2');

Herança

Além disso, você pode estender uma classe existente para criar uma nova classe com suas próprias propriedades e métodos adicionais. Isso é chamado de herança e é feito usando a palavra-chave extends.

O código abaixocria uma nova classe NomeDaClasseFilha que herda as propriedades e métodos da classe:

class NomeDaClasseFilha extends NomeDaClasse {
  constructor(propriedade1, propriedade2, propriedade3) {
    super(propriedade1, propriedade2);
    this.propriedade3 = propriedade3;
  }
  metodo3() {
    // código do método 3
  }
}

Conclusão

Isso ai, esse é o fundamento de utilização de classes no JavaScript. Se você teve duvida ou gostaria de um tutoria mais a fundo, prenda uma mensagem com a sua duvida e veremos o que podemos faze para te ajudar.

Como funciona o Intl.NumberFormat?

Neste breve post veremos como funciona o Intl.NumberFormat em partes para entendê-lo melhor e podermos gerar várias strings com valores numéricos formatados corretamente.

Sintaxe

A sintaxe básica é bem simples, instanciamos um objeto que precisa de dois parametros, locales e options. Ambos são opcionais

new Intl.NumberFormat([locales[, options]])

locales: em 99% dos casos nós usaremos as strings com representação do local/país/região representada no nosso objeto. Você provavelmente usará os valores ‘pt-BR’, ‘en’ ou alguma variação parecida. Para um guia completo, confira aqui: https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry

const valor = 1999.99;
console.log(new Intl.NumberFormat('pt-BR').format(valor));
// saida: 1.999,99
console.log(new Intl.NumberFormat('ar-EG').format(valor));
// saida: ١٬٩٩٩٫٩٩

options: O segundo parâmentro é um pouco mais complicado pois as opções tem várias opções… kkkk… mas faz parte Vejamos um modelo e depois explicarei o que cada coisa faz

const valor = 1999.99;

const options = {
    style : "currency",
    currency : "BRL",
    minimumIntegerDigits : 10,
    minimumFractionDigits : 2,
    maximumFractionDigits: 5,
}

console.log(new Intl.NumberFormat('pt-BR', options).format(valor));
// saida: R$ 0.000.001.999,99

style:

Definição: O estilo do formato a ser utilizado.

Valor Padrão: “decimal”

Valores Permitidos: “decimal" para formato de número simples, "currency" para formato monetário e "percent" para formato percentual;

currency:

Definição: A moeda para usar na formatação monetária.

Valor Padrão: Não existe. Se o style for “currency”, então o esta propriedade precisa ser informada

Valores Permitidos: Os valores permitidos são os códigos de moedas da ISO 4217, como "USD" para dólar estadunidense, "EUR" para euro, ou "CNY" para RMB chinês — veja a Lista de códigos de moedas e fundos atuais.

minimumIntegerDigits

Definição: A quantidade mínima de dígitos inteiros para utilizar.

Valor Padrão: 1

Valores Permitidos: de 1 a 21

minimumFractionDigits

Definição: A quantidade mínima de dígitos fracionados para utilizar.

Valor Padrão: o padrão para formatos monetários é a menor unidade de dígitos fornecidos pela lista de códigos de moedas ISO 4217 (2 se a lista não fornecer a informação).

Valores Permitidos: de 0 a 20.

maximumFractionDigits

Definição: O número máximo de dígitos fracionados para utilizar

Valor Padrão: o padrão para a formatação de número simples é o maior entre minimumFractionDigits e 3.

Valores Permitidos: de 0 a 20.

CONCLUSÃO

Isso pessoal, esse foi um tutorial bem simples de como usar uma classe extremamente útil. Para mais detalhes, vejam também a documentação oficial https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat

Como usar o forEach no JavaScript

forEach

Neste breve artigo, estarei mostrando como usar o forEach no JavaScript usando todas as possibilidades de passagem de valores no exemplos. Estarei presumindo que você entende como funcionam Arrays e Arrow Functions.

Descrição e uso do forEach

O forEach é um método acessado dos objetos array (vetores) que itera entre todos os itens da lista executando uma função que informamos passada por parâmetro. Sendo assim, quando você possui uma coleção que precisa ser iterada ele é um ótimo candidato por ser sucinto e fácil de entender.

Quando não usar o forEach

Se você precisa parar a iteração, o forEach não é o melhor candidato. Ele não é um loop que podemo encerrar com ‘break’ e se na função de callback colocarmos um ‘return’, ele simplesmente seguirá para o próximo item. Neste tipo de situação, de preferencia para os loops tradicionais.

Array.forEach simples

a forma mais simples é chamando o método e passando uma função de callback que possui apenas um parâmetro

// Uma lista simples
const dados = [1,2,3,4,5,6,7,8];
// uma função de callback com apenas 1 item passado de parametro
const callback = item => console.log(item)
// a chamada
dados.forEach(callback);

Poderíamos colocar a função diretamente dentro da chamada

dados.forEach(item => console.log(item));

Ou chamar todo o primeiro exemplo em apenas 1 linha

[1,2,3,4,5,6,7,8].forEach(item => console.log(item));

Mas é importante tentar manter o seu código o mais fácil de entender possível.

Array.forEach com 2 parâmetros no callback

Digamos que você precise saber o índice do item por algum motivo, neste caso, precisamos informar mais um parâmetro em nossa callback. Vamos fazer um exemplo um pouco diferente

// Uma lista com strings para não confundir com o valor do indice
const dados2 = ['caixa', 'pallet', 'caixote', 'sacola', 'avulo'];
// A callback agora precisa de um segundo parametro 
const callback2 = (item, indice) => console.log(`${indice}: ${item}`)
// mesma chamada
dados2.forEach(callback2);

Ao executar o código você verá que teremos a posição dos items e seus valores. Para comparação, o For tradicional geraria este Loop da seguinte maneira:

for(let indice; indice < dados2.length; indice++) console.log(`${indice}: ${item}`)

Array.forEach com 2 parâmetros

Para este exemplo, manteremos o nosso segundo vetor

const dados2 = ['caixa', 'pallet', 'caixote', 'sacola', 'avulo'];

e vamos criar um objeto bem simples com apenas 1 função que executa um console log no valor passado por parametro, no mundo real seria somente uma função, mas para nosso exemplo ele ele vale.

let obj = { log : (umItem) =&gt; console.log(umItem)}

Agora, se você quisesse executar o obj.log para cada item do dados2, você poderia fazer algo assim:

dados2.forEach(item =&gt; obj.log(item));

e vai funcionar. Agora digamos que você tenha uma ambiente dinamico no qual você não sabe o qual objeto está executando o método log e dentro deste método poderiam acontecer coisas diferentes ou até que você está montando uma biblioteca que receberá o objeto e executará alguma coisa. Como você faria? Com o forEach, é possível fazer o seguinte

dados2.forEach(item =&gt; this.log(item), obj);

Deu erro? Isso é porque arrow function não podem receber escopo, se não entendeu, veja novamente o link Arrow Functions. Entendeu, então a parte abaixo é simples. A solução mais simples, use a função normal.

dados2.forEach(function(item){ this.log(item)}, obj);

Era isso, espero que tenham gostado, qualquer duvida deixem nos comentários.

Exercício fácil: Recursão em Arrays

A recursão é uma metodologia de resolução de problemas que consiste em dividir o problema maior em subproblemas menores, até chegar em um problema pequeno o suficiente para que ele seja resolvido de forma trivial. Uma função recursiva chama a si mesma para resolver o problema proposto. As funções recursivas são soluções inteligentes e elegantes para problemas complexos. As funções recursivas devem ter um caso básico, devem mudar o seu estado e se aproximar do caso básico e devem chamar a si mesmas (recursivamente).

Fonte: https://panda.ime.usp.br/pensepy/static/pensepy/12-Recursao/recursionsimple-ptbr.html

Exercício:

No nosso exercício, teremos um caso base que deverá informar à nossa função que ela não precisará mais ser chamada. Isto significa que é um caso simples em que o valor de retorno já será conhecido. Também haverá uma chamada recursiva que executará a função com diferentes argumentos.

Você deverá criar uma função chamada contarDecrescente. Essa nossa função recursiva deverá receber um parâmetro (n). Caso esse parâmetro seja um número menor que 1, deverá retornar um array vazio. Caso atenda o requisito, crie uma constante chamada arrayDecrescente que recebe a função recursiva. Por exemplo, se o valor indicado no parâmetro for 5, o array retornado será: [5, 4, 3, 2, 1].

Não utilize laços de repetição para realizar este exercício.

Faça o download da solução aqui:

[download id=”4050″]

Exercício fácil: Parâmetros em Arrow Function

Explicação:

Uma Arrow Function é uma expressão de função. Foi introduzida no ES6 (que trouxe novas features, incluindo essa nova forma de criar funções, utilizando o =>)

Uma Arrow Function possui uma sintaxe curta e possuem alguns benefícios, por exemplo:

  • O this é definido à partir das funções onde foram definidas, tornando desnecessário o bind();
  • São menos verbosas que as maneiras anteriores de expressar funções.

As Arrow Functions não podem ser usadas como funções construtoras, pois não se pode aplicar o operador new a elas.

Vamos ao Exercício:

Exercício 1:

Declare uma função comum, utilizando uma declaração ou expressão de função. Essa nossa função deverá possuir dois parâmetros (name, lastName). A nossa função deve mostrar no console a seguinte frase: “Olá name lastName, eu sou uma função!”.

Realizada esta parte do exercício, você deverá:

Replicar o exercício anterior, utilizando Arrow Function. Utilize os mesmos parâmetros e retorne no console a mesma frase.

Exercício 2:

Agora, no exercício dois, criaremos uma função chamada descobreDiametro, onde receberemos um parâmetro chamado raio e um parâmetro chamado diametro. Dentro da função, retornaremos o resultado do seu diâmetro.

Realizada a primeira parte do exercício, replique o exercício 2 utilizando Arrow Function.

Não esqueça de mostrar o resultado no console!

Gostou deste exercício? Comente os seus resultados abaixo!

Entendendo o Prototype

Uma das formas de criar objetos em JavaScript é usando a função construtora (constructor). Mas há um problema em criar objetos com o Constructor, pois ao executar uma função construtora, criando-se objetos, a engine JavaScript cria duas cópias da função construtora, ou seja, todo objeto criado utilizando a função Constructor terá a sua própria cópia de propriedades e métodos. Ou seja, torna-se redundante, pois não há sentido em ter duas instâncias de uma função fazendo a mesma coisa. Por exemplo:

function Humanos(nome, sobrenome){
    this.nome = nome;
    this.sobrenome = sobrenome;
    this.nomeCompleto = function(){
        return this.nome + " " + this.sobrenome;
    }
}


let pessoa1 = new Humanos("João", "Silva");
let pessoa2 = new Humanos("José", "Silveira");
console.log(pessoa1);
console.log(pessoa2);

Utilizando o console.log, verificamos a criação de duas funções nomeCompleto(), e isso resulta em desperdício de memória.

E como resolver isso?

Ao criar uma função, o mecanismo JavaScript adiciona um protótipo (prototype) à função. Essa propriedade é um objeto denominado protótipo de objeto e possui um constructor por padrão. Esse constructor aponta de volta para a função na qual o prototype é uma propriedade. Podemos acessar a propriedade prototype da função usando nomeFuncao.prototype.

No nosso exemplo, a função Humanos possui uma propriedade prototype que aponta para o objeto prototype. O objeto prototype tem uma propriedade constructor e aponta de volta para a função Humanos. Confuso? Vamos verificar isso na nossa imagem:

Para acessar nossa propriedade prototype da função Humanos:

console.log(Humanos.prototype);

E isso nos mostrará que a função possui um objeto prototype com dua propriedades:

  • constructor: aponta para a própria função Humanos;
  • __proto__: propriedade utilizada no conceito de herança.

O Objeto pessoa1 criado usando a função construtora Humanos possui um __proto__ que aponta para o protótipo de objeto da função constructor.

Podemos verificar que o protótipo pessoa1.__proto__ e a propriedade Humanos.prototype são iguais:

Humanos.prototype === pessoa1.__proto__;
//true

Criaremos agora um novo objeto, chamado pessoa 2:

let pessoa2 = new Humanos("José", "Silveira");

Verificaremos que o protótipo pessoa2.__proto__ também é igual a propriedade Humanos.prototype:

Humanos.prototype === pessoa2.__proto__;
//true

E verificamos que a propriedade __proto__ dos dois objetos pessoas são estritamente iguais! Veja só:

pessoa1 === pessoa2;
//false

pessoa1.__proto__ === pessoa2.__proto__;
//true

E isso prova que as propriedades __proto__ de pessoa1 e pessoa2 apontam para o Humanos.prototype que criamos anteriormente!

Como o prototype é um objeto, podemos anexar propriedades e métodos ao objeto protótipo. Assim, permite que os objetos criados usando a função construtora compartilhem essas propriedades e métodos:

Humanos.prototype.nome = "Maria";
console.log(Humanos.prototype.nome);

Humanos.prototype["idade"] = 30;
console.log(Humanos.prototype["idade"]);

console.log(Humanos.prototype);

Você pode ver que as propriedades nome e idade foram adicionadas ao Humanos.prototype!

Quando tentamos acessar uma propriedade de um objeto, o JavaScript primeiro tenta encontrar a propriedade no objeto e, se a propriedade estiver presente no objeto, ele gera o seu valor. Se não estiver, ele tentará encontrar a propriedade no objeto prototype. Se for encontrada, o valor será retornado.

Exemplo:

Primeiro, criaremos uma função construtora vazia:

function Pessoa(){

}

Depois, adicionaremos as propriedades nome, idade e digaOla ao prototype da função Pessoa:

Pessoa.prototype.nome = "Maria";
Pessoa.prototype.idade = 30;
Pessoa.prototype.digaOla = function(){
    console.log(this.nome + " diz Olá para você!");
};

Criaremos um objeto usando a função construtora Pessoa e acessaremos a propriedade nome usando o objeto criado:

let pessoa1 = new Pessoa();
console.log(pessoa1.nome);

E a saída será?

Maria

Gostou deste artigo? Comente abaixo!

Referência: https://medium.com/better-programming/prototypes-in-javascript-5bba2990e04b

Exercício fácil – recursão com JavaScript

Neste exercício, veremos antes uma função que utiliza recursão. Essa função retorna um array de números inteiros começando com 1 pelo número passado para a função.

Teremos um exemplo para você tirar uma base de como resolver o exercício.

No nosso caso base, a função recursiva não precisa mais se chamar, sendo um caso simples em que o valor de retorno já é conhecido. Também haverá uma chamada recursiva que executa a função original com os argumentos diferentes.

No nosso exemplo base, temos uma função recursiva que retorna um vetor que contém os números de 1 a n. Então, se passarmos um valor n, ele deverá adicionar valores ao vetor até chegar a esse valor. Por exemplo: n = 10. O vetor resultante deverá ser [1, 2, 3, 4, 5, 6, 7, 8, 9, 10}. Se o valor de n for menor que 1, retornará um vetor vazio:

function contador (n){
    if (n < 1){
        return [];
    } else {
        let contadorArray = contador (n - 1);
        contadorArray.push(n);
        return contadorArray;
    }
}

console.log(contador(20));
/* [
   1,  2,  3,  4,  5,  6,  7,
   8,  9, 10, 11, 12, 13, 14,
  15, 16, 17, 18, 19, 20
] */

No começo, isso parece contra-intuitivo, com o valor de n diminuindo, mas os valores do vetor aumentando. Isso acontece pois o envio ocorre por último, após o retorno da chamada recursiva. Quando n é inserido, a contagem (n-1) já foi avaliada e retornada [1, 2, …, n-1].

Vamos ao exercício:

No nosso exercício, utilizaremos a recursão para retornar um array que contém os números inteiros que vão de n a 1, com base no parâmetro n. Se n for menor que 1, retorna um array vazio, senão, retorna os valores de n a 1. Exemplo:

n = 10;

[10, 9, 8, 7, 6, 5, 4, 3, 2, 1].

Use o exemplo anterior como base para este exercício. Não use o método push!

Você pode realizar o download da resolução deste exercício aqui:

[download id=”3715″]