Arrays
Arrays
EPUB/PDF
17 de noviembre de 2023
Arrays
Los objetos te permiten almacenar colecciones de datos a través de nombres. Eso está bien.
Pero a menudo necesitamos una colección ordenada, donde tenemos un 1ro, un 2do, un 3er
elemento y así sucesivamente. Por ejemplo, necesitamos almacenar una lista de algo:
usuarios, bienes, elementos HTML, etc.
No es conveniente usar objetos aquí, porque no proveen métodos para manejar el orden de
los elementos. No podemos insertar una nueva propiedad “entre” los existentes. Los objetos
no están hechos para eso.
Existe una estructura llamada Array (llamada en español arreglo o matriz/vector) para
almacenar colecciones ordenadas.
Declaración
Hay dos sintaxis para crear un array vacío:
Casi siempre se usa la segunda. Podemos suministrar elementos iniciales entre los corchetes:
1 let fruits = ["Apple", "Orange", "Plum"];
2
3 alert( fruits[0] ); // Apple
4 alert( fruits[1] ); // Orange
5 alert( fruits[2] ); // Plum
1 let fruits = ["Apple", "Orange", "Plum"];
2
3 alert( fruits.length ); // 3
1 let fruits = ["Apple", "Orange", "Plum"];
2
3 alert( fruits ); // Apple,Orange,Plum
1 // mezcla de valores
2 let arr = [ 'Apple', { name: 'John' }, true, function() { alert(
3
4 // obtener el objeto del índice 1 y mostrar su nombre
5 alert( arr[1].name ); // John
6
7 // obtener la función del índice 3 y ejecutarla
8 arr[3](); // hello
Coma residual
Un array, al igual que un objeto, puede tener una coma final:
1 let fruits = [
2 "Apple",
3 "Orange",
4 "Plum",
5 ];
La “coma final” hace más simple insertar y remover items, porque todas la líneas se
vuelven similares.
1 let fruits = ["Apple", "Orange", "Plum"];
2
3 alert( fruits[fruits.length-1] ); // Plum
Un poco engorroso, ¿no es cierto? Necesitamos escribir el nombre de la variable dos veces.
1 let fruits = ["Apple", "Orange", "Plum"];
2
3 // es lo mismo que fruits[fruits.length-1]
4 alert( fruits.at(-1) ); // Plum
En la práctica los necesitamos muy a menudo. Por ejemplo, una cola de mensajes que
necesitamos mostrar en pantalla.
Hay otro caso de uso para los arrays – la estructura de datos llamada pila.
Entonces los elementos nuevos son agregados o tomados siempre desde el “final”.
Una pila es usualmente mostrada como un mazo de cartas, donde las nuevas cartas son
agregadas al tope o tomadas desde el tope:
push
pop
Para las pilas, la última introducida es la primera en ser recibida, en inglés esto es llamado
principio LIFO (Last-In-First-Out, última en entrar primera en salir). Para las colas, tenemos
FIFO (First-In-First-Out primera en entrar, primera en salir).
Los arrays en JavaScript pueden trabajar como colas o pilas. Ellos permiten agregar/quitar
elementos al/del principio o al/del final.
pop
1 let fruits = ["Apple", "Orange", "Pear"];
2
3 alert( fruits.pop() ); // quita "Pear" y lo muestra en un alert
4
5 alert( fruits ); // Apple, Orange
Tanto fruits.pop() como fruits.at(-1) devuelven el último elemento del array, pero
fruits.pop() también modifica el array eliminando tal elemento.
push
1 let fruits = ["Apple", "Orange"];
2
3 fruits.push("Pear");
4
5 alert( fruits ); // Apple, Orange, Pear
shift
1 let fruits = ["Apple", "Orange", "Pear"];
2
3 alert( fruits.shift() ); // quita Apple y lo muestra en un alert
4
5 alert( fruits ); // Orange, Pear
unshift
1 let fruits = ["Orange", "Pear"];
2
3 fruits.unshift('Apple');
4
5 alert( fruits ); // Apple, Orange, Pear
Los métodos push y unshift pueden agregar múltiples elementos de una vez:
1 let fruits = ["Apple"];
2
3 fruits.push("Orange", "Peach");
4 fruits.unshift("Pineapple", "Lemon");
5
6 // ["Pineapple", "Lemon", "Apple", "Orange", "Peach"]
7 alert( fruits );
Interiores
Un array es una clase especial de objeto. Los corchetes usados para acceder a una propiedad
arr[0] vienen de la sintaxis de objeto. Son esencialmente lo mismo que obj[key] ,
donde arr es el objeto mientras los números son usados como claves.
Ellos extienden los objetos proveyendo métodos especiales para trabajar con colecciones
ordenadas de datos y también la propiedad length . Pero en el corazón es aún un objeto.
Recuerde, solo hay ocho tipos de datos básicos en JavaScript (consulte el capítulo Tipos de
datos para obtener más información). Array es un objeto y, por tanto, se comporta como un
objeto.
1 let fruits = ["Banana"]
2
3 let arr = fruits; // copiado por referencia (dos variables refer
4
5 alert( arr === fruits ); // true
6
7 arr.push("Pear"); // modifica el array por referencia
8
9 alert( fruits ); // Banana, Pear - ahora con 2 items
…Pero lo que hace a los array realmente especiales es su representación interna. El motor
trata de almacenarlos en áreas de memoria contigua, uno tras otro, justo como muestra la
ilustración en este capítulo. Hay otras optimizaciones también para hacer que los arrays
trabajen verdaderamente rápido.
Pero todo esto se puede malograr si dejamos de trabajarlos como arrays de colecciones
ordenadas y comenzamos a usarlos como si fueran objetos comunes.
Esto es posible porque los arrays son objetos en su base. Podemos agregar cualquier
propiedad en ellos.
Pero el motor verá que estamos tratándolo como un objeto común. Las optimizaciones
específicas no son aptas para tales casos y serán desechadas, y sus beneficios desaparecerán.
Piensa en los arrays como estructuras especiales para trabajar con datos ordenados. Ellos
proveen métodos especiales para ello. Los arrays están cuidadosamente afinados dentro de
los motores JavaScript para funcionar con datos ordenados contiguos, por favor úsalos de
esa manera. Y si necesitas claves arbitrarias, hay altas chances de que en realidad necesites
objetos comunes {} .
Performance
Los métodos push/pop son rápidos, mientras que shift/unshift son lentos.
unshift pop
0 1 2 3
shift push
¿Por qué es más rápido trabajar con el final del array que con el principio? Veamos qué pasa
durante la ejecución:
"Orange"
"Orange"
"Apple"
"Lemon"
"Lemon"
"Lemon"
"Pear"
"Pear"
"Pear"
length = 4 length = 3
limpiar mover
0 11 2 3 1 2 3 0 1 2
elementos
a la izquierda
Cuanto más elementos haya en el array, más tiempo tomará moverlos, más
operaciones en memoria.
Algo similar ocurre con unshift : para agregar un elemento al principio del array,
necesitamos primero mover todos los elementos hacia la derecha, incrementando sus
índices.
¿Y qué pasa con push/pop ? Ellos no necesitan mover nada. Para extraer un elemento del
final, el método pop limpia el índice y acorta length .
"Orange"
"Apple"
"Lemon"
"Apple"
"Pear"
"Pear"
length = 4 length = 3
limpiar
0 1 2 3 0 1 2
El método pop no necesita mover nada, porque los demás elementos mantienen sus
índices. Es por ello que es muy rápido.
Bucles
Una de las formas más viejas de iterar los items de un array es el bucle for sobre sus
índices:
1 let arr = ["Apple", "Orange", "Pear"];
2
3 for (let i = 0; i < arr.length; i++) {
4 alert( arr[i] );
5 }
Pero para los arrays también hay otra forma de bucle, for..of :
1 let fruits = ["Apple", "Orange", "Plum"];
2
3 // itera sobre los elementos del array
4 for (let fruit of fruits) {
5 alert( fruit );
6 }
Técnicamente, y porque los arrays son objetos, es también posible usar for..in :
1 let arr = ["Apple", "Orange", "Pear"];
2
3 for (let key in arr) {
4
5 alert( arr[key] ); // Apple, Orange, Pear
}
1. El bucle for..in itera sobre todas las propiedades, no solo las numéricas.
Existen objetos “simil-array” en el navegador y otros ambientes que parecen arrays. Esto
es, tienen length y propiedades indexadas, pero pueden también tener propiedades no
numéricas y métodos que usualmente no necesitemos. Y el bucle for..in los listará.
Entonces si necesitamos trabajar con objetos simil-array, estas propiedades “extras”
pueden volverse un problema.
Acerca de “length”
La propiedad length automáticamente se actualiza cuando se modifica el array. Para ser
precisos, no es la cuenta de valores del array sino el mayor índice más uno.
Por ejemplo, un elemento simple con un índice grande da una longitud grande:
1 let fruits = [];
2 fruits[123] = "Apple";
3
4 alert( fruits.length ); // 124
new Array()
Hay una sintaxis más para crear un array:
Es raramente usada porque con corchetes [] es más corto. También hay una característica
peculiar con ella.
Si new Array es llamado con un único argumento numérico, se crea un array sin items,
pero con la longitud “length” dada.
1 let arr = new Array(2); // ¿Creará un array de [2]?
2
3 alert( arr[0] ); // undefined! sin elementos.
4
5 alert( arr.length ); // longitud 2
Para evitar sorpresas solemos usar corchetes, salvo que sepamos lo que estamos haciendo.
Arrays multidimensionales
Los arrays pueden tener items que a su vez sean arrays. Podemos usarlos como arrays
multidimensionales, por ejemplo para almacenar matrices:
1 let matrix = [
2 [1, 2, 3],
3 [4, 5, 6],
4 [7, 8, 9]
5 ];
6
7 alert( matrix[1][1] ); // 5, el elemento central
toString
Los arrays tienen su propia implementación del método toString que devuelve un lista de
elementos separados por coma.
Por ejemplo:
1 let arr = [1, 2, 3];
2
3 alert( arr ); // 1,2,3
4 alert( String(arr) === '1,2,3' ); // true
1 alert( [] + 1 ); // "1"
2 alert( [1] + 1 ); // "11"
3 alert( [1,2] + 1 ); // "1,21"
1 alert( "" + 1 ); // "1"
2 alert( "1" + 1 ); // "11"
3 alert( "1,2" + 1 ); // "1,21"
Este operador no tiene un tratamiento especial para arrays, trabaja con ellas como con
cualquier objeto.
Entonces, si comparamos arrays con == , nunca son iguales, a no ser que comparemos dos
variables que hacen referencia exactamente a la misma array.
Por ejemplo:
1 alert( [] == [] ); // falso
2 alert( [0] == [0] ); // falso
Estas arrays son técnicamente objetos diferentes. Así que no son iguales. El operador == no
hace comparaciones de elemento a elemento.
Comparaciones con primitivos también pueden dar resultados aparentemente extraños:
1 alert( 0 == [] ); // verdadero
2
3 alert('0' == [] ); // falso
Aquí, en ambos casos, comparamos un primitivo con un objeto array. Entonces la array []
se convierte a primitivo para el propósito de comparar y se convierte en una string vacía '' .
1 // después de que [] se convierta en ''
2 alert( 0 == '' ); // verdadero, ya que '' se convierte en el núm
3
4 alert('0' == '' ); // falso, sin conversión de tipos, strings di
Resumen
Los arrays son una clase especial de objeto, adecuados para almacenar y manejar items de
datos ordenados.
La declaración:
● La propiedad length es la longitud del array o, para ser preciso, el último índice
numérico más uno. Se autoajusta al usar los métodos de array.
● Si acortamos length manualmente, el array se trunca.
Podemos usar un array como una pila “deque” o “bicola” con las siguientes operaciones:
● for (let i=0; i<arr.length; i++) – lo más rápido, compatible con viejos
navegadores.
● for (let item of arr) – la sintaxis moderna para items solamente.
● for (let i in arr) – nunca lo uses.
Para comparar arrays, no uses el operador == (como tampoco > , < y otros), ya que no
tienen un tratamiento especial para arrays. Lo manejan como cualquier objeto y no es lo que
normalmente queremos.
En su lugar puedes utilizar el bucle for..of para comparar arrays elemento a elemento.
Volveremos a los arrays y estudiaremos más métodos para agregar, quitar, extraer elementos
y ordenar arrays en el capítulo Métodos de arrays.
Tareas
solución
Operaciones en arrays.
importancia: 5
solución
solución
Ejecutar el demo
solución
Subarray máximo
importancia: 2
La tarea es encontrar, dentro de ’arr’, el subarray de elementos contiguos que tenga la suma
máxima.
Por ejemplo:
Si todos los elementos son negativos, no toma ninguno (el subarray queda vacío) y la suma
es cero:
Comentarios
● Si tiene sugerencias sobre qué mejorar, por favor enviar una propuesta de GitHub
o una solicitud de extracción en lugar de comentar.
● Si no puede entender algo en el artículo, por favor explique.
● Para insertar algunas palabras de código, use la etiqueta <code> , para varias
líneas – envolverlas en la etiqueta <pre> , para más de 10 líneas – utilice una
entorno controlado (sandbox) (plnkr, jsbin, codepen…)
contáctenos