Responsive Advertisement

JavaScript #13: Iterator design pattern in JavaScript

Welcome back to series about design pattern in JavaScript. This is a link to follow my articles about design pattern in JavaScript topic. Design pattern series.

Table of contents:

  • What is Iterator design pattern?
  • How to implements Iterator design pattern?
  • Pratical application

Let’s go to the content!

What is Iterator design pattern?

Iterator pattern is a behavioral design pattern that lets you traverse elements of a collection without exposing its underlying representation (list, stack, tree, etc, …).

Iterator pattern allows to effectively loop over some collection of objects.

How to implements Iterator design pattern?

We create a Iterator interface which narrates navigation method and a Aggregaate interface which returns the iterator concreate a classes implementing the Aggregate interface will be responsible to implement Iterator interface and use it.

And this is UML class diagram.



Pratical application

We've just gone through theories. We go into practice. We will build an Iterator according to the property, if there are elements, we continue to traverse. We can browse forward and backward at the same time.

Unlike the theory we will create an Iterator function that takes the object to be traversed.

function Iterator(items) {

    this.items = items

    this.index = 0

}

 

This.items is the object we get for browsing. this.index is our pointer, wherever the pointer goes, the element at that position will be traversed.

Next, we define methods to iterate over the elements.

Iterator.prototype = {

    hasNext: function () {

        return this.index < this.items.length

    },

    next: function () {

        return this.items[this.index++]

    },

}

 

We have two methods, hasNext(), to check whether there are elements in the object being traversed. And next() is used to browse the next element.

const arr = [1, NaN, 'alo', function () { }, null, true, false, undefined, { name: 'alaba' }, [1, 0], 'String']

const arrIter = new Iterator(arr)

 

We have an array consisting of many elements of different types such as number, NaN, string, function, object, null, boolean, undefined, array. We create a variable to store the value of the Iterator object.

We'll go through the elements and print them out to see if our function is working.

while (arrIter.hasNext()) {

    console.log(arrIter.next())

}

// => 1, NaN, alo, function arr(), null, true, false, undefined, Object {name: "alaba"}, Array[1, 0], String

 

Awesome! So, we have implemented an Iterator design pattern used to traverse the elements in the object that needs to be traversed.

Now let's upgrade the problem a little bit. We will add two methods, hasPrevious() and previous(), to iterate the elements in the opposite direction.

hasPrevious: function () {

        return this.index > 0

    },

    previous: function () {

        return this.items[--this.index]

    }

 

We will reuse the original object to cycle through the elements. And use serialization methods.

const arr = [1, NaN, 'alo', function () { }, null, true, false, undefined, { name: 'alaba' }, [1, 0], 'String']

const arrIter = new Iterator(arr)

 

console.log(arrIter.next()) // => 1

console.log(arrIter.next()) // => NaN

console.log(arrIter.previous()) // => NaN

console.log(arrIter.previous()) // => 1

 

Great! We can traverse elements in the forward and reverse direction.

Let's go through the analysis of Iterator design pattern.

Pros:

Single Responsibility Principle. You can clean up the client code and the collections by extracting bulking traversal.

Open/Closed Priciple. You can implement new type of collections and iterators and pass them to existing code without breaking anything.

You can iterate over the same collection in parallel because each iterator object contains its own iteration state.

For the same reason, you can delay an iteration and continue it when needed.

Cons

Applying the pattern can be an overkill if your app only works with simple collections.

Using an iterator may be less efficient then going through element of some specialized collections directly.

Conclusion

We just went through the Iterator design pattern in JavaScript. The Iterator pattern is like any other design pattern. It is applicable to large problems that need to traverse difficult and complex objects with algorithms such as DFS, BFS, etc. You might consider applying the Iterator design pattern to large problems.

If you have any ideas feel free to comment below. Thank you for joining with me. Having a good day!


 

Đăng nhận xét

0 Nhận xét