JS para impacientes

Javascript para impacientes

January 06, 2020

Js para impacientes

Introdução

Motivação

Esse documento é um conjunto de “cheatsheet” para javascript que você frequentemente encontrará em projetos modernos e na maioria de exemplos de códigos atuais.

Esse guia não tem a intenção de te ensinar Javascript do zero, mas sim ajudar desenvolvedores com conhecimentos básicos a se familiarizarem com códigos modernos.

Nota: Muito dos conceitos apresentados aqui vem de uma atualização do Javascript (ES2015, chamada também de ES6). Você pode achar as novas funcionalidades adicionadas nessa atualização aqui.

Créditos do texto Original: Manuel Beaudru ⚡️

Material Complementar

Se você estiver com dificuldades em entender alguma coisa, eu sugiro que você procure por respostas nos seguintes lugares:

Sumário

  • Modern JavaScript cheatsheet

    • Introdução
    • Motivação
    • Material Complementar
    • Tabela de Conteúdos
    • Noções
    • Declaração de variáveis: var, const, let

      • Breve explicação
      • Exemplo
      • Explicação Detalhada
      • Material Complementar
    • Função de Seta

      • Exemplo
      • Explicação Detalhada
      • Concisão
      • Referência this
      • Material Útil
    • Parametros padrão de uma Function

      • Material Complementar
    • Desestruturação de objetos e arrays

      • Explicação com exemplo de código
      • Material Útil
    • Metodos de lista - map / filter / reduce

      • Exemplo
      • Explicação
      • Array.prototype.ma
      • Array.prototype.filte
      • Array.prototype.reduc
      • Material Complementar
    • Spread operator ”…”

      • Exemplo
      • Explicação
      • Em interações
      • Function rest parameter
      • Object properties spreading
      • Material Complementar
    • Object property shorthand

      • Explicação
      • Material Complementar
    • Promises

      • Exemplo
      • Explicação
      • Criando uma promise
      • Usando uma promise
      • External Resources
    • Template literals

      • Sample code
      • External resources
    • Imports / Exports

      • Explanation with sample code
      • External resources
    • JavaScript this

      • External resources
    • Class

      • Samples
      • External resources
    • Async Await

      • Sample code
      • Explanation
      • External resources
    • Glossary
    • Scope
    • Variable mutation

Noções

Declaração de variáveis: var, const, let

Em JavaScript, existem três palavras-chave disponíveis para declarar uma variável, e cada uma tem suas diferenças. São elas var, let e const.

Breve explicação

Variáveis declaradas com a palavra-chave const não podem ser reatribuídas, enquanto let e var podem.

Eu recomendo sempre declarar suas variáveis com const por padrão, e com let se você precisar modifica-lo ou reatribuí-lo mais tarde.

Escopo Reatribuível Mutável Zona Temporal Inoperante
const Bloco Não Sim Sim
let Bloco Sim Sim Sim
var Função Sim Sim Não

Exemplo

const person = "Nick";
person = "John" // Irá ocorrer um erro, person não pode ser reatribuída
let person = "Nick";
person = "John";
console.log(person) // "John", a reatribuição é permitida com let

Explicação Detalhada

O escopo de uma variável grosseiramente significa “onde esta variável está disponível no código”.

var

Variáveis declaradas com var são função escopada, significando que quando uma variável é criada em uma função, tudo naquela função pode acessar essa variável. Além disso, uma variável de função escopada criada em uma função não pode ser acessada fora desta função.

Eu recomendo que você imagine isso, como se uma variável X escopada significasse que essa variável era uma propriedade de X.

function myFunction() {
  var myVar = "Nick";
  console.log(myVar); // "Nick" - myVar é acessível dentro da função.
}
console.log(myVar); // Lança um ReferenceError, myVar não está acessível fora da função.

Ainda focado na variável de escopo, aqui está um exemplo mais sutil:

function myFunction() {
  var myVar = "Nick";
  if (true) {
    var myVar = "John";
    console.log(myVar); // "John"
    // na verdade, sendo myVar do escopo da função, nós simplesmente apagamos o valor anterior do myVar "Nick" para "John"
  }
  console.log(myVar); // "John" - veja como as instruções no bloco if afetaram esse valor
}
console.log(myVar); // Lança um ReferenceError, myVar não é acessível fora da função.

Além disso, variáveis declaradas var são movidas para o topo do escopo na execução. É o que chamamos de içando a var.

Esta parte do código:

console.log(myVar) // undefined -- sem erro lançado
var myVar = 2;

é entendido na execução como:

var myVar;
console.log(myVar) // undefined -- sem erro lançado
myVar = 2;
let

var e let são quase os mesmos, mas variáveis declaradas com let

  • são escopado em bloco
  • não são acessíveis antes de serem atribuídas
  • não podem ser re-declaradas no mesmo escopo

Vamos ver o impacto do escopo em bloco em nosso exemplo anterior:

function myFunction() {
  let myVar = "Nick";
  if (true) {
    let myVar = "John";
    console.log(myVar); // "John"
    // na verdade, myVar sendo escopada em bloco, nós criamos uma nova variável myVar.
    // essa variável não é acessível fora do bloco e é totalmente independente
    // da primeira myVar criada !
  }
  console.log(myVar); // "Nick", veja como as instruções no bloco IF NÃO afetou este valor
}
console.log(myVar); // lançado um ReferenceError, myVar não é acessível fora da fucnção.

Agora, o que significa para as variáveis let (e const) não estarem acessíveis antes de serem atribuídas:

console.log(myVar) // lança um ReferenceError !
let myVar = 2;

Em contraste com as variáveis var, se você tentar ler ou escrever em uma variável let ou const antes de serem atribuídos, um erro será gerado. Esse fenômeno é freqüentemente chamado Zona Temporal Inoperante ou TDZ.

Nota: Tecnicamente, as declarações de let e const também estão sendo içadas, mas não a sua atribuição. Uma vez que elas são feitas para que elas não possam ser usados antes da atribuição, ela intuitivamente parece que não há içamento, mas existe. Saiba mais sobre isso explicação muito detalhada aqui se quiser saber mais.

Além disso, você não pode re-declarar uma variável let:

let myVar = 2;
let myVar = 3; // Retorna um SyntaxError
const

Variáveis declaradas const agem como variáveis let, mas elas não podem ser reatribuídas.

Para resumir, variáveis const:

  • são escopado em bloco
  • não são acessíveis antes de serem atribuídos
  • não podem ser re-declaradas no mesmo escopo
  • não podem ser reatribuídas
const myVar = "Nick";
myVar = "John" // lança um erro, reatribuição não é permitido
const myVar = "Nick";
const myVar = "John" // lança um erro, re-declaração não é permitida

Mas há uma sutileza : variáveis const não são imutáveis ! Concretamente, Isto significa que variáveis objetos e arrays declaradas com const podem ser mutadas.

Para objetos:

const person = {
  name: 'Nick'
};
person.name = 'John' // isto irá funcionar! A variável objeto person não é completamente reatribuída, mas mutada
console.log(person.name) // "John"
person = "Sandra" // lança um erro, porque a reatribuição não é permitida com variáveis declaradas com const

Para arrays:

const person = [];
person.push('John'); // isto irá funcionar! A variável array person não é completamente reatribuída, mas mutada
console.log(person[0]) // "John"
person = ["Nick"] // lança um erro, porque a reatribuição não é permitida com variáveis declaradas com array

Material Complementar

Função de seta

A atualização do JavaScript ES6 introduziu funções de seta, que é outra maneira de declarar e usar funções. Aqui estão os benefícios que elas trazem:

  • Mais conciso
  • this é retirado dos arredores
  • retorno implícito

Exemplo de código

  • Concisão e retorno implícito
function double(x) { return x * 2; } // Forma tradicional
console.log(double(2)) // 4
const double = x => x * 2; // A mesma função escrita como uma função de seta com retorno implícito
console.log(double(2)) // 4
  • Referência this

Em uma função de seta, this é igual ao valor this do contexto de execução envolvente. Basicamente, com as funções de seta, você não precisa fazer o truque “that/self = this” antes de chamar uma função dentro de uma função.

function myFunc() {
  this.myVar = 0;
  setTimeout(() => {
    this.myVar++;
    console.log(this.myVar) // 1
  }, 0);
}

Explicação detalhada

Concisão

As funções de seta são mais concisas do que as funções tradicionais em diversas maneiras. Vamos rever todos os casos possíveis:

  • Retorno implícito VS explícito

Um retorno explícito é uma função em que a palavra-chave return é usada em seu corpo.

  function double(x) {
    return x * 2; // esta função retorna explicitamente x * 2, a palavra-chave *retorno*  é usada
  }

Na maneira tradicional de escrever funções, o retorno sempre foi explícito. Mas com funções de seta, você pode fazer retorno implícito, o que significa que você não precisa usar a palavra-chave return para retornar um valor.

  const double = (x) => {
    return x * 2; // um retorno explícito aqui
  }

Uma vez que esta função apenas retorna algo (sem instruções antes da palavra-chave return), podemos fazer um retorno implícito.

  const double = (x) => x * 2; // Correto, retorna x*2

Para fazer isso, só precisamos remover os colchetes e a palavra-chave return. É por isso que é chamado de retorno implícito, a palavra-chave return não existe, mas essa função retornará x * 2.

Nota: Se sua função não retornar um valor (com efeitos colaterais), ele não faz um retorno explícito nem implícito.

Além disso, se você quiser retornar implicitamente um objeto, você deve ter parênteses em torno dele, pois isso entrará em conflito com as chaves do bloco:

const getPerson = () => ({ name: "Nick", age: 24 })
console.log(getPerson()) // { name: "Nick", age: 24 } -- objeto implicitamente retornado pela função de seta
  • Só um argumento

Se a sua função apenas tiver um parâmetro, você pode omitir os parênteses à sua volta. Se pegarmos o código double acima:

  const double = (x) => x * 2; // esta função de seta apenas leva um parâmetro

Parênteses ao redor do parâmetro podem ser evitados:

  const double = x => x * 2; // esta função de seta tem apenas um parâmetro
  • Nenhum argumento

Quando não há argumento fornecido para uma função de seta, você precisa fornecer parênteses, ou não será uma sintaxe válida.

  () => { // parênteses são fornecidos, tudo está ok
    const x = 2;
    return x;
  }
  => { // Sem parênteses, isso não funcionará!
    const x = 2;
    return x;
  }
Referência this

Para entender essa sutileza introduzida com funções de seta, você deve saber como this se comporta em JavaScript.

Em funções de seta, this é igual ao valor this do contexto de execução envolvente. O que significa que uma função de seta não cria um novo this, Ela pega do seu entorno em vez disso.

Sem uma função de seta, se você quisesse acessar uma variável de this em uma função dentro de outra função, você tinha que usar that = this ou self = this.

Por exemplo, usando a função setTimeout dentro de myFunc:

function myFunc() {
  this.myVar = 0;
  var that = this; // that = this (truque)
  setTimeout(
    function() { // Um novo *this* é criado neste escopo de função
      that.myVar++;
      console.log(that.myVar) // 1

      console.log(this.myVar) // undefined -- veja a declaração da função acima
    },
    0
  );
}

Mas com função de seta, this é retirado do seu entorno:

function myFunc() {
  this.myVar = 0;
  setTimeout(
    () => { // this é retirado do entorno, o que significa de myFunc aqui
      this.myVar++;
      console.log(this.myVar) // 1
    },
    0
  );
}

Material Útil

Parametros padrão de uma Function

A partir da atualização do JavaScript ES2015, você pode definir um valor padrão para os parâmetros da função usando a seguinte sintaxe:

function myFunc(x = 10) {
  return x;
}
console.log(myFunc()) // 10 -- nenhum valor é fornecido então o valor padrão de x que é 10 será atribuído a x em myFunc
console.log(myFunc(5)) // 5 -- um valor é fornecido então x é igual a 5 em myFunc

console.log(myFunc(undefined)) // 10 -- um valor undefined é fornecido então o valor padrão é atribuído para x
console.log(myFunc(null)) // null -- um valor (null) é fornecido, veja abaixo para mais detalhes neste caso

O valor de parâmetro padrão é aplicado em duas e somente duas situações:

  • Nenhum parâmetro fornecido
  • undefined parâmetro fornecido

Em outras palavras, se você passar um null o parâmetro padrão não irá ser aplicado.

Nota: Atribuição de valor padrão também pode ser usada com parâmetros desestruturados (veja o próximo conceito para ver um exemplo)

Material Complementar

Desestruturação de objetos e arrays

Desestruturação é uma maneira conveniente de criar novas variáveis extraindo alguns valores de dados armazenados em objetos ou arrays (matrizes).

Para nomear alguns casos de uso, desestruturação pode ser usado para desestruturar parâmetros de função ou this.props em projetos React, por exemplo.

Explicação com exemplo de código

  • Objeto

Vamos considerar o seguinte objeto para todos os exemplos:

const person = {
  firstName: "Nick",
  lastName: "Anderson",
  age: 35,
  sex: "M"
}

Sem desestruturação

const first = person.firstName;
const age = person.age;
const city = person.city || "Paris";

Com desestruturação, tudo em uma única linha:

const { firstName: first, age, city = "Paris" } = person; // É isso ! :)

console.log(age) // 35 -- uma nova variável age é criada e é igual a person.age
console.log(first) // "Nick" -- uma nova variável first é criada e é igual person.firstName
console.log(firstName) // ReferenceError -- person.firstName existe MAS a nova variável criada é nomeada primeiro
console.log(city) // "Paris" -- uma nova variável city é criada e uma vez que person.city é indefinida, city é igual ao valor padrão fornecido "Paris".

Nota : Em const { age } = person;, os colchetes depois da palavra-chave const não são usados para declarar um objeto nem um bloco, mas é a sintaxe da desestruturação.

  • Parâmetros de função

Desestruturação é freqüentemente usado para desestruturar parâmetros de objetos em funções.

Sem desestruturação

function joinFirstLastName(person) {
  const firstName = person.firstName;
  const lastName = person.lastName;
  return firstName + '-' + lastName;
}

joinFirstLastName(person); // "Nick-Anderson"

Ao desestruturar o parâmetro de objeto person, obtemos uma função mais concisa:

function joinFirstLastName({ firstName, lastName }) { // criamos variáveis firstName e lastName por desestruturação person parameter
  return firstName + '-' + lastName;
}

joinFirstLastName(person); // "Nick-Anderson"

A desestruturação é ainda mais agradável para usar com [funções de seta] (#função-de-seta):

const joinFirstLastName = ({ firstName, lastName }) => firstName + '-' + lastName;

joinFirstLastName(person); // "Nick-Anderson"
  • Array (Matriz)

Vamos considerar a seguinte array:

const myArray = ["a", "b", "c"];

Sem desestruturação

const x = myArray[0];
const y = myArray[1];

Com desestruturação

const [x, y] = myArray; // É isso !

console.log(x) // "a"
console.log(y) // "b"

Material Útil

CONTINUA…

Créditos do texto Original: Manuel Beaudru ⚡️


Está curtindo os conteúdos da Reativa? Quer que a gente te ajude a ser um dev melhor? Clique aqui.