JavaScript moderno: todo lo que te has perdido en los últimos 10 años

JavaScript ha recorrido un largo camino desde que lo conocí como la letra "D" en DHTML. Para cualquiera como yo que no quisiera usar la última sintaxis que podría requerir polyfills o un transpiler, escribí esta hoja de trucos para familiarizarlo con todos los beneficios que son ampliamente compatibles con los navegadores modernos.



Contenido



  • Funciones de matriz
  • const / let
  • ¿Coalescencia nula? y el encadenamiento opcional? .. operadores
  • Async / Await
  • Funciones de flecha () => {}
  • para ... de
  • para esperar ... de
  • Clases
  • obtener / configurar
  • función parámetros predeterminados
  • function named parameters
  • function rest… parameter
  • Destructuring
  • Shorthand functions aka Methods
  • Promise.all
  • Template literals
  • Proxy
  • Module import/export


( , , )





Array functions



Eche un vistazo a todas estas nuevas funciones de matriz nativas. Ya no es necesario el subrayado o 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



Estas nuevas palabras clave declaran variables en el alcance del bloque (a diferencia del alcance global o funcional). El uso const



implica que el valor que el valor no debe cambiar, pero let



da esta oportunidad.



Deje documentación



?? ¿y?.



??



comprueba si un valor es nulo o indefinido. Ya no es necesario usarlo !!



.



?.



comprueba si un valor es verdadero antes de llamar a la siguiente propiedad o función. Extremadamente útil cuando se trata de accesorios adicionales.



Documentación de encadenamiento 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



Las palabras clave async / await están ahí para salvarlo del infierno de devolución de llamada. Úselo await



para hacer que una llamada asíncrona parezca una llamada síncrona, es decir, la ejecución await fetchUserName()



no avanzará a la siguiente línea hasta que se haya completado fetchUserName (). Tenga en cuenta que para usar await



, debe ejecutar una función declarada como asíncrona, es decir, 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()
    
      
      







Funciones de flecha () => {}



Estas son funciones ligadas al contexto actual. Hay tres tipos principales que verá en la naturaleza:

un argumento, una línea, muchas líneas.



Una forma de un solo argumento no requiere paréntesis y una forma de una sola línea no requiere un operador return



; regreso incondicional.



1 const fn = a => a*2
      
      







Un argumento. Una línea.



Un formulario de varias líneas requiere una declaración return



si la función tiene la intención de devolver algo. Varios argumentos requieren paréntesis.



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







Múltiples argumentos, múltiples líneas.



Documentos de la función de flecha



para ... de



Se usa para iterar sobre un iterador. Del mismo modo for...in



, excepto que no es necesario verificar hasOwnProperty



. No puede usar esta sintaxis de bucle en un objeto directamente porque el objeto no tiene un iterador. Úselo Object.entries ({})



para obtener iteración en su lugar .



para ... de docs



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







para esperar ... de



La iteración asincrónica se introdujo en 2018. Además Promise.all



, se puede utilizar para sincronizar muchas tareas asincrónicas. El siguiente ejemplo muestra 3 tareas que se ejecutan de forma asincrónica. El ciclo procesa un resultado a la vez, en orden; en este caso, las tareas más rápidas para completar son evidentes solo al final de la iteración.



a la espera ... de documentos



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)
}
      
      







Clases



En 2015, ES6 transfirió clases a Javascript. Las clases de Javascript son como clases de otros idiomas que conoces y amas. Herencia, métodos de clase, captadores y definidores, propiedades, etc.



Documentación de la clase



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)
      
      







obtener / configurar



Obtener y establecer son funciones llamadas propiedades, por ejemplo person.age = 16; person.age> 18



. Esto resulta muy útil cuando se necesita una propiedad dinámica o calculada. Y se pueden usar tanto con clases como con objetos regulares.



obtener / establecer clases de documentación



con getters y 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 con getters y setters

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







función parámetros predeterminados



¡Hurra! Ahora puede especificar los parámetros predeterminados en la definición de su función. Funciona como era de esperar.



Documentos de parámetros predeterminados



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







función nombrada parámetros



Gracias a la magia de la desestructuración de objetos, las funciones ahora pueden tener parámetros con nombre.



Documentos de parámetros con nombre



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







función resto ... parámetro



El parámetro de reinicio permite que la función acepte un número arbitrario de argumentos como una matriz. Se recomienda utilizar esto en su lugar arguments



.



Documentos de parámetros de descanso



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







Operador de asignación y propagación de objetos



Object.assign(target, source)



combina dos o más objetos en uno. Modifica el destino en su lugar, por lo que si prefiere crear un nuevo objeto, pase un literal de objeto vacío como primer argumento.



Como alternativa, puede utilizar el operador de difusión ...



para combinar múltiples objetos: {... obj1, ... obj2}



a pesar de tener en cuenta que spread



no va a llamar a los emisores en un objeto, así que para ser más portátil, tenga en cuenta Object.assign



. El operador Spread también se puede utilizar con matrices, como se muestra en el último ejemplo de código.



Difundir documentos de sintaxis



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)
      
      
      







Desestructuración



La desestructuración le permite recuperar valores de objetos y matrices usando plantillas. Este es un tema complejo con muchas aplicaciones ... demasiadas para enumerarlas, pero he mostrado algunos de los usos más comunes que se me ocurren.



Desestructurar documentos y 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);
}
      
      
      







Funciones taquigráficas también conocidas como métodos



Las funciones declaradas para objetos pueden usar el nuevo estilo abreviado, que carece de la palabra clave de función.



Las dos funciones (fn1, fn2) son equivalentes en el siguiente ejemplo.



Guía de métodos



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

      
      







Promise.all



En su mayoría, me salté las promesas porque se prefiere async / await, pero a veces es necesario sincronizar múltiples llamadas asincrónicas y Promise.all es la forma más fácil de hacerlo.



Promise.all documentación



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()
      
      
      







Literales de plantilla



Esta nueva sintaxis, también conocida como cadenas de plantilla, proporciona interpolación de cadenas simple y cadenas de varias líneas.



Documentos literales de plantilla



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

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







Apoderado



Un proxy le permite interceptar llamadas get / set en otro objeto. Esto puede resultar útil para realizar un seguimiento de los cambios en las propiedades, actualizar el DOM más adelante o crear API innovadoras como el proxy www a continuación. Documentos de proxy



imagen







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)
      
      







Importación / exportación de módulos



Los módulos le permiten crear un espacio de nombres para su código y dividir la funcionalidad en archivos más pequeños. En el siguiente ejemplo, tenemos un módulo llamado greet.js que se incluye en index.html. Tenga en cuenta que la carga del módulo siempre se aplaza, por lo que no bloquea la representación HTML. Hay muchas formas de importar / exportar la funcionalidad desde archivos js, lea la documentación de exportación para obtener más detalles .



Importar documentos



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







Un archivo llamado "greet.js" en el directorio "/ js".



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







index.html



Lee mas



Entonces, no hablé de todo lo que ha cambiado durante la última década, sino solo de lo que encuentro más útil. Consulte estos otros temas.



Referencias





Guías




All Articles