margin-js | kuworking

Gatsby11tyAstro|UnoCSS|SolidJS

Cómo crear arrays en JavaScript

Ojo, este artículo no se ha actualizado desde hace más de 12 meses

Crear arrays en JavaScript es sencillo

const miArray = []
const miArray2 = new Array() // dos formas idénticas de crear un array

Y si queremos crear un array de 10 elementos?

Así no funciona

// así en realidad estamos creando un array con el valor 10
const miArray = [10]

console.log(miArray) // [10]
console.log(miArray.length) // 1

Así estamos creando un array con el valor 10 en su primera y única posición

En su lugar podemos hacer esto

const miArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

console.log(miArray) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(miArray.length) // 10

Pero no querremos hacer esto con un array de 100, en su lugar podríamos hacer esto

const miArray = new Array(100)
const miArray2 = Array(100) // es lo mismo

console.log(miArray) // [undefined, undefined, undefined, undefined ...]
console.log(miArray.length) // 100

Hecho, ya tenemos un array con 100 posiciones

Y si queremos que tengan algún valor dentro?

Podríamos utilizar Array.map

const miArray = Array(100).map((el, i) => {
  console.log(i) // no aparece por ningún lado
  return i
})

console.log(miArray) // [undefined, undefined, undefined, undefined ...]
console.log(miArray.length) // 100

Pero no funciona, porque aunque el array que creamos con Array(100) tiene la propiedad length de 100, en realidad es un array vació y map no tiene nada sobre lo qué iterar

Otro intento con Array.fill

const miArray = Array(100).fill('e')

console.log(miArray) // ["e", "e", "e", "e", "e", ...]
console.log(miArray.length) // 100

Ahora sí, esto funciona

Pero cuidado, si quieres asignar un objeto estarás asignando el mismo objeto

const miArray = Array(100).fill({ status: 'pending' })

console.log(miArray) // [{status: "pending"}, {status: "pending"}, {status: "pending"} ...]
console.log(miArray.length) // 100

miArray[0].status = 'valid'
console.log(miArray) // [{status: "valid"}, {status: "valid"}, {status: "valid"} ...]
// han cambiado todos los estados!

Dependiendo de lo que quieras esto no es lo que buscabas, pero podríamos combinar lo que ya hemos visto

const miArray = Array(100)
  .fill()
  .map((el, i) => i)

console.log(miArray) // [0, 1, 2, 3, 4, 5, 6, 7 ...]
console.log(miArray.length) // 100

Así nos funciona

También podemos hacerlo con Array.from, que vendría a ser lo mismo pero escrito de forma algo distinto

const miArray = Array.from(Array(100), (el, i) => i)

console.log(miArray) // [0, 1, 2, 3, 4, 5, 6, 7 ...]
console.log(miArray.length) // 100

Listos, pero cuál de los dos métodos es mejor?

Si voy a measurethat.net tengo lo siguiente

  • fill().map() 1400K operaciones por segundo
  • from() 300K operaciones por segundo

Es decir, mucho mejor la primera opción, que además a mi me parece la más legible

Pero y si asignamos un objeto? sirven las dos?

const miArray1 = Array(100)
  .fill()
  .map(() => ({ status: 'pending' }))
const miArray2 = Array.from(Array(100), () => ({ status: 'pending' }))

miArray1[0].status = 'valid'
miArray2[0].status = 'valid'
console.log(miArray1) // [{status: "valid"}, {status: "pending"}, {status: "pending"} ...]
console.log(miArray2) // [{status: "valid"}, {status: "pending"}, {status: "pending"} ...]

Sí, sirven los dos

Hay una última alternativa con el operador spread que además resulta ser la más rápida

const miArray1 = Array(100)
  .fill()
  .map((el, i) => i)
const miArray2 = [...Array(100)].map((el, i) => i)

console.log(miArray1) // [0, 1, 2, 3, 4, 5, 6, 7 ...]
console.log(miArray2) // [0, 1, 2, 3, 4, 5, 6, 7 ...]
  • miArray1 1400K operaciones por segundo
  • miarray2 1800K operaciones por segundo