¿Quién conoce
JavaScript?

yo!

¿Quién sufre
JavaScript?

No uses JavaScript

🪦

A mi me encanta.

Os confieso que...

+50 nuevas
features

desde 2015...

¡Hey 👋!

https://midu.tube

https://midu.live

Miguel Ángel Durán

El JavaScript del futuro

¿Cómo evoluciona
JavaScript?

 
debe ser siempre
retrocompatible

y encima evitar...

Antes de 2015

EcmaScript

la receta para crear el lenguaje JavaScript

1995 - se empezó

1997 - se intentó

1998 - se progresó

xxxx - se abandonó por 10 años

2011 - se retomó

2015 - se tomó en serio

Personas expertas y altamente cualificadas de vendors

https://github.com/tc39/proposals

stage 0

stage 1

stage 2

stage 3

Las fases de una propuesta en JavaScript

💬 idea inicial

💡 propuesta

✍️ borrador

📝 candidato

y si no se 💀... entonces...

Nueva funcionalidad

que te va a salvar la vida

https://midu.link/js

¡Vota tus

favoritos!

Clonar Arrays y Objetos

Array y Objetos son referencias

const dynos = ['🦖', '🦕', '🐉']
const fakeCopyDynos = dynos

// cambio el valor del primer elemento en fakeCopyDynos
fakeCopyDynos[0] = '🐓'

// la copia tiene el cambio
console.log(fakeCopyDynos) // -> [ '🐓', '🦕', '🐉' ]

// pero si miramos también el contenido de dynos...
console.log(dynos) // -> [ '🐓', '🦕', '🐉' ]

// ¡sorpresa! nos han colado la 🐓
const dynos = ['🦖', '🦕', '🐉']
const fakeCopyDynos = dynos

console.log(dynos === fakeCopyDynos) // -> true

const arrayWithSameDynos = ['🦖', '🦕', '🐉']
console.log(dynos === arrayWithSameDynos) // -> false

Array y Objetos son referencias

WAT!!!!!!!1!!!

// Crear copias superficiales

const dynos = ['🦖', '🦕', '🐉']
const copyOfDynos = dynos.slice()

const dynos = ['🦖', '🦕', '🐉']
const copyOfDynos = [...dynos]

const dynos = ['🦖', '🦕', '🐉']
const copyOfDynos = Array.from(dynos)

Las copias superficiales son... superficiales...

const dynosAndFriends = ['🦖', '🦕', ['🦎', '🐊']]
const copy = [...dynosAndFriends]

// En el primer elemento del Array anidado ponemos una 🐓
copy[2][0] = '🐓'

// En la copia todo está bien
console.log(copy) // -> [ '🦖', '🦕', [ '🐓', '🐊' ] ]

// ¡Pero en nuestro Array original se ha cambiado también!
console.log(dynosAndFriends) // -> [ '🦖', '🦕', [ '🐓', '🐊' ] ]

"BASTA. DIME CÓMO ARREGLARLO"

JSON Hack

const dynosAndFriends = ['🦖', '🦕', ['🦎', '🐊']]
const dynosAndFriendsString = JSON.stringify(dynosAndFriends)
const copyOfDynosAndFriends = JSON.parse(dynosAndFriendsString)

// para one-liner-lovers 💛
const copyOfDynosAndFriends = JSON.parse(JSON.stringify(dynosAndFriends))
const dynosAndFriends = ['🦖', '🦕', ['🦎', '🐊']]

const cloneArray = items =>
  items.map(item =>
    Array.isArray(item)
      ? cloneArray(item)
      : item
    )

const copyOfDynosAndFriends = cloneArray(dynosAndFriends)

A manija...

import clone from 'just-clone'

let arr = [1, 2, 3]
let subObj = { aa: 1 }
let obj = { a: 3, b: 5, c: arr, d: subObj }
let objClone = clone(obj)

arr.push(4)
objClone.d.bb = 2
obj // {a: 3, b: 5, c: [1, 2, 3, 4], d: {aa: 1}}
objClone // {a: 3, b: 5, c: [1, 2, 3], d: {aa: 1, bb: 2}}

Con dependencias

Todas las soluciones previas tienen problemas

🏴‍☠️ Alguna un poco hacky

❌ Propensas a errores

 

🗓 Copias incompletas

🏋️‍♂️ Impactan la carga de JS

Ven... te enseñaré
a clonar objetos en JS

const dynosAndFriends = ['🦖', '🦕', ['🦎', '🐊']]
const clone = structuredClone(dynosAndFriends)

// En el primer elemento del Array anidado ponemos una 🐓
clone[2][0] = '🐓'

// En el clon está todo bien...
console.log(clone) // -> [ '🦖', '🦕', [ '🐓', '🐊' ] ]

// ¡Y el original sigue estando inalterado!
console.log(dynosAndFriends) // -> [ '🦖', '🦕', [ '🦎', '🐊' ] ]

structuredClone()

structuredClone()

¿Pero esto lo soporta
algún navegador?

structuredClone()

¡Vota tus

favoritos!

Esto no lo ha decidido el

WHATWG

Arrow functions

fetch()

Promises

Métodos de Array

structuredClone()

<img loading="lazy" />

WAT!!!!!!!1!!!

Grandes mejoras
en Arrays

Array Grouping

stage 3

const nums = [1, 2, 3, 4, 5]

// Agrupa los números en un objeto
// Pasándole la key donde debe añadirse
array.group((num, index, array) => {
  return num % 2 === 0 ? 'even': 'odd'
})

// {
//   odd: [1, 3, 5],
//   even: [2, 4]
// }

Change
Array
by copy

stage 3

const sequence = [1, 2, 3]
const reversed = sequence.reverse()
reversed // => [3, 2, 1]
sequence // => [3, 2, 1]

// splice, sort...

Change
Array
by copy

stage 3

const sequence = [1, 2, 3]
sequence.toReversed() // => [3, 2, 1]
sequence // => [1, 2, 3]

const outOfOrder = [3, 2, 1]
outOfOrder.toSorted() // => [1, 2, 3]
outOfOrder // => [3, 1, 2]

const correctionNeeded = [1, 1, 3]
correctionNeeded.with(1, 2) // => [1, 2, 3]
correctionNeeded // => [1, 1, 3]

const input = [5, 4, 3, 2, 1, 0]
toSpliced(input, 2, 2) // [5, 4, 1, 0]
input // [5, 4, 3, 2, 1, 0]

+ programación
funcional

piping

output = input -> func1 -> func2 -> func3
const output = func3(func2(func1(input)))
const title = '3 Trucos de JavaScript'
const toLowerCase = (str) => str.toLowerCase()
const addHyphens = (str) => str.replace(/\s/g, '-')

const slug = addHyphens(toLowerCase(title))
console.log(slug) // -> 3-trucos-de-javascript

const pipe = (...args) => args.reduce((acc, el) => el(acc))
const slug = pipe(title, toLowerCase, addHyphens)
console.log(slug) // -> 3-trucos-de-javascript

Pipeline
Operator

stage 2

const title = '3 Trucos de JavaScript'
const toLowerCase = (str) => str.toLowerCase()
const addHyphens = (str) => str.replace(/\s/g, '-')

const output = title |> toLowerCase(%) |> addHyphens(%)

const output = title
  |> toLoweCase(%)
  |> addHyphens(%)

Pipeline
Operator

stage 2

// ahora...
return filter(obj, negate(cb(predicate)), context)

// en el futuro...
return cb(predicate)
  |> negate(%)
  |> filter(obj, %, context);

Pipeline
Operator

stage 2

console.log(
  chalk.dim(
    `$ ${Object.keys(envars)
      .map(envar => `${envar}=${envars[envar]}`)
      .join(' ')}`,
    'node',
    args.join(' ')
  )
)

Pipeline
Operator

stage 2

Object.keys(envars)
  .map(envar => `${envar}=${envars[envar]}`)
  .join(' ')
  |> `$ ${%}`
  |> chalk.dim(%, 'node', args.join(' '))
  |> console.log(%);

¡Nuevos tipos primitivos!

String, Number, Boolean,
null, undefined, BigInt, Symbol

Inmutables

Los que tenemos ahora...

const obj1 = { a: 'midu' }
const obj2 = { a: 'midu' }

obj1 === obj2 // false

const m = [1, 2, 3]
const n = [1, 2, 3]

m === n // false

Pero los objetos...

Records & Tuples

Records
& Tuples

stage 3

const r1 = #{ a: 'midu' }
const r2 = #{ a: 'midu' }

r1 === r2 // true

const t1 = #[1, 2, 3]
const t2 = #[1, 2, 3]

t1 === t2 // true

Records
& Tuples

stage 3

const persona = #{
  name: 'Miguel',
  aka: #['midudev', 'midu', 'midudog']
}

persona === #{
  name: 'Miguel',
  aka: #['midudev', 'midu', 'midudog']
} // -> true

¡Igualdad profunda!

#

Cositas a tener en cuenta

1. Sólo funciona

con tipos primitivos

Records
& Tuples

stage 3

const proposal = #{
  id: 777,
  title: "Propuesta Record & Tuple",
  contents: `...`,
  // Tuplas son primitivos,
  // así que puedes usarlos
  keywords: #[
    "ecma",
    "tc39",
    "proposal",
    "record",
    "tuple"
  ],
};

Records
& Tuples

stage 3

const chile = {
  name: 'JSConf Chile',
  puntuacion: 100
}

const conferencias = #[
  chile, // TypeError
]

2. Son inmutables

Records
& Tuples

stage 3

const persona = #{
  name: 'Miguel',
  aka: #['midudev', 'midu', 'midudog']
}

persona.name = 'Miguel Ángel'
 
// TypeError: Cannot assign to read
// only property 'name'

Records
& Tuples

stage 3

const persona = #{
  name: 'Miguel',
  aka: #['midudev', 'midu', 'midudog']
}

const newPersona = #{
  ...persona,
  name: 'Miguel Ángel'
}

console.log(newPersona)

TypeScript

¿en JavaScript?

Type
Annotations

Type
Annotations

stage 1

let x: string

x = "hello"

x = 100

function equals(x: number, y: number): string {
  return x === y
}

Básicamente
se ignoran los tipos

Y el futuro que
yo le veo a esto...

"

 La experiencia del pasado, si no cae en el olvido, sirve de guía para el futuro.

La galleta de la fortuna
que me comí ayer

 

Temporal

let now = Temporal.Now.instant()
let checkDate = Temporal.PlainDate.from({
    year: 2022,
    month: 03,
    day: 28
})

// Devuelve true al comparar fechas
Temporal.PlainDate.compare(now, checkDate)

// Y muchas más APIs...

Temporal

stage 3

Temporal

new Date()

🔪

💀

🤩

Vuestros votos...

Aprende JavaScript

gratis y de forma práctica

https://aprendejavascript.dev

¡Gracias!

https://midu.tube

https://midu.live

@midudev

El JavaScript del Futuro

By Miguel Angel Durán García

El JavaScript del Futuro

  • 265