Sebastian Gomez
🚀 Entendiendo el patrón iterador (Iterator pattern) en Javascript 🚀
En este post aprenderemos cómo implementar el patrón iterador en Javascript 🟨 y en qué situaciones lo podemos usar 💻.
El patrón iterador es uno de los patrones de diseño de software más usado en Javascript y también uno de los más sencillos 😌. Es un patrón de comportamiento, ya que define cómo se comunican objetos entre sí 🔗. De él se extienden importantes aplicaciones que pueden ayudar a definir mejores arquitecturas en aplicaciones web 🌐, por lo que su uso y estudio es altamente recomendado 📚. En este post aprenderemos cómo implementarlo en Javascript y en qué situaciones lo podemos usar.
Empecemos por definir este patrón 📖. Básicamente todos hemos usado arrays de esta forma [1,2,3,4] y usualmente si queremos recorrerlo nos inclinamos rápidamente por usar una estructura cíclica como for o while 🔄, sin embargo esto hace que el código sea un poco más imperativo y menos declarativo, haciendo que no tengamos tanto control con cada dato unitario dentro del arreglo. Desde este punto es donde empieza a cobrar fuerza este patrón iterador 🌀, ya que básicamente lo que nos provee es una manera de recorrer el arreglo de una manera declarativa. El principal principio de este patrón es permitirnos recorrer colecciones de objetos de una manera que podamos decidir cuándo queremos el siguiente objeto y cuándo no 🚦. Para ello, obligatoriamente deben existir tres métodos dentro del iterador:
Empecemos entonces por definir una clase llamada Iterator con estos tres métodos:
// Define la clase "Iterator"
class Iterator {
// Constructor de la clase "Iterator" que acepta un argumento "collection"
constructor(collection) {
// Inicializa la propiedad "index" con el valor 0
this.index = 0;
// Asigna el valor del argumento "collection" a la propiedad "collection" del objeto
this.collection = collection;
}
// Método "first" para obtener el primer elemento de la colección
first() {
// Retorna el primer elemento de la colección (índice 0)
return this.collection[0];
}
// Método "next" para obtener el siguiente elemento de la colección
next() {
// Incrementa el valor de la propiedad "index" en 1
this.index += 1;
// Retorna el elemento de la colección en la posición actual de "index"
return this.collection[this.index];
}
// Método "current" para obtener el elemento actual de la colección
current() {
// Retorna el elemento de la colección en la posición actual de "index"
return this.collection[this.index];
}
}
Como ves, usando ES6 hemos definido una clase que permite hacer operaciones muy básicas sobre el array, pero siempre conservando cuál es el índice sobre el que está la colección en todo momento 📌. Esto nos permitirá fácilmente movernos sobre ella. Adicionalmente, aunque no es obligatorio en la implementación de este patrón, sí es altamente recomendado añadir dos métodos utilitarios más sobre la clase iterador. Estos son:
Veamos entonces cómo sería la implementación:
// Define la clase "Iterator"
class Iterator {
// ...
// Método "reset" para reiniciar el índice del iterador al inicio de la colección
reset() {
// Asigna el valor 0 a la propiedad "index" del objeto
this.index = 0;
}
// Método "hasNext" para verificar si hay un siguiente elemento en la colección
hasNext() {
// Retorna "true" si la longitud de la colección es mayor que el índice actual más uno, de lo contrario, retorna "false"
return this.collection.length > this.index + 1;
}
// ...
}
¡Super simple! 😄 Una vez que tu clase esté definida, puedes usar prácticamente cualquier tipo de array para construir tu iterador y operar sobre él. Veamos un ejemplo de su uso práctico usando un ciclo while:
// Crea una constante "arr" que contiene un array con los números del 1 al 5
const arr = [1, 2, 3, 4, 5];
// Crea una nueva instancia de la clase "Iterator" utilizando el array "arr" como argumento y asigna el objeto resultante a la constante "arrayIterator"
const arrayIterator = new Iterator(arr);
// Imprime en la consola el primer elemento del array utilizando el método "first" del objeto "arrayIterator"
console.log(arrayIterator.first());
// Inicia un bucle "while" que se ejecuta mientras haya un siguiente elemento en el array
while (arrayIterator.hasNext()) {
// Imprime en la consola el siguiente elemento del array utilizando el método "next" del objeto "arrayIterator"
console.log(arrayIterator.next());
}
De esta manera queda totalmente completo el patrón iterador. Como ves, es muy fácil implementar el patrón iterador y su utilidad es casi inmediata 🌟. A continuación, podrás observar todo el código completo de este ejemplo:
// Define la clase "Iterator"
class Iterator {
// Constructor de la clase "Iterator" que acepta un argumento "collection"
constructor(collection) {
// Inicializa la propiedad "index" con el valor 0
this.index = 0;
// Asigna el valor del argumento "collection" a la propiedad "collection" del objeto
this.collection = collection;
}
// Método "first" para obtener el primer elemento de la colección
first() {
// Retorna el primer elemento de la colección (índice 0)
return this.collection[0];
}
// Método "next" para obtener el siguiente elemento de la colección
next() {
// Incrementa el valor de la propiedad "index" en 1
this.index += 1;
// Retorna el elemento de la colección en la posición actual de "index"
return this.collection[this.index];
}
// Método "current" para obtener el elemento actual de la colección
current() {
// Retorna el elemento de la colección en la posición actual de "index"
return this.collection[this.index];
}
// Método "reset" para reiniciar el índice del iterador al inicio de la colección
reset() {
// Asigna el valor 0 a la propiedad "index" del objeto
this.index = 0;
}
// Método "hasNext" para verificar si hay un siguiente elemento en la colección
hasNext() {
// Retorna "true" si el índice actual más uno es menor que la longitud de la colección, de lo contrario, retorna "false"
return this.index + 1 < this.collection.length;
}
}
// Crea una constante "arr" que contiene un array con los números del 1 al 5
const arr = [1, 2, 3, 4, 5];
// Crea una nueva instancia de la clase "Iterator" utilizando el array "arr" como argumento y asigna el objeto resultante a la constante "arrayIterator"
const arrayIterator = new Iterator(arr);
// Imprime en la consola el primer elemento del array utilizando el método "first" del objeto "arrayIterator"
console.log(arrayIterator.first());
// Inicia un bucle "while" que se ejecuta mientras haya un siguiente elemento en el array
while (arrayIterator.hasNext()) {
// Imprime en la consola el siguiente elemento del array utilizando el método "next" del objeto "arrayIterator"
console.log(arrayIterator.next());
}
Eso es todo, espero que este post te sea de utilidad y lo puedas aplicar a algún proyecto que tengas en mente 🧠, y que simplemente te haya ayudado a entender la naturaleza del patrón iterator. Déjame un comentario si lograste implementarlo, si quieres añadir alguna otra funcionalidad o si tienes alguna duda, no dudes en dejarme un comentario en la parte de abajo ⬇️. Recuerda que si te gustó, también puedes compartir usando los links a las redes sociales en la parte de abajo 🌐.
🎯 Conclusiones 🎯
💪 Ejercicios para practicar 💪
🔖 Resumen en 3 puntos 🔖
¡Gracias por leer! Esperamos que esta guía te haya sido útil y te haya proporcionado una comprensión sólida del patrón iterador en Javascript. Si tienes preguntas, comentarios o sugerencias, no dudes en dejar un comentario abajo ⬇️. ¡Buena suerte con tus proyectos y que sigas aprendiendo! 🌈
Creador de contenido principalmente acerca de tecnología.