Javascript moderno: tudo o que você perdeu nos últimos 10 anos

JavaScript percorreu um longo caminho desde que eu o conhecia como a letra "D" em DHTML. Para qualquer um como eu que não quisesse usar a sintaxe mais recente que pode exigir polyfills ou um transpiler, escrevi esta folha de dicas para que você se familiarize com todos os benefícios amplamente suportados nos navegadores modernos.



Contente



  • Funções de array
  • const / let
  • Nullish coalescing ?? e encadeamento opcional? .. operadores
  • Async / Await
  • Funções de seta () => {}
  • para de
  • para aguardar ... de
  • Aulas
  • prepare-se
  • parâmetros padrão da função
  • function named parameters
  • function rest… parameter
  • Destructuring
  • Shorthand functions aka Methods
  • Promise.all
  • Template literals
  • Proxy
  • Module import/export


( , , )





Array functions



Confira todas essas novas funções de array nativas. Não há mais necessidade de sublinhado ou lodash.



Array.every ()

Array.filter ()

Array.find ()

Array.findIndex ()

Array.forEach ()

Array.from ()

Array.includes ()

Array.isArray ()

Array.lastIndexOf ()

Array.map ()

Array.reduce ()

Array.reduceRight ()

Array.some ()



Array docs



const / let



Essas novas palavras-chave declaram variáveis ​​no escopo do bloco (em oposição ao escopo global ou funcional). O uso const



implica que o valor que o valor não deve mudar, mas let



dá essa oportunidade.



Deixe a documentação



?? e?.



??



verifica se um valor é nulo ou indefinido. Não há necessidade de usar mais !!



.



?.



verifica se um valor é verdadeiro antes de chamar a próxima propriedade ou função. Extremamente útil ao lidar com adereços adicionais.



Documentação de encadeamento opcional



let a, b=1
let result = a ?? b
print(result)

result = (a !== null && a !== undefined) ? a : b;
print(result)
      
print({x:1}?.a?.b ?? "not found")
      
      
      







Async / Await



As palavras-chave async / await existem para salvá-lo do inferno de callback. Use await



para fazer com que uma chamada assíncrona pareça uma chamada síncrona, ou seja, a execução await fetchUserName()



não avançará para a próxima linha até que fetchUserName () seja concluído. Observe que, para usar await



, você deve executar uma função declarada como assíncrona, ou seja, async function fn () {await fetchUserName ()}.







Async / Await docs.



function fetchUserName() {
  return new Promise(resolve => setTimeout(resolve, 500))
}
      
async function withAsync() {
  print("withAsync: fetching...")
  await fetchUserName()
  print("withAsync: done")
}
await withAsync()
      
function withoutAsync() {
  print("withoutAsync: fetching...")
  fetchUserName().then(()=>print("withoutAsync done"))
}
withoutAsync()
    
      
      







Funções de seta () => {}



Essas são funções vinculadas ao contexto atual. Existem três tipos principais que você verá na natureza:

um argumento, uma linha, muitas linhas.



Um formulário de argumento único não requer parênteses, e um formulário de linha única não requer um operador return



; retornar incondicional.



1 const fn = a => a*2
      
      







Um argumento. Uma linha.



Um formulário de várias linhas requer uma declaração return



se a função pretende retornar algo. Vários argumentos requerem parênteses.



const fn = (a,b) => {
  console.log(a,b)
  return a*b
}
      
      







Vários argumentos, várias linhas.



Documentos de função de seta



para de



Usado para iterar em um iterador. Da mesma forma for...in



, exceto que você não precisa verificar hasOwnProperty



. Você não pode usar essa sintaxe de loop em um objeto diretamente porque o objeto não tem um iterador. Use Object.entries ({})



para obter a iteração.



para ... de documentos



const x = {a: 1, b: 2}
for (const [key, value] of Object.entries(x)) {
  print(`${key}=${value}`)
}
      
      







para aguardar ... de



A iteração assíncrona foi introduzida em 2018. Além disso Promise.all



, pode ser usado para sincronizar muitas tarefas assíncronas. O exemplo abaixo mostra 3 tarefas em execução de forma assíncrona. O loop processa um resultado de cada vez, em ordem; nesse caso, as tarefas mais rápidas de serem concluídas são evidentes apenas no final da iteração.



para aguardar ... de docs



const delay = (n) => {
  return new Promise((resolve) => {
    setTimeout(()=>{
      print("resolve "+n)
      resolve(n)
    }, n)
  })
}

const delays = [
  delay(150),
  delay(50),
  delay(25)
]

for await (const ret of delays) {
  print("for loop await "+ret)
}
      
      







Aulas



Em 2015, a ES6 portou aulas para Javascript. As aulas de Javascript são como aulas de outras linguagens que você conhece e adora. Herança, métodos de classe, getters e setters, propriedades, etc.



Documentação da aula



class A {
  constructor(name) {
    this.name = name
  }
  myProp = "myProp"
  static foo() {
    print("Static method says foo")
  }
}
class B extends A {
  constructor(name, age) {
    super(name)
    this.age = age
  }
  toString() {
    return `${this.name} ${this.age}`
  }
}
A.foo()
const b = new B("Catch", 22)
print(b)
print(b.myProp)
      
      







prepare-se



Get e set são funções chamadas de propriedades, por exemplo person.age = 16; person.age> 18



. Isso é muito útil quando você precisa de uma propriedade dinâmica ou computada. E eles podem ser usados ​​com classes e objetos regulares.



get / set documentation



Classes com getters e setters

class A {
  constructor() {
    this._firstName = "Jane"
    this._lastName = "Smith"
  }
  get fullName() {
    return `${this._firstName} ${this._lastName}`
  }
  set firstName(v) {
    this._firstName = v
  }
}
const a = new A()
print(a.fullName)
a.firstName = "John"
print(a.fullName)
      
      







Objetos com getters e setters

const x = {
  get now() { return new Date() }
}
print(x.now)
      
      







parâmetros padrão da função



Viva! Agora você pode especificar os parâmetros padrão em sua definição de função. Funciona como você esperaria.



Documentos de parâmetro padrão



function greet(msg="Hello world") {
  print(msg)
}
greet()
greet("hi")
      
      







parâmetros nomeados de função



Por meio da mágica da desestruturação de objetos, as funções agora podem ter parâmetros nomeados.



Documentos de parâmetros nomeados



function greet({name = "Jane", age = 42} = {}){
  print(name + " " +age)
}
greet()
greet({name: "John", age: 21})
      
      







função resto ... parâmetro



O parâmetro reset permite que a função aceite um número arbitrário de argumentos como uma matriz. Recomenda-se usar isso em seu lugar arguments



.



Documentos do parâmetro Rest



function greet(msg1, ...msgs) {
  print(msg1)
  msgs.forEach(s => print(s))
}
greet("hi", "hello", "world")
      
      







Operador Object.assign e spread



Object.assign(target, source)



combina dois ou mais objetos em um. Ele modifica o destino no local, portanto, se você preferir criar um novo objeto, passe um literal de objeto vazio como o primeiro argumento.



Como alternativa, você pode usar o operador spread ...



para combinar vários objetos: {... obj1, ... obj2}



embora tenha em mente que spread



isso não chamará setters em um objeto, portanto, para ser mais portátil, considere Object.assign



. O operador Spread também pode ser usado com matrizes, conforme mostrado no último exemplo de código.



Espalhe documentos de sintaxe



const source = {x: 1, y: 4}
const target = Object.assign({}, source)
print(JSON.stringify(target))

const spread = {a: 1, b: 2, ...source}
print(JSON.stringify(spread))

const ary1 = [1]
const ary = [...ary1, [2,3]]
print(ary)
      
      
      







Destruição



A desestruturação permite que você recupere valores de objetos e matrizes usando modelos. Este é um tópico complexo com muitos aplicativos ... muitos para eu listar, mas mostrei alguns dos usos mais comuns que posso pensar.



Documentos de estruturação e documentos MDN



function f() {
  return [1, 2];
}
let [a, b] = f()
print("a="+a + " b=" + b)

const obj = {state: {id: 1, is_verified: false}}
const {id, is_verified: verified} = obj.state
print("id = " + id)
print("verified = " + verified)

for (const [key, value] of Object.entries({a: 1, b: 2, c: 3})) {
  print(key + " is " + value);
}
      
      
      







Funções abreviadas também conhecidas como métodos



As funções declaradas para objetos podem usar o novo estilo abreviado, que não possui a palavra-chave de função.



As duas funções (fn1, fn2) são equivalentes no exemplo abaixo.



Guia de método



const x = {
  type: "x",
  shorthand() {
    print("shorthand "+this.type)
  },
  long: function() {
    print("long "+this.type)
  }
}
x.shorthand()
x.long()

      
      







Promise.all



Na maioria das vezes, ignorei as promessas porque async / await é preferível, mas às vezes você precisa sincronizar várias chamadas assíncronas e Promise.all é a maneira mais fácil de fazer isso.



Documentação da Promise.all



const delay = (n) => {
  return new Promise((resolve) => {
    setTimeout(()=> resolve(n), n)
  })
}
async function main() {
  const delays = [100, 200, 300].map(n => delay(n))
  print("waiting…")
  const res = await Promise.all(delays)
  print("done. result is " + res)
}
main()
      
      
      







Literais de modelo



Essa nova sintaxe, também conhecida como strings de modelo, fornece interpolação de string simples e strings de várias linhas.



Documentos literais de modelo



let x = `multi
      line
string`
print(x)

x = `1+1=${1+1}`
print(x)
      
      







Proxy



Um proxy permite interceptar chamadas get / set em outro objeto. Isso pode ser útil para rastrear alterações de propriedade, atualizar o DOM posteriormente ou criar APIs inovadoras como o proxy www abaixo. Documentos proxy



imagem







let _nums = [1,2,3]
let nums = new Proxy(_nums, {
  set(target, key, value) {
    target[key] = value
    print("set called with " + key + "=" + value)
    print("update DOM")
    return true
  }
})
nums.push(4)
print("nums: " + nums)
print("_nums: " + _nums)
      
      







Importação / exportação de módulo



Os módulos permitem que você crie um namespace para o seu código e divida a funcionalidade em arquivos menores. No exemplo abaixo, temos um módulo denominado greet.js que está incluído em index.html. Observe que o carregamento do módulo é sempre adiado, portanto, não bloqueia a renderização de HTML. Existem muitas maneiras de importar / exportar funcionalidade de arquivos js, leia a documentação de exportação para obter detalhes .



Importar documentos



function greet(msg) {
  console.log("greet:", msg)
}
export default greet
      
      







Um arquivo chamado "greet.js" no diretório "/ js".



<script type="module">
  import greet from "/js/greet.js"
  greet("hi")
</script>
      
      







index.html



Consulte Mais informação



Portanto, não falei sobre tudo o que mudou na última década, mas apenas sobre o que considero mais útil. Confira esses outros tópicos.



Referências





Guias




All Articles